Trait minijinja::value::StructObject
source · pub trait StructObject: Send + Sync {
// Required method
fn get_field(&self, name: &str) -> Option<Value>;
// Provided methods
fn static_fields(&self) -> Option<&'static [&'static str]> { ... }
fn fields(&self) -> Vec<Arc<String>> { ... }
fn field_count(&self) -> usize { ... }
}
Expand description
Provides the behavior of an Object
holding a struct.
An basic object with the shape and behavior of a struct (that means a map with string keys) can be represented by this trait.
Simplified Example
For structs which do not need any special method behavior or methods, the
Value
type is capable of automatically constructing a wrapper Object
by using Value::from_struct_object
. In that case only StructObject
needs to be implemented and the value will provide default implementations
for stringification and debug printing.
use minijinja::value::{Value, StructObject};
struct Point(f32, f32, f32);
impl StructObject for Point {
fn get_field(&self, name: &str) -> Option<Value> {
match name {
"x" => Some(Value::from(self.0)),
"y" => Some(Value::from(self.1)),
"z" => Some(Value::from(self.2)),
_ => None,
}
}
fn static_fields(&self) -> Option<&'static [&'static str]> {
Some(&["x", "y", "z"][..])
}
}
let value = Value::from_struct_object(Point(1.0, 2.5, 3.0));
Full Example
The following example shows how to implement a dynamic object which
represents a struct. Note that in this case not only Object
needs to be
implemented, but also Debug
and Display
no longer
come for free.
use std::fmt;
use minijinja::value::{Value, Object, ObjectKind, StructObject};
#[derive(Debug, Clone)]
struct Point(f32, f32, f32);
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}, {}, {})", self.0, self.1, self.2)
}
}
impl Object for Point {
fn kind(&self) -> ObjectKind<'_> {
ObjectKind::Struct(self)
}
}
impl StructObject for Point {
fn get_field(&self, name: &str) -> Option<Value> {
match name {
"x" => Some(Value::from(self.0)),
"y" => Some(Value::from(self.1)),
"z" => Some(Value::from(self.2)),
_ => None,
}
}
fn static_fields(&self) -> Option<&'static [&'static str]> {
Some(&["x", "y", "z"][..])
}
}
let value = Value::from_object(Point(1.0, 2.5, 3.0));
Required Methods§
sourcefn get_field(&self, name: &str) -> Option<Value>
fn get_field(&self, name: &str) -> Option<Value>
Invoked by the engine to get a field of a struct.
Where possible it’s a good idea for this to align with the return value
of fields
but it’s not necessary.
If an field does not exist, None
shall be returned.
A note should be made here on side effects: unlike calling objects or
calling methods on objects, accessing fields is not supposed to
have side effects. Neither does this API get access to the interpreter
State
nor is there a channel to send out failures as only an option
can be returned. If you do plan on doing something in field access
that is fallible, instead use a method call.
Provided Methods§
sourcefn static_fields(&self) -> Option<&'static [&'static str]>
fn static_fields(&self) -> Option<&'static [&'static str]>
If possible returns a static vector of field names.
If fields cannot be statically determined, then this must return None
and fields
should be implemented instead. If however
this method is implemented, then fields
should not be
implemented as the default implementation dispatches to here, or it has
to be implemented to match the output.
sourcefn fields(&self) -> Vec<Arc<String>>
fn fields(&self) -> Vec<Arc<String>>
Returns a vector of field names.
This should be implemented if static_fields
cannot
be implemented due to lifetime restrictions. To avoid unnecessary
allocations of the fields themselves it’s recommended to use the
intern
function. The default implementation converts the return value
of static_fields
into a compatible format automatically.
sourcefn field_count(&self) -> usize
fn field_count(&self) -> usize
Returns the number of fields.
The default implementation uses fields
and
static_fields
automatically.