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.