#[non_exhaustive]
pub enum StructDef<'a> {
Static {
name: &'static str,
fields: Fields<'static>,
},
Dynamic {
name: &'a str,
fields: Fields<'a>,
},
}
Expand description
A struct’s name, fields, and other struct-level information.
Returned by Structable::definition()
, StructDef
provides the caller
with information about the struct’s definition.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Static
Fields
This variant is marked as non-exhaustive
The struct is statically-defined, all fields are known ahead of time.
Most Structable
definitions for Rust struct types will be
StructDef::Static
.
Examples
A statically defined struct
use valuable::{Fields, Valuable, Structable, StructDef};
#[derive(Valuable)]
struct MyStruct {
foo: &'static str,
}
let my_struct = MyStruct { foo: "Hello" };
let fields = match my_struct.definition() {
StructDef::Static { name, fields, ..} => {
assert_eq!("MyStruct", name);
fields
}
_ => unreachable!(),
};
match fields {
Fields::Named(named_fields) => {
assert_eq!(1, named_fields.len());
assert_eq!("foo", named_fields[0].name());
}
_ => unreachable!(),
}
Dynamic
Fields
This variant is marked as non-exhaustive
The struct is dynamically-defined, not all fields are known ahead of time.
A dynamically-defined struct could be represented using
Mappable
, though, using Structable
offers benefits in a couple of
cases. For example, when serializing a Value
, some formats will
serialize maps and structs differently. In this case, differentiating
the two is required. There also are times when some struct fields
are known statically, but not all of them (see second example).
Examples
The struct stores field values in a HashMap
.
use valuable::{Fields, NamedField, NamedValues, Structable, StructDef, Value, Valuable, Visit};
use std::collections::HashMap;
/// A dynamic struct
struct Dyn {
// The struct name
name: String,
// Named values.
values: HashMap<String, Box<dyn Valuable>>,
}
impl Valuable for Dyn {
fn as_value(&self) -> Value<'_> {
Value::Structable(self)
}
fn visit(&self, visit: &mut dyn Visit) {
// This could be optimized to batch some.
for (field, value) in self.values.iter() {
visit.visit_named_fields(&NamedValues::new(
&[NamedField::new(field)],
&[value.as_value()],
));
}
}
}
impl Structable for Dyn {
fn definition(&self) -> StructDef<'_> {
StructDef::new_dynamic(&self.name, Fields::Named(&[]))
}
}
Some fields are known statically.
use valuable::{Fields, NamedField, NamedValues, Structable, StructDef, Value, Valuable, Visit};
use std::collections::HashMap;
struct HalfStatic {
foo: u32,
bar: u32,
extra_values: HashMap<String, Box<dyn Valuable>>,
}
impl Valuable for HalfStatic {
fn as_value(&self) -> Value<'_> {
Value::Structable(self)
}
fn visit(&self, visit: &mut dyn Visit) {
// First, visit static fields
visit.visit_named_fields(&NamedValues::new(
FIELDS,
&[self.foo.as_value(), self.bar.as_value()],
));
// This could be optimized to batch some.
for (field, value) in self.extra_values.iter() {
visit.visit_named_fields(&NamedValues::new(
&[NamedField::new(field)],
&[value.as_value()],
));
}
}
}
static FIELDS: &[NamedField<'static>] = &[
NamedField::new("foo"),
NamedField::new("bar"),
];
impl Structable for HalfStatic {
fn definition(&self) -> StructDef<'_> {
// Include known fields.
StructDef::new_dynamic(
"HalfStatic",
Fields::Named(FIELDS))
}
}
Implementations§
source§impl<'a> StructDef<'a>
impl<'a> StructDef<'a>
sourcepub const fn new_static(
name: &'static str,
fields: Fields<'static>
) -> StructDef<'a>
pub const fn new_static( name: &'static str, fields: Fields<'static> ) -> StructDef<'a>
Create a new StructDef::Static
instance.
This should be used when a struct’s fields are fixed and known ahead of time.
Examples
use valuable::{StructDef, Fields};
let def = StructDef::new_static("Foo", Fields::Unnamed(2));
sourcepub const fn new_dynamic(name: &'a str, fields: Fields<'a>) -> StructDef<'a>
pub const fn new_dynamic(name: &'a str, fields: Fields<'a>) -> StructDef<'a>
Create a new StructDef::Dynamic
instance.
This is used when the struct’s fields may vary at runtime.
Examples
use valuable::{StructDef, Fields};
let def = StructDef::new_dynamic("Foo", Fields::Unnamed(3));
sourcepub const fn name(&self) -> &'a str
pub const fn name(&self) -> &'a str
Returns the struct’s name
Examples
With a static struct
use valuable::{StructDef, Fields};
let def = StructDef::new_static("Foo", Fields::Unnamed(1));
assert_eq!("Foo", def.name());
With a dynamic struct
use valuable::{StructDef, Fields};
let def = StructDef::new_dynamic("Foo", Fields::Unnamed(2));
assert_eq!("Foo", def.name());
sourcepub const fn fields(&self) -> &Fields<'a>
pub const fn fields(&self) -> &Fields<'a>
Returns the struct’s fields
Examples
With a static struct
use valuable::{StructDef, Fields};
let def = StructDef::new_static("Foo", Fields::Unnamed(3));
assert!(matches!(def.fields(), Fields::Unnamed(_)));
With a dynamic struct
use valuable::{StructDef, Fields};
let def = StructDef::new_dynamic("Foo", Fields::Unnamed(1));
assert!(matches!(def.fields(), Fields::Unnamed(_)));
sourcepub const fn is_static(&self) -> bool
pub const fn is_static(&self) -> bool
Returns true
if the struct is statically defined.
Examples
With a static struct
use valuable::{StructDef, Fields};
let def = StructDef::new_static("Foo", Fields::Unnamed(2));
assert!(def.is_static());
With a dynamic struct
use valuable::{StructDef, Fields};
let def = StructDef::new_dynamic("Foo", Fields::Unnamed(4));
assert!(!def.is_static());
sourcepub const fn is_dynamic(&self) -> bool
pub const fn is_dynamic(&self) -> bool
Returns true
if the struct is dynamically defined.
Examples
With a static struct
use valuable::{StructDef, Fields};
let def = StructDef::new_static("Foo", Fields::Unnamed(1));
assert!(!def.is_dynamic());
With a dynamic struct
use valuable::{StructDef, Fields};
let def = StructDef::new_dynamic("Foo", Fields::Unnamed(1));
assert!(def.is_dynamic());