pub trait FromValue: Sized {
// Required method
fn from_value(v: Value) -> Result<Self, ShellError>;
// Provided method
fn expected_type() -> Type { ... }
}
Expand description
A trait for loading a value from a Value
.
§Derivable
This trait can be used with #[derive]
.
When derived on structs with named fields, it expects a Value::Record
where each field of
the struct maps to a corresponding field in the record.
- If
#[nu_value(rename = "...")]
is applied to a field, that name will be used as the key in the record. - If
#[nu_value(rename_all = "...")]
is applied on the container (struct) the key of the field will be case-converted accordingly. - If neither attribute is applied, the field name is used as is.
Supported case conversions include those provided by heck
, such as
“snake_case”, “kebab-case”, “PascalCase”, and others.
Additionally, all values accepted by
#[serde(rename_all = "...")]
are valid here.
For structs with unnamed fields, it expects a Value::List
, and the fields are populated in
the order they appear in the list.
Unit structs expect a Value::Nothing
, as they contain no data.
Attempting to convert from a non-matching Value
type will result in an error.
Only enums with no fields may derive this trait.
The expected value representation will be the name of the variant as a Value::String
.
- If
#[nu_value(rename = "...")]
is applied to a variant, that name will be used. - If
#[nu_value(rename_all = "...")]
is applied on the enum container, the name of variant will be case-converted accordingly. - If neither attribute is applied, the variant name will default to “snake_case”.
Additionally, you can use #[nu_value(type_name = "...")]
in the derive macro to set a custom type name
for FromValue::expected_type
. This will result in a Type::Custom
with the specified type name.
This can be useful in situations where the default type name is not desired.
§Enum Example
#[derive(FromValue, Debug, PartialEq)]
#[nu_value(rename_all = "COBOL-CASE", type_name = "birb")]
enum Bird {
MountainEagle,
ForestOwl,
#[nu_value(rename = "RIVER-QUACK")]
RiverDuck,
}
assert_eq!(
Bird::from_value(Value::string("FOREST-OWL", span)).unwrap(),
Bird::ForestOwl
);
assert_eq!(
Bird::from_value(Value::string("RIVER-QUACK", span)).unwrap(),
Bird::RiverDuck
);
assert_eq!(
&Bird::expected_type().to_string(),
"birb"
);
§Struct Example
#[derive(FromValue, PartialEq, Eq, Debug)]
#[nu_value(rename_all = "kebab-case")]
struct Person {
first_name: String,
last_name: String,
#[nu_value(rename = "age")]
age_years: u32,
}
let value = Value::record(record! {
"first-name" => Value::string("John", span),
"last-name" => Value::string("Doe", span),
"age" => Value::int(42, span),
}, span);
assert_eq!(
Person::from_value(value).unwrap(),
Person {
first_name: "John".into(),
last_name: "Doe".into(),
age_years: 42,
}
);
Required Methods§
sourcefn from_value(v: Value) -> Result<Self, ShellError>
fn from_value(v: Value) -> Result<Self, ShellError>
Provided Methods§
sourcefn expected_type() -> Type
fn expected_type() -> Type
Expected Value
type.
This is used to print out errors of what type of value is expected for conversion.
Even if not used in from_value
this should still be implemented
so that other implementations like Option
or Vec
can make use of it.
It is advised to call this method in from_value
to ensure that expected type in the error
is consistent.
Unlike the default implementation, derived implementations explicitly reveal the concrete
type, such as Type::Record
or Type::List
, instead of an opaque type.