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

Refactoring and Improvements on #[cgp_getter] #81

Merged
merged 19 commits into from
Mar 23, 2025
Merged

Conversation

soareschen
Copy link
Collaborator

@soareschen soareschen commented Mar 23, 2025

Summary

This PR brings several quality of life improvements on the proc macros #[cgp_getter] and #[cgp_auto_getter], allowing them to support more general getter interfaces to be defined.

Specialized &str Field

Getter methods can now return &str instead of &String to derive UseField implementations that require the context to contain a String field.

For example, the following HasName trait will be implemented for any context struct that contains name: String:

#[cgp_auto_getter]
pub trait HasName {
    fn name(&self) -> &str;
}

Specialized Option<&T> Field

Getter methods can now return Option<&T> instead of &Option<T> to derive UseField implementations that require the context to contain an Option<T> field.

For example, the following HasName trait will be implemented for any context struct that contains name: Option<Self::Name>:

#[cgp_auto_getter]
pub trait HasName: HasNameType {
    fn name(&self) -> Option<&Self::Name>;
}

Specialized Cloneeable Field

Getter methods can now return owned values instead of references. The derived implementation will require the value type to implement Clone.

For example, the following HasName trait will be implemented for any context struct that contains name: Self::Name with Self::Name: Clone:

#[cgp_auto_getter]
pub trait HasName: HasNameType<Name: Clone> {
    fn name(&self) -> Self::Name;
}

PhantomData Tag Argument

A second PhantomData argument can now be provided in getter methods to help with type inferences, in case when the getter trait contains generic parameters.

Example:

pub trait HasName<App>
where
    App: HasNameType,
{
    fn name(&self, _tag: PhantomData<App>) -> &App::Name;
}

WithFieldRef

A UseFieldRef provider has been implemented as a complement of UseField, which allows accessing a field value using AsRef. This allows field accessors to be implemented on structs that do not contain the exact same type, such as values that are wrapped in Box or Arc.

For example, the following Person context implements HasName that returns String, even though the context contains a name field of type Box<String>:

#[cgp_getter {
    provider: NameGetter,
}]
pub trait HasName {
    fn name(&self) -> &String;
}

#[cgp_context(PersonProvider)]
#[derive(HasField)]
pub struct Person {
    pub name: Box<String>,
}

delegate_components! {
    PersonProvider {
        NameGetterComponent: WithFieldRef<symbol!("name"), String>,
    }
}

check_components! {
    CanUsePerson for Person {
        NameGetterComponent,
    }
}

@soareschen soareschen merged commit ca16acf into main Mar 23, 2025
5 checks passed
@soareschen soareschen deleted the getter-improvement branch March 23, 2025 16:38
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

Successfully merging this pull request may close these issues.

1 participant