#枚举 #方法 # #文件系统 #写入文件 #实现块

impl-enum

使枚举使用类似于特质的对象更加方便的宏

4个版本 (2个破坏性更新)

0.3.1 2023年11月7日
0.3.0 2022年8月18日
0.2.0 2020年12月4日
0.1.0 2020年7月29日

#17#实现块

Download history 500/week @ 2024-04-08 400/week @ 2024-04-15 458/week @ 2024-04-22 315/week @ 2024-04-29 397/week @ 2024-05-06 344/week @ 2024-05-13 516/week @ 2024-05-20 414/week @ 2024-05-27 378/week @ 2024-06-03 408/week @ 2024-06-10 482/week @ 2024-06-17 512/week @ 2024-06-24 181/week @ 2024-07-01 371/week @ 2024-07-08 384/week @ 2024-07-15 296/week @ 2024-07-22

每月1,245次下载
luthien使用

MPL-2.0 许可协议

18KB
213 代码行

impl-enum

Crates.io docs.rs Crates.io GitHub

包含proc macro属性with_methodsas_dyn,使枚举使用类似于特质的对象更加方便。

使用案例

当某些值的具体类型依赖于运行时条件时,特质对象或为每个具体类型提供变体的枚举是最自然的选择,每种选择都有其优缺点。使用枚举的一个缺点是使用起来可能不方便。如果你想要使用不能转换为特质对象的类型,或者在与其他crate中定义的类型和特质一起工作时,特质对象方法也可能存在问题。这个crate旨在使这样的枚举更容易使用。

with_methods

//! The variant of the writer is dynamically selected with an environment variable.
//! Using the macro, we can use the enum with the convenience of a trait object.

use std::{
    env,
    fs::File,
    io::{Cursor, Write},
};

#[impl_enum::with_methods {
    fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()>
    pub fn write(&mut self, buf: &[u8]) -> std::io::Result<usize>
}]
pub enum Writer {
    Cursor(Cursor<Vec<u8>>),
    File { file: File },
}

fn get_writer() -> Writer {
    if let Ok(path) = env::var("WRITER_FILE") {
        Writer::File {
            file: File::create(path).unwrap(),
        }
    } else {
        Writer::Cursor(Cursor::new(vec![]))
    }
}

fn main() {
    let mut writer = get_writer();
    writer.write_all(b"hello!").unwrap();
}

该宏生成与以下等效的实现块

impl Writer {
    fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
        match self {
            Self::Cursor(first, ..) => first.write_all(buf),
            Self::File { file, .. } => file.write_all(buf),
        }
    }
    pub fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        match self {
            Self::Cursor(first, ..) => first.write(buf),
            Self::File { file, .. } => file.write(buf),
        }
    }
}

as_dyn

//! The variant of the writer is dynamically selected with an environment variable.
//! Using the macro, we can conveniently turn the enum into a trait object when necessary.

use std::{
    fmt::Debug,
    fs::File,
    io::{Cursor, Write},
};

#[impl_enum::as_dyn(Debug, Write)]
pub enum Writer {
    Cursor(Cursor<Vec<u8>>),
    File { file: File },
}

fn get_writer() -> Writer {
    if let Ok(path) = std::env::var("WRITER_FILE") {
        Writer::File {
            file: File::create(path).unwrap(),
        }
    } else {
        Writer::Cursor(Cursor::new(vec![]))
    }
}

fn main() {
    let mut writer = get_writer();

    let dyn_debug = writer.as_dyn_debug();
    println!("{:?}", dyn_debug);

    let dyn_writer_mut = writer.as_dyn_write_mut();
    dyn_writer_mut.write_all(b"hello!").unwrap();

    let box_dyn_debug = writer.into_dyn_debug();
    println!("{:?}", box_dyn_debug);
}

该宏生成与以下等效的实现块

impl Writer {
    fn as_dyn_write(&self) -> &dyn Write {
        match self {
            Self::Cursor(first, ..) => first as &dyn Write,
            Self::File { file, .. } => file as &dyn Write,
        }
    }
    fn as_dyn_write_mut(&mut self) -> &mut dyn Write {
        match self {
            Self::Cursor(first, ..) => first as &mut dyn Write,
            Self::File { file, .. } => file as &mut dyn Write,
        }
    }
    fn into_dyn_write(self) -> Box<dyn Write> {
        match self {
            Self::Cursor(first, ..) => Box::new(first) as Box<dyn Write>,
            Self::File { file, .. } => Box::new(file) as Box<dyn Write>,
        }
    }
}

替代方案

许可协议

根据Mozilla公共许可证版本2.0授权。

依赖关系

~0.3–0.8MB
~19K SLoC