pub struct MessageField<T: Default, P = Box<T>> { /* private fields */ }Expand description
A wrapper for optional message fields that provides transparent access to a default instance when the field is not set.
This type is used for singular message fields in generated code. The pointer
type P is pluggable; see ProtoBox. Codegen emits Inline<T> by
default — the message is stored directly in the parent struct (laid out as
Option<T>), so size_of::<T>() is reserved whether set or not and there
is no per-field heap allocation. Recursive fields and explicit opt-outs use
Box<T> instead, which heap-allocates only when set. The struct’s own
P = Box<T> type-parameter default applies only to a hand-written
MessageField<T> (e.g. in tests), not to generated fields.
Because P has a default, a standalone construction with no pinning
context needs a type annotation — write let f: MessageField<Foo> = MessageField::some(x); (or MessageField::<Foo>::some(x)). In the common
cases — a struct-literal field (Outer { inner: MessageField::some(x), .. })
or an assignment to a typed field — P is inferred from the target and no
annotation is needed.
§Access patterns
// Reading through an unset field gives the default:
let msg = Outer::default();
assert_eq!(msg.inner.name, ""); // No unwrap needed, derefs to default
// Check if set:
if msg.inner.is_set() { ... }
// Set a value:
msg.inner = MessageField::some(Inner { name: "hello".into(), ..Default::default() });
// Clear:
msg.inner = MessageField::none();§Construction and conversion
From conversions are the idiomatic way to populate a generated message
field. They accept both a message value and an Option of one. Reading
goes the other way through Deref, so a field whose
message type implements DefaultInstance needs no unwrapping at all.
use buffa::MessageField;
// A value converts straight into a set field.
let field: MessageField<Person> = Person { name: "Ada".into(), id: 1 }.into();
// Reading goes through `Deref`, so no unwrapping ceremony.
assert_eq!(field.name, "Ada");
// An `Option` converts too, so `map` chains land directly in the field.
let field: MessageField<Person> = Some("Grace")
.map(|name| Person { name: name.into(), id: 2 })
.into();
assert_eq!(field.id, 2);
// An unset field derefs to the default instance rather than panicking.
let empty: MessageField<Person> = None.into();
assert!(empty.is_unset());
assert_eq!(empty.name, "");Implementations§
Source§impl<T: Default, P: ProtoBox<T>> MessageField<T, P>
impl<T: Default, P: ProtoBox<T>> MessageField<T, P>
Sourcepub fn from_pointer(value: P) -> Self
pub fn from_pointer(value: P) -> Self
Create a MessageField from an already-constructed pointer, without
unwrapping and re-boxing the value.
Prefer this over MessageField::some(p.into_inner()) when you already
hold a P — for an inline pointer (e.g. SmallBox) the latter would
move the value out and re-store it, defeating the point. The generic
counterpart to from_box (which is Box-only).
Sourcepub fn as_option_mut(&mut self) -> Option<&mut T>
pub fn as_option_mut(&mut self) -> Option<&mut T>
Get a mutable reference to the inner value, or None if unset.
Sourcepub fn get_or_insert_default(&mut self) -> &mut T
pub fn get_or_insert_default(&mut self) -> &mut T
Get a mutable reference to the value, initializing to the default if unset.
Sourcepub fn modify<F: FnOnce(&mut T)>(&mut self, f: F)
pub fn modify<F: FnOnce(&mut T)>(&mut self, f: F)
Call f with a mutable reference to the inner value, initializing to
the default if the field is currently unset.
This is the ergonomic write counterpart to the transparent read
provided by Deref. Instead of calling get_or_insert_default once
per assignment:
msg.address.get_or_insert_default().street = "123 Main St".into();
msg.address.get_or_insert_default().city = "Springfield".into();use modify to initialize the field once and set all sub-fields in
the closure:
msg.address.modify(|a| {
a.street = "123 Main St".into();
a.city = "Springfield".into();
});Sourcepub fn into_option(self) -> Option<T>
pub fn into_option(self) -> Option<T>
Consume the field, returning Some(T) if set or None if unset.
This unboxes the inner value. For in-place extraction that leaves the
field unset without consuming the enclosing struct, see take.
Sourcepub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U>
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U>
Consume the field, applying f to the inner value if set.
Mirrors Option::map. Equivalent in effect to
into_option.map(f), but reads as if the
field were a plain Option. The motivating case is converting an
optional submessage into a differently-typed Option when mapping
a generated struct to a domain type:
// Before: value.shoulder_entity_left.into_option().map(Into::into)
shoulder_entity_left: value.shoulder_entity_left.map(Into::into),With map(Into::into) the target type must be inferable from
context (a typed struct field, annotated let, or function return);
otherwise name the conversion (map(Domain::from)). To map without
consuming the field, use as_option.map(...).
Sourcepub fn unwrap(self) -> T
pub fn unwrap(self) -> T
Consume the field, returning the inner value.
Equivalent in effect to into_option().unwrap(), with a clearer
panic message. Prefer ok_or /
ok_or_else when an unset field should produce
an error rather than a panic.
§Panics
Panics if the field is unset.
Sourcepub fn expect(self, msg: &str) -> T
pub fn expect(self, msg: &str) -> T
Consume the field, returning the inner value, with a custom panic message if unset.
Mirrors Option::expect. Prefer ok_or /
ok_or_else when an unset field should produce
an error rather than a panic.
§Panics
Panics with msg if the field is unset.
Sourcepub fn ok_or<E>(self, err: E) -> Result<T, E>
pub fn ok_or<E>(self, err: E) -> Result<T, E>
Consume the field, returning Ok(T) if set or Err(err) if unset.
Mirrors Option::ok_or. Useful for enforcing presence of
semantically-required fields that the proto schema leaves optional:
let cmd = request.normalized_command.ok_or(Error::MissingCommand)?;Sourcepub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E>
pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E>
Consume the field, returning Ok(T) if set or Err(err()) if unset.
Mirrors Option::ok_or_else. The closure is only called if the
field is unset, so use this over ok_or when
constructing the error is non-trivial:
let cmd = request.normalized_command.ok_or_else(|| {
ConnectError::invalid_argument("missing normalized_command in request")
})?;Source§impl<T: Default> MessageField<T, Box<T>>
impl<T: Default> MessageField<T, Box<T>>
Sourcepub fn from_box(value: Box<T>) -> Self
pub fn from_box(value: Box<T>) -> Self
Create a MessageField from a boxed value.
Specific to Box<T> (the struct’s P = Box<T> type-parameter default,
used for recursive fields and explicit opt-outs); inline-backed
generated fields use some or
from_pointer instead.
Trait Implementations§
Source§impl<'a, T: Default + Arbitrary<'a>, P: ProtoBox<T>> Arbitrary<'a> for MessageField<T, P>
Available on crate feature arbitrary only.
impl<'a, T: Default + Arbitrary<'a>, P: ProtoBox<T>> Arbitrary<'a> for MessageField<T, P>
arbitrary only.Source§fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self>
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self>
Self from the given unstructured data. Read moreSource§fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self, Error>
fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self, Error>
Self from the entirety of the given
unstructured data. Read moreSource§fn size_hint(depth: usize) -> (usize, Option<usize>)
fn size_hint(depth: usize) -> (usize, Option<usize>)
Unstructured this type
needs to construct itself. Read moreSource§fn try_size_hint(
depth: usize,
) -> Result<(usize, Option<usize>), MaxRecursionReached>
fn try_size_hint( depth: usize, ) -> Result<(usize, Option<usize>), MaxRecursionReached>
Unstructured this type
needs to construct itself. Read moreSource§impl<T: DefaultInstance, P: ProtoBox<T>> Deref for MessageField<T, P>
impl<T: DefaultInstance, P: ProtoBox<T>> Deref for MessageField<T, P>
Source§impl<'de, T: Default + Deserialize<'de>, P: ProtoBox<T>> Deserialize<'de> for MessageField<T, P>
Available on crate feature json only.
impl<'de, T: Default + Deserialize<'de>, P: ProtoBox<T>> Deserialize<'de> for MessageField<T, P>
json only.Source§fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error>
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error>
impl<T: DefaultInstance + Eq + PartialEq, P: ProtoBox<T>> Eq for MessageField<T, P>
Source§impl<T: Default, P: ProtoBox<T>> From<MessageField<T, P>> for Option<T>
impl<T: Default, P: ProtoBox<T>> From<MessageField<T, P>> for Option<T>
Source§fn from(field: MessageField<T, P>) -> Self
fn from(field: MessageField<T, P>) -> Self
Unbox a MessageField into an Option<T>; equivalent to
MessageField::into_option.