Skip to content

KKould/ref-view

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ref-view

ref-view provides #[derive(RefView)] for generating zero-copy reference views over named structs and named-field enums.

use ref_view::RefView;

#[derive(RefView)]
#[ref_view(name = ItemWithoutPayload, omit(payload))]
struct Item {
    id: u64,
    payload: Option<String>,
}

By default the macro generates:

  • ItemView: a trait with field accessors
  • ItemRef<'a>: a full reference view

Additional #[ref_view(name = ..., omit(...))] attributes generate views that do not store omitted fields. Their accessors return None.

For enums, omit targets can be variant-qualified:

#[derive(RefView)]
#[ref_view(name = TableRefWithoutPivot, omit(Table.pivot, Subquery.pivot))]
enum TableRef {
    Table { pivot: String },
    Subquery { pivot: String },
}

MVP limits:

  • only non-generic types
  • only named structs and named-field enum variants

Examples

Run the examples with:

cargo run --example basic_struct
cargo run --example derive_and_impl_trait
cargo run --example enum_table_reference

Struct Views

examples/basic_struct.rs shows a full UserRef<'a> and a UserPublicView<'a> that omits sensitive fields:

#[derive(RefView)]
#[ref_view(name = UserPublicView, omit(email, api_token))]
struct User {
    id: u64,
    name: String,
    email: Option<String>,
    api_token: String,
}

Fields omitted by at least one view get Option<&T> accessors. The full view returns Some(...); the omitted view returns None.

The same example also shows #[ref_view(trait_name = ConfigLike)], which makes generated views implement ConfigLike instead of the default ConfigView.

Derives And Trait Implementations

examples/derive_and_impl_trait.rs shows how to make generated ref views derive the same common traits as the source type:

#[derive(Debug, PartialEq, Eq, RefView)]
#[ref_view(derive(Debug, PartialEq, Eq))]
#[ref_view(name = PublicUserRef, omit(email, api_token))]
struct User {
    id: u64,
    name: String,
    email: Option<String>,
    api_token: String,
}

Functions can be widened to accept the source type and generated views:

#[ref_view::impl_fn(UserView)]
fn compact_label(user: &User) -> String {
    format!("{}#{} ({:?})", user.name(), user.id(), user.role())
}

Normal impl blocks can be mirrored to generated ref views:

#[ref_view::impl_trait(UserView => UserRef<'_>, PublicUserRef<'_>)]
impl std::fmt::Display for User {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{} [{}]", compact_label(self), optional_contact(self))
    }
}

The macro always derives Clone and Copy for generated views. Extra derives are explicit via #[ref_view(derive(...))] instead of copied automatically from the source type, because derives such as Default may not make sense for borrowed views.

The example also demonstrates trait-oriented patterns:

  • functions taking &impl UserView
  • generic functions with T: UserView
  • blanket impls for local traits over every T: UserView
  • widened helper functions via #[ref_view::impl_fn(...)]
  • mirrored trait impls for generated ref views via #[ref_view::impl_trait(...)], such as sharing one Display implementation across User, UserRef<'_>, and PublicUserRef<'_>

Enum Views

examples/enum_table_reference.rs demonstrates a SQL-like formatter shared by the source enum, its full ref view, and an omit view:

#[derive(RefView)]
#[ref_view(name = TableReferenceWithoutPivot, omit(Table.pivot, Subquery.pivot))]
enum TableReference {
    Table { pivot: String, /* ... */ },
    Subquery { pivot: String, /* ... */ },
}

The formatter calls pivot() normally. Full views return the pivot; the omit view returns None, so the same formatter can render a table reference without the pivot clause.

About

Derive zero-copy reference views for structs and enums

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages