Skip to content

Idea: render_to helper #480

@nanoqsh

Description

@nanoqsh

What if the library provided a helper like this for implementing Render?

pub fn render_to<F>(f: F) -> impl maud::Render
where
    F: Fn(&mut String),
{
    struct Render<F>(F);

    impl<F> maud::Render for Render<F>
    where
        F: Fn(&mut String),
    {
        fn render_to(&self, buffer: &mut String) {
            (self.0)(buffer);
        }
    }

    Render(f)
}

This would simplify implementing Render for custom types.
As an example, let's look at custom date formatting with localization parameters:

pub struct Date { day: u8, month: Month, year: i32 }

impl Date {
    pub fn render(self, local: &Local, lang: Lang) -> impl maud::Render {
        struct Render<'local>(Date, &'local Local, Lang);

        impl maud::Render for Render<'_> {
            fn render_to(&self, buffer: &mut String) {
                let Self(Date { day, month, year }, local, lang) = self;
                let month_name = local.month_short_name(*month, *lang).unwrap_or_else(|| {
                    eprintln!("unknown month {month} for lang {lang}!");
                    "nul"
                });

                _ = write!(buffer, "{day} {month_name} {year}");
            }
        }

        Render(self, local, lang)
    }
}

With the proposed helper, the implementation becomes much shorter and more ergonomic:

impl Date {
    pub fn render(self, local: &Local, lang: Lang) -> impl maud::Render {
        let Self { day, month, year } = self;
        let month_name = local.month_short_name(month, lang).unwrap_or_else(|| {
            eprintln!("unknown month {month} for lang {lang}!");
            "nul"
        });

        render_to(move |buffer| _ = write!(buffer, "{day} {month_name} {year}"))
    }
}

What do you think about this idea - does it seem useful?

Alternatively, you can use the display helper, but the Display implementation would be just as verbose.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions