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
validateattribute 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
Defaulttrait). - If the attribute
defaultis 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, } }awill 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, } }awill 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 = 10ordefault = 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
&strthe value of the default attribute is kept as it is. - if the type is
Stringth 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
Nonethen 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)"#).