borrowize
borrowize provides #[derive(View)], a small procedural macro for generating
borrowed view types from owned structs and enums.
The macro is useful when an API wants to expose a cheap borrowed projection of an owned value without writing a second struct and conversion method by hand.
Quick Start
use View;
;
let user = User ;
let view = user.view;
assert_eq!;
assert_eq!;
assert_eq!;
This generates a sibling view type similar to:
The generated lifetime is always named 'borrowize inside generated view type
definitions. Source structs may not define a lifetime with that name.
Default Mapping
borrowize maps common owned field types to borrowed forms:
| Source field type | Generated view field type | Generated expression |
|---|---|---|
String |
&'borrowize str |
self.field.as_str() |
Vec<T> |
&'borrowize [T] |
self.field.as_slice() |
[T; N] |
&'borrowize [T] |
&self.field[..] |
Box<T> |
&'borrowize T |
self.field.as_ref() |
PathBuf |
&'borrowize std::path::Path |
self.field.as_path() |
Option<T> |
Option<Borrowed<T>> |
self.field.as_ref().map(...) |
&'a T |
&'a T |
self.field |
other T |
&'borrowize T |
&self.field |
Option<T> is mapped recursively, so Option<String> becomes
Option<&'borrowize str> and Option<u64> becomes Option<&'borrowize u64>.
Type matching is syntactic. The macro recognises unqualified names and common
standard-library qualified names such as std::string::String,
alloc::string::String, std::vec::Vec, alloc::vec::Vec,
std::option::Option, core::option::Option, std::boxed::Box,
alloc::boxed::Box, and std::path::PathBuf. Type aliases are treated as
unknown types and are borrowed as &T.
Struct And Enum Options
Item-level options are written as #[borrowize(...)] on the source struct or
enum.
Names are explicit; there are no shorthand options.
use View;
Supported item options:
| Option | Meaning |
|---|---|
view_name = "Name" |
Override the generated view type name. |
view_visibility = "pub" |
Override the generated view type visibility. |
field_visibility = "pub" |
Set the default visibility for generated view fields. |
method_name = "name" |
Override the generated method name. |
method_visibility = "pub" |
Override the generated method visibility. |
no_method |
Do not generate the inherent view method. |
When a visibility option is omitted, visibility is inherited from the source
item or field. Explicit visibility values must be legal Rust visibility syntax,
such as pub, pub(crate), or pub(super).
no_method cannot be combined with method_name or method_visibility.
field_visibility applies to generated named and tuple struct view fields
only. It cannot be used on enums because Rust enum variant fields do not have
independent visibility.
Enums
Enums with named-field variants, tuple variants, and unit variants are supported. Each variant is mapped independently using the same default field mapping as structs.
use View;
let event = Created ;
let view = event.view;
match view
Tuple enum variant fields are exposed to generation_expression overrides as
field_0, field_1, and so on.
Field Options
Field-level options are written as #[borrowize(...)] on a source field.
use View;
Supported field options:
| Option | Meaning |
|---|---|
borrowed_type = "Type" |
Override the generated view field type. |
generation_expression = "expr" |
Override the generated field initializer in the view method. |
visibility = "pub" |
Override this generated struct view field's visibility. |
borrowed_type overrides may refer to the generated borrow lifetime as
'borrowize.
generation_expression is parsed as a Rust expression in the generated method
body. On structs it can refer to self because the generated method borrows
&self, including tuple fields such as self.0. On named enum variants it can
refer to the named variant field binding. On tuple enum variants it can refer
to field_0, field_1, and later generated field bindings.
Manual View Construction
Generated view fields inherit source field visibility by default. Use
field_visibility or field-level visibility when views need to be assembled
outside the source module.
use View;
let id = 21;
let view = PublicSourceView ;
This is useful when you have borrowed pieces available before you have an owned
source value to call view() on.
Generics
Source generics, const generics, lifetimes, and where clauses are preserved on the generated view type and inherent method.
use View;
Limitations
View supports named-field structs, tuple structs, named-field enum variants,
tuple enum variants, and unit enum variants. Unions and unit structs produce
compile errors.
The generated inherent method can conflict with a user-defined method of the
same name. Use method_name to choose a different method name or no_method
when only the view type is needed.
Nested custom view conversion is not inferred. Unknown types are borrowed as
&T, even if they also derive View.
Type matching is syntactic, so aliases and re-exports of recognised container types are not expanded.
The generated lifetime name 'borrowize is reserved.
Licence
borrowize is distributed under the terms of both the MIT licence and the
Apache License, Version 2.0. You may use it under either licence, at your
option.
See LICENSE-MIT and LICENSE-APACHE for the full licence texts.
Contributions
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in borrowize is licensed as MIT OR Apache-2.0, without any
additional terms or conditions.