Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: allow deriving Template on enums #666

Closed
tema3210 opened this issue Apr 17, 2022 · 7 comments
Closed

Suggestion: allow deriving Template on enums #666

tema3210 opened this issue Apr 17, 2022 · 7 comments

Comments

@tema3210
Copy link

tema3210 commented Apr 17, 2022

Restrictions: Each enum variant should be tuple like with exactly one variant, wrapped type of each variant should implement Template
Semantics: While useless for top level pages(??), it may be handy for component templates:

  • we make dispatch for template components automatic;
  • their enumeration easy
  • when one wants to render one of many variants of template, currently others still need to be initialized resulting in waste of memory as well as the need to fill unused variants somehow (hello Option and template level matching)

Consider:

#[derive(Template)]
enum OrderStatus {
  Arrived(ArrivedOrder),
  Delivery(DeviveryOrder),
  PendingConfirmation(ConfirmOrder)
}

Isn't that nice?

Edit: removed pointless annotation

@djc
Copy link
Collaborator

djc commented Apr 18, 2022

So what would order_status.html look like in this case?

@tema3210
Copy link
Author

So what would order_status.html look like in this case?

Indeed, it's unnecessary.

@djc
Copy link
Collaborator

djc commented Apr 19, 2022

So basically this is kind of a generic derive that forwards to the trait implementation for the unit variant's nested type? I guess other crates already provide something like that...

@Kijewski
Copy link
Collaborator

Kijewski commented Apr 19, 2022

I would lose the single element requirement, and would turn your example

#[derive(Template)]
#[template(path = "hello.html")]
enum OrderStatus {
    Arrived(<elements...>),
    Delivery(<elements...>),
    PendingConfirmation { <elements...> },
}

into:

const _: () = {
    impl Template for OrderStatus {
        fn render(&self) -> Result<String> {
            match self {
                Arrived(_) => {
                    Template_Arrived(<elements...>).render()
                },
                Delivery(<elements...>) => {
                    Template_Delivery(<elements...>).render()
                },
                PendingConfirmation(<elements...>) => {
                    Template_PendingConfirmation(<elements...>).render()
                },
            }
        }

        fn render_into(&self, writer: &mut impl Write + ?Sized) -> Result<()> {
            match self {
                Arrived(<elements...>) => {
                    Template_Arrived(<elements...>).render_into(writer)
                },
                Delivery(<elements...>) => {
                    Template_Delivery(<elements...>).render_into(writer)
                },
                PendingConfirmation { <elements...> } => {
                    Template_PendingConfirmation { <elements...> }.render_into(writer)
                },
            }
        }
    }

    #[derive(Template)]
    #[template(path = "hello.html")]
    struct Template_Arrived<'a>(<&'a elements...>);

    #[derive(Template)]
    #[template(path = "hello.html")]
    struct Template_Delivery<'a>(<&'a elements...>);

    #[derive(Template)]
    struct Template_PendingConfirmation<'a> { <&'a elements...> };
};

Should be easy enough to implement since all the magic can be done by syn, no actual implementation needed.

Most likely it would be more useful to put #[template(…)] next to the variants instead of the enum itself, or the enum could function as the default, that variants can override. But then the problem remains what if not every variant has the same mime-type?

@Kijewski
Copy link
Collaborator

Kijewski commented Apr 21, 2022

I implemented a very simplistic version of my idea, but I don't think there's anymore needed:

This might serve as a better/simpler multiple templates per struct approach than #600. What do y'all think?

@djc
Copy link
Collaborator

djc commented Apr 21, 2022

It seems nice but pretty niche. :) It's probably good enough as a solution for this issue?

@tema3210
Copy link
Author

It seems nice but pretty niche. :) It's probably good enough as a solution for this issue?

Yes. thanks @Kijewski.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants