一段没有被使用的rust代码

Written by: algebnaly

Date: 2026-02-12T09:10:51.000Z

在LLM的辅助下, 编写了如下的复杂rust代码, 像黑魔法一样, 最后我还是选择从实际的代码库中删去了它, 因为太难懂了, 放在这篇博客里留作纪念.

写得这么复杂的原因是我希望这段代码可以尽量通用, 输入可以是&str, 可以是bytes或者什么其他任何满足约束的类型。

pub struct Keywords<'a, T: ?Sized + 'a, const N: usize> {
    keywords: [&'a T; N],
}

impl<'a, T: ?Sized + 'a, const N: usize> Keywords<'a, T, N> {
    pub fn new(keywords: [&'a T; N]) -> Self {
        Keywords { keywords }
    }
}

impl<'a, I, T, const N: usize> Parser<I> for Keywords<'a, T, N>
where
    T: ?Sized + 'a,
    I: Input + Compare<&'a T>,
    &'a T: Input + Clone,
    <I as Input>::Item: AsChar,
{
    type Output = ();
    type Error = nom::error::Error<I>;

    fn process<OM: nom::OutputMode>(
        &mut self,
        mut input: I,
    ) -> nom::PResult<OM, I, Self::Output, Self::Error> {
        if N == 0 {
            return Ok((input, OM::Output::bind(|| ())));
        }

        let (rest, _) = multispace0.process::<OM>(input)?;
        input = rest;

        let (rest, _) = tag(self.keywords[0]).process::<OM>(input)?;
        input = rest;

        for i in 1..N {
            let (rest, _) = multispace1.process::<OM>(input)?;
            input = rest;
            let (rest, _) = tag(self.keywords[i]).process::<OM>(input)?;
            input = rest;
        }

        Ok((input, <OM::Output as Mode>::bind(|| ())))
    }
}

pub fn keywords<'a, T: ?Sized + 'a, const N: usize>(kws: [&'a T; N]) -> Keywords<'a, T, N> {
    Keywords::new(kws)
}

这段代码的作用实际上非常简单, 就是创建一个parser, 用来吃掉给定的关键词序列, 并返回一个空元组。关键词序列的开头可以是一个或多个空格, 关键词之间至少被一个空格划分。 这里的主要困难是搞懂nom的OutputMode, 以及I, T这几个泛型参数各自代表什么, 各个parser对参数的约束之类的。 返回值使用<OM::Output as Mode>::bind(|| ())是因为nom 为了支持Emit和Check两种输出模式, Emit模式下会产生一个值, 所有bind中的闭包会被调用, 产生实际的输出.Check模式下可能不会调用闭包, 编译器可以进行性能优化。