Repository: typst/typst
File: crates/typst-macros/src/symbols.rs (Rust)

Code before:
        } else {
            if !handler.is_none() {
                return Err(input.error("unexpected handler"));
            }
            let content;
            syn::bracketed!(content in input);
            Ok(Self::Multiple(Punctuated::parse_terminated(&content)?))
        }
    }
}

impl Parse for Variant {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut name = String::new();
        let handler = input.parse::<Handler>()?;
        if input.peek(syn::Ident::peek_any) {
            name.push_str(&input.call(Ident::parse_any)?.to_string());
            while input.peek(Token![.]) {
                input.parse::<Token![.]>()?;
                name.push('.');
                name.push_str(&input.call(Ident::parse_any)?.to_string());
            }
            if name == "self" && !handler.is_none() {
                return Ok(Self {
                    name: "".to_string(),
                    c: LitChar::new('\0', Span::call_site()),
                    handler,
                });
            }
            input.parse::<Token![:]>()?;
        }
        let c = input.parse()?;
        Ok(Self { name, c, handler })
    }
}

impl Handler {
    fn is_none(&self) -> bool {
        matches!(self, Self::None)
    }
}

impl Parse for Handler {
    fn parse(input: ParseStream) -> Result<Self> {
        let Ok(attrs) = input.call(syn::Attribute::parse_outer) else {
            return Ok(Self::None);
        };
        let handler = attrs
            .iter()
            .find_map(|attr| {
                if attr.path().is_ident("call") {

Review comment (suggestion):
If I use `floor` directly as a symbol / cast it to a string, do I get the null-terminator? That would be a bit of a problem.

Code after:
            }
            let content;
            syn::bracketed!(content in input);
            Ok(Self::Multiple(Punctuated::parse_terminated(&content)?))
        }
    }
}

impl Parse for Variant {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut name = String::new();
        let handler = input.parse::<Handler>()?;
        if input.peek(syn::Ident::peek_any) {
            name.push_str(&input.call(Ident::parse_any)?.to_string());
            while input.peek(Token![.]) {
                input.parse::<Token![.]>()?;
                name.push('.');
                name.push_str(&input.call(Ident::parse_any)?.to_string());
            }
            input.parse::<Token![:]>()?;
        }
        let c = input.parse()?;
        Ok(Self { name, c, handler })
    }
}

impl Parse for Handler {
    fn parse(input: ParseStream) -> Result<Self> {
        let Ok(attrs) = input.call(syn::Attribute::parse_outer) else {
            return Ok(Self(None));
        };
        let handler = attrs
            .iter()
            .find_map(|attr| {
                if attr.path().is_ident("call") {
                    if let Ok(path) = attr.parse_args::<Path>() {
                        return Some(Self(Some(path)));
                    }
                }
                None
            })
            .unwrap_or(Self(None));
        Ok(handler)
    }
}