# relax Derive partial (“relaxed”) types ## Usage ### Generate “relaxed” types ```rust use relax::Relax; #[derive(Relax)] #[relax(PartialData)] pub(crate) struct Data { id: u16, pub name: String, pub favorite: Option, } ``` yields the following partial (“relaxed”) struct: ```rust pub(crate) struct PartialData { id: Option, pub name: Option, pub favorite: Option, } ``` Nesting is also supported: ```rust use relax::Relax; #[derive(Relax)] #[relax(PartialFoo)] struct Foo { id: u16, #[relax] bar: Bar, #[relax] bar2: Option, } #[derive(Relax)] #[relax(PartialBar)] struct Bar { name: String, favorite: Option, } ``` yields ```rust struct PatrialFoo { id: Option, bar: Option, bar2: Option, } struct PartialBar { name: Option, favorite: Option, } ``` You can also add attributes to generated structs: ```rust use relax::Relax; use serde::{Serialize, Deserialize}; #[derive(Relax)] #[relax(PartialData, derive(Serialize, Deserialize), serde(rename_all = "UPPERCASE"))] pub(crate) struct Data { id: u16, pub name: String, pub favorite: Option, } ``` yields ```rust #[derive(Serialize, Deserialize)] #[serde(rename_all = "UPPERCASE")] pub(crate) struct PartialData { id: Option, pub name: Option, pub favorite: Option, } ``` ### Create empty “relaxed” instances Relaxed structs derive `Relaxed` trait, which has `new` associated function. ```rust use relax::{Relax, Relaxed}; #[derive(Relax)] #[relax(PartialData, derive(Debug, PartialEq))] pub(crate) struct Data { id: u16, pub name: String, pub favorite: Option, } let empty = PartialData { id: None, name: None, favorite: None, }; assert_eq!(PartialData::new(), empty); ``` ### Combine multiple “relaxed” instances `Relaxed` trait also has `merge` function. The behavior is similar to `Option::or`, except that this function is applied for each struct field. ```rust use relax::{Relax, Relaxed}; #[derive(Relax)] #[relax(PartialData, derive(Debug, PartialEq))] pub(crate) struct Data { id: u16, pub name: String, pub favorite: Option, } let partial_data_1 = PartialData { id: None, name: Some("John".to_owned()), favorite: None, }; let partial_data_2 = PartialData { id: None, name: None, favorite: Some("Rust".to_owned()), }; let merged = partial_data_1.merge(partial_data_2); let expected = PartialData { id: None, name: Some("John".to_owned()), favorite: Some("Rust".to_owned()), }; assert_eq!(merged, expected); ``` ### Create an original struct instance from a relaxed instance If all the required fields of the original struct are set in a relaxed struct instance, you can use `try_into()` to convert it to the original struct. ```rust use relax::{Relax, Relaxed}; let partial_data_1: PartialData = read_data(file_1); let partial_data_2: PartialData = read_data(file_2); let partial_data_3: PartialData = read_data(file_3); let data: Data = partial_data_1 .merge(partial_data_2) .merge(partial_data_3) .try_into()?; ```