Skip to content
This repository has been archived by the owner on May 12, 2024. It is now read-only.

Add macro support for enum of entities #15

Closed
chipsenkbeil opened this issue Dec 28, 2020 · 2 comments
Closed

Add macro support for enum of entities #15

chipsenkbeil opened this issue Dec 28, 2020 · 2 comments
Milestone

Comments

@chipsenkbeil
Copy link
Owner

Use case is for vimwiki where I have BlockElement, InlineElement, and other enums that can be one of several types.

Need to be able to do

#[simple_ent]
pub struct Page {
    #[ent(edge = "BlockElement"))]
    elements: Vec<Id>,
}

#[simple_ent]
pub enum BlockElement {
    Paragraph(Paragraph),
    // ...
}

This would generate an implementation for the enum that has no builder, maybe a typed query but without anything useful (just id, type, etc) since the page would generate it, and routes all IEnt functions to the underlying variant. Because you can use the field and edge untyped functions, that would be good enough here, especially since you can extract the more specific type from the enum.

@chipsenkbeil
Copy link
Owner Author

chipsenkbeil commented Dec 29, 2020

Several changes need to be made:

  1. IEnt's r#type method needs to be a static method rather than an instance one (and const if possible). This is because the enum derive won't know what the str type of the variant will be unless it can call the method. It needs this for the second change.
  2. A query will be generated for the enum that begins with an "or" predicate of type equality, saying to find an ent that matches any of the variant types. This is why we need a static r#type method as this will generate a call to each variant's type str. We cannot assume that the generated constant or anything else is available as users can define this themselves without code generation.
  3. An implementation of IEnt for the enum where each method matches against the enum and calls the variant's implementation
  4. Conversion from each variant to the enum via individual From impls just like with derive_more
  5. Special handling on the edge definition to indicate that this is an enum that is not stored directly. We need this because we don't actually want to store the ent wrapped in the enum, but rather just the ent itself. This means that converting from Box -> SomeEnum isn't possible. Instead, the process is Box -> MyEnt -> MyEnum::MyEnt. The generated load_edge method needs to return DatabaseResult<Option<MyEnum>> with extra internal logic to get a generic Box and then a series of cast checks against each variant type until we either find a match and wrap it in the enum or we fail and return an error/none.

@chipsenkbeil
Copy link
Owner Author

Involved adding a new trait that enums implement called EntWrapper along with a new word attr in the form of ent(edge(wrap, ...)) that switches from ent.to_ent::<$type>() to $type::wrap_ent(ent).

@chipsenkbeil chipsenkbeil added this to the 0.1 milestone Jan 6, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant