Skip to content

Refactoring and Improvements on #[cgp_getter]#81

Merged
soareschen merged 19 commits intomainfrom
getter-improvement
Mar 23, 2025
Merged

Refactoring and Improvements on #[cgp_getter]#81
soareschen merged 19 commits intomainfrom
getter-improvement

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