Default Values
There are several scenarios where a default value will be used to initialize a field during deserialization:
- The field is not mandatory and is not present in the serialized data.
- The field is present in the serialized data, but it has some issues trying to deserialize it and the
validate
attribute is set tofallback
. - The field is skipped during serialization and it has to be defaulted during deserialization.
In these scenarios, FlatMessage will do one of the following:
- Use the default value for the type if it is available (this implies that the type implements the
Default
trait). - If the attribute
default
is specified, it will use the value of the attribute.
Example:
- Use the default value:
In this case, the field#![allow(unused)] fn main() { #[derive(FlatMessage)] struct Test { #[flat_message_item(skip = true)] a: u32, } }
a
will be initialized to0
(the default value foru32
). - Use the value of the attribute
default
:
In this case, the field#![allow(unused)] fn main() { #[derive(FlatMessage)] struct Test { #[flat_message_item(skip = true, default = 10)] a: u32, } }
a
will be initialized to10
.
Custom Default Values
When using the attribute default
, you can specify a custom default value for the field in the following ways:
- A constant value (e.g.
default = 10
ordefault = MY_CONSTANT
). - A string representation of the value (e.g.
default = "10"
). In this case the value is parsed and adjusted to fit the actual type of the field. - A raw string representation of the value (e.g.
default = r#"foo(1,2,3)"#
). In this case the value is use exactly as is. This is in particular useul if you want to use exprssior or a call to a functon to initialize the value.
String representations
When using a string representation: default = "..."
the following steps are checked:
- if the type is
&str
the value of the default attribute is kept as it is. - if the type is
String
th value of the default attribute is converted into a String - if the type is NOT a string the quotes (
"
) are removed and the actual value will be used - if the type is on option (
Option<T>
) then:- if the value of the default attribute is
None
then the field is set toNone
- if the value of the default attribute is
Some(T)
then the field is set toSome(T)
- otherwise the value of the default attribute is converted into a
Some<value>
- if the value of the default attribute is
Examples
Type | Default value | Actual value |
---|---|---|
Numeric (u8, u32, f32, etc) | default = "10" | 10 |
Numeric (u8, u32, f32, etc) | default = 123 | 123 |
Numeric (u8, u32, f32, etc) | default = MY_CONSTANT | MY_CONSTANT (it is assumed that MY_CONSTANT exists in the current scope) |
Numeric (u8, u32, f32, etc) | default = r#"1+2+3"# | 6 |
Boolean value (bool) | default = "true" | true |
Boolean value (bool) | default = false | false |
Boolean value (bool) | default = r#"foo(a,b,c)"# | foo(a,b,c) (it is assumed that a , b , c and the function foo exists in the current scope) |
String reference ( &str ) | default = "hello" | "hello" |
String ( String ) | default = "hello" | String::from("hello") |
String reference ( &str ) | default = MY_CONSTANT | "MY_CONSTANT" (it is assumed that MY_CONSTANT exists in the current scope) |
Option | default = "None" | None |
Option | default = "Some(123)" | Some(123) |
Option | default = MY_CONSTANT | MY_CONSTANT (it is assumed that MY_CONSTANT exists in the current scope and it of type Option<T> ) |
Option | default = r#"foo(1+2+3)"# | foo(1+2+3) (it is assumed that foo exists in the current scope and returns an Option<T> ) |
Option | default = "4" | Some(4) (the value is automatically converted into a Some<T> ) |
Option<&str> | default = "Hello" | Some("Hello") |
Option | default = "Hello" | Some(String::from("Hello")) (first the content of the quotes is converted into a String, then it is converted into a Some<String> ****) |
Remark: If you need to be 100% sure that the value is converted into the correct type, you can use the raw string representation (e.g. default = r#"Some(1+2+3)"#
).