我正在用Rust编写一个解析器,并向char添加了一些快捷函数,用于创建特定的单字符标记:

impl CharToToken for char {
    fn to_token(&self, pos: usize) -> Token {
        match *self {
            '{' => Token {
                token_type: TokenType::CurlyBraceOpen,
                span: (pos, pos),
                text: "{",
            },
            '}' => Token {
                token_type: TokenType::CurlyBraceClose,
                span: (pos, pos),
                text: "}",
            },
            ';' => Token {
                token_type: TokenType::SemiColon,
                span: (pos, pos),
                text: ";",
            },
            _ => panic!("Can't create a token from char {:?}", self),
        }
    }
}

这里的预期用例只是为了节省一些打字时间.而不是写:

tokens.push(Token {
    token_type: TokenType::CurlyBraceOpen,
    span: (cursor, cursor),
    text: "{",
})

我可以只写:

tokens.push('{'.to_token(cursor));

这里唯一的缺点是,类型系统并不能使我免于编写'X'.to_token(123)和使应用程序崩溃,而且我真的不想返回Result,从而使我的逻辑更加冗长.我宁愿类型系统从一开始就阻止我写错东西.

有没有办法指示编译器,这个函数应该只在字符文字'{''}'';'上调用,而不是允许任何char

推荐答案

您可以使用常量泛型来实现这一点,但它有点冗长.

fn main() {
    ToToken::<'{'>::to_token(0);
}

struct ToToken<const C: char>;
impl ToToken<'{'> {
    fn to_token(pos: usize) -> Token {
        Token {
            token_type: TokenType::CurlyBraceOpen,
            span: (pos, pos),
            text: "{",
        }
    }
}

执行和调用可以用宏来缩短.

但是,您已经有了在TokenType中列出的所有有效令牌,所以我将改用它:

TokenType::CurlyBraceOpen.to_token(cursor);

Rust相关问答推荐

如何在Rust中为具有多个数据持有者的enum变体编写文档 comments ?

将此字符串转换为由空格字符分隔的空格

什么样的 struct 可以避免使用RefCell?

下载压缩文件

从Type::new()调用函数

Gtk4-rs:将监视器作为gdk::monitor获取,而不是作为glib::对象获取

在我的Cargo 中,当我在建筑物中使用时,找不到我可以在产品包中使用的 crate .r我如何解决这个问题?

不能在一个代码分支中具有不变的自身borrow ,而在另一个代码分支中具有可变的self borrow

如何在Rust中缩短数组

链表堆栈溢出

Rust面向对象设计模式

Cargo.toml:如何有条件地启用依赖项功能?

如何在 Rust 中编写一个通用方法,它可以接受任何可以转换为另一个值的值?

Rust Axum 框架 - 解包安全吗?

如何在Rust中使用Serde创建一个自定义的反序列化器来处理带有内部标记的枚举

在1.5n次比较中找到整数向量中的最大和次大整数

错误:将自定义 proc_macro 与用Rust 的宝贝编写的属性一起使用时,无法在此范围内找到属性

从 Axum IntoResponse 获取请求标头

如何在 Rust 中编写涉及异步的重试函数

在使用大型表达式时(8k 行需要一小时编译),是否可以避免 Rust 中的二次编译时间?