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

Code before:
            }
        }
    });

    let Elem { ident, .. } = element;

    quote! {
        impl #foundations::Fields for #ident {
            type Enum = Fields;

            fn has(&self, id: u8) -> bool {
                let Ok(id) = Fields::try_from(id) else {
                    return false;
                };

                match id {
                    #(#has_arms,)*
                    _ => false,
                }
            }

            fn field(&self, id: u8) -> Result<#foundations::Value, #foundations::FieldAccessError> {
                let id = Fields::try_from(id)?;
                match id {
                    #(#field_arms,)*
                    _ => Err(#foundations::FieldAccessError::Internal),
                }
            }

            fn field_with_styles(&self, id: u8, styles: #foundations::StyleChain) -> Result<#foundations::Value, #foundations::FieldAccessError> {
                let id = Fields::try_from(id)?;
                match id {
                    #(#field_with_styles_arms,)*
                    _ => Err(#foundations::FieldAccessError::Internal),
                }
            }

            fn field_from_styles(id: u8, styles: #foundations::StyleChain) -> Result<#foundations::Value, #foundations::FieldAccessError> {
                let id = Fields::try_from(id)?;
                match id {
                    #(#field_from_styles_arms,)*
                    _ => Err(#foundations::FieldAccessError::Internal),
                }
            }

            fn materialize(&mut self, styles: #foundations::StyleChain) {
               #(#materializes)*
            }

            fn fields(&self) -> #foundations::Dict {
                let mut fields = #foundations::Dict::new();

Review comment (bug):
The `None` in these functions can also indicate that the field doesn't exist because depending on the function the matchers above aren't exhausive. If you try `#hide[].hidden` for instance, then you'll get the "this is a bug" message. I think we can just return `MissingField` and remove `Internal`.

Code after:
            }
        }
    });

    let Elem { ident, .. } = element;

    let result = quote! {
        Result<#foundations::Value, #foundations::FieldAccessError>
    };

    quote! {
        impl #foundations::Fields for #ident {
            type Enum = Fields;

            fn has(&self, id: u8) -> bool {
                let Ok(id) = Fields::try_from(id) else {
                    return false;
                };

                match id {
                    #(#has_arms,)*
                    _ => false,
                }
            }

            fn field(&self, id: u8) -> #result {
                let id = Fields::try_from(id)?;
                match id {
                    #(#field_arms,)*
                    // This arm might be reached if someone tries to access an
                    // internal field.
                    _ => Err(#foundations::FieldAccessError::Unknown),
                }
            }

            fn field_with_styles(&self, id: u8, styles: #foundations::StyleChain) -> #result {
                let id = Fields::try_from(id)?;
                match id {
                    #(#field_with_styles_arms,)*
                    // This arm might be reached if someone tries to access an
                    // internal field.
                    _ => Err(#foundations::FieldAccessError::Unknown),
                }
            }

            fn field_from_styles(id: u8, styles: #foundations::StyleChain) -> #result {
                let id = Fields::try_from(id)?;
                match id {
                    #(#field_from_styles_arms,)*
                    // This arm might be reached if someone tries to access an
                    // internal field.