#mut #proc-macro #generate #methods #identifier #version #non-mut

mwt

用于生成不重复代码的mut和非mut方法的进程宏

7 个不稳定版本 (3 个破坏性更新)

0.4.3 2022年7月28日
0.4.2 2022年7月28日
0.4.1 2022年5月10日
0.3.0 2021年12月24日
0.1.0 2021年12月24日

501过程宏

MIT 许可证

18KB
250

mwt

嘿!你!在使用前阅读此内容!

mwt是为了个人使用而迅速拼凑起来的,因为我找不到一个现有的crate可以做到这一点。

我已经使用它几个月了,还没有遇到任何重大问题,但可能存在一些错误。

肯定有一些边缘情况还没有被考虑,错误信息也比较糟糕。

随着我使用它并修复我发现的问题,它应该会得到改善,但“买者自慎”或其他什么


在不重复代码的情况下生成相同函数的mut和非mut版本!

mwt提供了两个基本相同的宏:mwtmaybe_mut

  • mwt 在标识符中寻找 mwt,并寻找类似 &Mwt<T> 的类型
  • maybe_mutmaybe_mut&MaybeMut<T> 做同样的事情

它们都允许你在块之前放置 #[if_mut]#[not_mut] 来有条件地包含部分。

它们还有分别对应的 mwt()maybe_mut() 函数,用于类似 return &mwt(self.0) 的操作。

两者都允许您传递一个参数 ignore_self,例如:#[mwt::maybe_mut(ignore_self)] 以阻止 mwt 修改 &self(或 &mut self)参数。从 &mut self 中移除 mut 是默认行为,因为取 &T<self> 会导致解析错误,而且在大多数情况下,这是期望的行为(至少在我的用例中)。

目前尚无处理形式为 _ref/_mut 的函数的方法,但将来可能会添加(可能是 rwf,它将变为 refmut?)

*这不是一个函数,但过程宏会像函数调用一样寻找它的使用

示例

mwt 允许您编写

use mwt::mwt;

struct SomeStruct {
    a_vector: Vec<SomeStruct>,
}

impl SomeStruct {
    #[mwt]
    fn my_mwt_accessor(&mut self) -> &Mwt<SomeStruct> {
        let mut a = 0;
        a = a + 1;
        let b = &mwt(a);
        #[if_mut] {
            println!("Hello from my_mut_accessor()!");
        }
        #[not_mut] {
            println!("Hello from my_accessor()!");
        }
        self.a_vector.get_mwt(0).unwrap()
    }
}

这将生成两个函数

impl SomeStruct {
    fn my_accessor(&self) -> &SomeStruct {
        let mut a = 0;
        a = a + 1;
        let b = &a;
        println!("Hello from my_accessor()!");
        self.a_vector.get(0).unwrap()
    }
    fn my_mut_accessor(&mut self) -> &mut SomeStruct {
        let mut a = 0;
        a = a + 1;
        let b = &mut a;
        println!("Hello from my_mut_accessor()!");
        self.a_vector.get_mut(0).unwrap()
    }
}

如何使用

例如:

#[mwt::mwt]
fn my_mwt_method(&'a mut self, other_param: i32) -> &Mwt<bool> {
    #[if_mut] {
        //code for only the mut version of the function
        let i = 0;
    }
    #[not_mut] {
        // code for only the non-mut version of the function
        let i= 1;
    }
    // do something with i
    self.get_mwt_flag_by_index(i)
}

基本上,编写您函数的可变版本,但对于标识符,将 mut 替换为 mwt,对于类型,将 &mut T 替换为 &Mwt<T>

您还可以在类型中使用 Mwt,例如 MyMwtType 变为 MyMutTypeMyType

或者,如果您觉得更易读,可以使用 mwt::maybe_mut。示例

#[mwt::maybe_mut]
pub fn get_maybe_mut<T: 'static + Component>(&mut self) -> Option<&MaybeMut<T>> {
    // use #[if_mut]{} and #[not_mut]{} for conditional behavior
    //      or for cases where mwt isn't powerful enough yet
    //      like .as_ref() vs .as_mut()
    #[if_mut] { println!("if_mut"); }
    #[not_mut] { println!("not_mut"); }
    //   use &MaybeMut<T> for &mut types
    let map: &MaybeMut<HashMap<TypeId,Box<dyn Component>>>
    //    and &maybe_mut(...) for taking mut references
            = &maybe_mut(self.components);
    // use _maybe_mut_ in function calls, etc.
    map.get_maybe_mut(&TypeId::of::<T>())
        .and_then(|c| c.cast_maybe_mut::<T>())
}

生成两个函数

pub fn get_<T: 'static + Component>(& self) -> Option<&T> {
    println!("not_mut"); 
    let map: &HashMap<TypeId,Box<dyn Component>> = &self.components;
    map.get(&TypeId::of::<T>()).and_then(|c| c.cast::<T>())
}
pub fn get_mut<T: 'static + Component>(&mut self) -> Option<&mut T> {
    println!("if_mut");
    let map: &mut HashMap<TypeId,Box<dyn Component>> = &mut self.components;
    map.get_mut(&TypeId::of::<T>()).and_then(|c| c.cast_mut::<T>())
}

它实际上做了什么?

mwt::mwt基本上只是将函数替换为两个副本(即非可变和可变版本),并在这些副本上执行一些操作

  • 将所有类型引用,如 &Mwt<T>,替换为 &T&mut T 分别
  • 将所有 mwt(expr) 替换为 exprmut expr 分别
  • 对于函数的非可变版本
    • 它取找到的所有标识符,删除任何以 "mwt_" 开头和以 "_mwt" 结尾的部分,并将 "_mwt_" 替换为 "_"
    • 它取找到的所有类型,删除任何 "Mwt" 实例
  • 对于函数的可变版本
    • 它取找到的所有标识符,将任何 "mwt" 实例替换为 "mut"
    • 它取找到的所有类型,将任何 "Mwt" 实例替换为 "Mut"
  • 为了允许行为有其他差异的方式,mut版本移除任何#[not_mut]{...}的出现,而非mut版本移除任何#[if_mut]{...}的出现(未被移除的会移除花括号,请注意这一点)
  • 为了允许不同类型,MwtAlt<First, Second>在mut和非mut版本中分别被替换为FirstSecond

mwt::maybe_mut只是字符串不同,含义相同。(Mwt -> MaybeMutmwt -> maybe_mutMwtAlt -> MutOrElse


发现了bug?需要功能?

请提交一个问题或发送一个pull request!

依赖项

~1.5MB
~35K SLoC