Expand description
§Using derive
§Overview
This crate contains derive macros and function-like macros for implementing
NixDeserialize and NixSerialize with less boilerplate.
§Examples
#[derive(NixDeserialize, NixSerialize)]
struct Unnamed(u64, String);#[derive(NixDeserialize, NixSerialize)]
struct Fields {
    number: u64,
    message: String,
};#[derive(NixDeserialize, NixSerialize)]
struct Ignored;§Attributes
To customize the derived trait implementations you can add attributes to containers, fields and variants.
#[derive(NixDeserialize)]
#[nix(crate="nix_compat")] // <-- This is a container attribute
struct Fields {
    number: u64,
    #[nix(version="..20")] // <-- This is a field attribute
    message: String,
};
#[derive(NixDeserialize)]
#[nix(crate="nix_compat")] // <-- This is also a container attribute
enum E {
    #[nix(version="..10")] // <-- This is a variant attribute
    A(u64),
    #[nix(version="10..")] // <-- This is also a variant attribute
    B(String),
}§Container attributes
§#[nix(from_str)]
When from_str is specified the fields are all ignored and instead a
String is first deserialized and then FromStr::from_str is used
to convert this String to the container type.
This means that the container must implement FromStr and the error
returned from the from_str must implement Display.
§Example
#[derive(NixDeserialize)]
#[nix(from_str)]
struct MyString(String);
impl std::str::FromStr for MyString {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s != "bad string" {
            Ok(MyString(s.to_string()))
        } else {
            Err("Got a bad string".to_string())
        }
    }
}§#[nix(from = "FromType")]
When from is specified the fields are all ignored and instead a
value of FromType is first deserialized and then From::from is
used to convert from this value to the container type.
This means that the container must implement From<FromType> and
FromType must implement NixDeserialize.
§Example
#[derive(NixDeserialize)]
#[nix(from="usize")]
struct MyValue(usize);
impl From<usize> for MyValue {
    fn from(val: usize) -> Self {
        MyValue(val)
    }
}§#[nix(try_from = "FromType")]
With try_from a value of FromType is first deserialized and then
TryFrom::try_from is used to convert from this value to the container
type.
This means that the container must implement TryFrom<FromType> and
FromType must implement NixDeserialize.
The error returned from try_from also needs to implement Display.
§Example
#[derive(NixDeserialize)]
#[nix(try_from="usize")]
struct WrongAnswer(usize);
impl TryFrom<usize> for WrongAnswer {
    type Error = String;
    fn try_from(val: usize) -> Result<Self, Self::Error> {
        if val != 42 {
            Ok(WrongAnswer(val))
        } else {
            Err("Got the answer to life the universe and everything".to_string())
        }
    }
}§#[nix(into = "IntoType")]
When into is specified the fields are all ignored and instead the
container type is converted to IntoType using Into::into and
IntoType is then serialized. Before converting Clone::clone is
called.
This means that the container must implement Into<IntoType> and Clone
and IntoType must implement NixSerialize.
§Example
#[derive(Clone, NixSerialize)]
#[nix(into="usize")]
struct MyValue(usize);
impl From<MyValue> for usize {
    fn from(val: MyValue) -> Self {
        val.0
    }
}§#[nix(try_into = "IntoType")]
When try_into is specified the fields are all ignored and instead the
container type is converted to IntoType using TryInto::try_into and
IntoType is then serialized. Before converting Clone::clone is
called.
This means that the container must implement TryInto<IntoType> and
Clone and IntoType must implement NixSerialize.
The error returned from try_into also needs to implement Display.
§Example
#[derive(Clone, NixSerialize)]
#[nix(try_into="usize")]
struct WrongAnswer(usize);
impl TryFrom<WrongAnswer> for usize {
    type Error = String;
    fn try_from(val: WrongAnswer) -> Result<Self, Self::Error> {
        if val.0 != 42 {
            Ok(val.0)
        } else {
            Err("Got the answer to life the universe and everything".to_string())
        }
    }
}§#[nix(display)]
When display is specified the fields are all ignored and instead the
container must implement Display and NixWrite::write_display is used to
write the container.
§Example
#[derive(NixSerialize)]
#[nix(display)]
struct WrongAnswer(usize);
impl Display for WrongAnswer {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "Wrong Answer = {}", self.0)
    }
}§#[nix(display = "path")]
When display is specified the fields are all ignored and instead the
container the specified path must point to a function that is callable as
fn(&T) -> impl Display. The result from this call is then written with
NixWrite::write_display.
For example default = "my_value" would call my_value(&self) and display = "AType::empty" would call AType::empty(&self).
§Example
#[derive(NixSerialize)]
#[nix(display = "format_it")]
struct WrongAnswer(usize);
struct WrongDisplay<'a>(&'a WrongAnswer);
impl<'a> Display for WrongDisplay<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "Wrong Answer = {}", self.0.0)
    }
}
fn format_it(value: &WrongAnswer) -> impl Display + '_ {
    WrongDisplay(value)
}§#[nix(crate = "...")]
Specify the path to the nix-compat crate instance to use when referring
to the API in the generated code. This is usually not needed.
§Variant attributes
§#[nix(version = "range")]
Specifies the protocol version range where this variant is used.
When deriving an enum the version attribute is used to select which
variant of the enum to deserialize. The range is for minor version and
the version ranges of all variants combined must cover all versions
without any overlap or the first variant that matches is selected.
§Example
#[derive(NixDeserialize)]
enum Testing {
    #[nix(version="..=18")]
    OldVersion(u64),
    #[nix(version="19..")]
    NewVersion(String),
}§Field attributes
§#[nix(version = "range")]
Specifies the protocol version range where this field is included.
The range is for minor version. For example version = "..20"
includes the field in protocol versions 1.0 to 1.19 and skips
it in version 1.20 and above.
§Example
#[derive(NixDeserialize)]
struct Field {
    number: u64,
    #[nix(version="..20")]
    messsage: String,
}§#[nix(default)]
When a field is skipped because the active protocol version falls
outside the range specified in #[nix(version = "range")]
this attribute indicates that Default::default() should be used
to get a value for the field. This is also the default
when you only specify #[nix(version = "range")].
§Example
#[derive(NixDeserialize)]
struct Field {
    number: u64,
    #[nix(version="..20", default)]
    messsage: String,
}§#[nix(default = "path")]
When a field is skipped because the active protocol version falls
outside the range specified in #[nix(version = "range")]
this attribute indicates that the function in path should be called to
get a default value for the field. The given function must be callable
as fn() -> T.
For example default = "my_value" would call my_value() and default = "AType::empty" would call AType::empty().
§Example
#[derive(NixDeserialize)]
struct Field {
    number: u64,
    #[nix(version="..20", default="missing_string")]
    messsage: String,
}
fn missing_string() -> String {
    "missing string".to_string()
}Modules§
Macros§
- nix_deserialize_ remote 
- Macro to implement NixDeserializeon a type. Sometimes you can’t use the deriver to implementNixDeserialize(like when dealing with types in Rust standard library) but don’t want to implement it yourself. So this macro can be used for those situations where you would derive using#[nix(from_str)],#[nix(from = "FromType")]or#[nix(try_from = "FromType")]if you could.
- nix_serialize_ remote 
- Macro to implement NixSerializeon a type. Sometimes you can’t use the deriver to implementNixSerialize(like when dealing with types in Rust standard library) but don’t want to implement it yourself. So this macro can be used for those situations where you would derive using#[nix(display)],#[nix(display = "path")],#[nix(store_dir_display)],#[nix(into = "IntoType")]or#[nix(try_into = "IntoType")]if you could.