diff --git a/typify-impl/src/value.rs b/typify-impl/src/value.rs
index 4e9e13c8..d4dfd9d7 100644
--- a/typify-impl/src/value.rs
+++ b/typify-impl/src/value.rs
@@ -8,8 +8,9 @@ use quote::{format_ident, quote};
use crate::{
convert::STD_NUM_NONZERO_PREFIX,
type_entry::{
- EnumTagType, StructProperty, StructPropertyRename, TypeEntry, TypeEntryDetails,
- TypeEntryEnum, TypeEntryNative, TypeEntryNewtype, TypeEntryStruct, Variant, VariantDetails,
+ EnumTagType, StructProperty, StructPropertyRename, StructPropertyState, TypeEntry,
+ TypeEntryDetails, TypeEntryEnum, TypeEntryNative, TypeEntryNewtype, TypeEntryStruct,
+ Variant, VariantDetails,
},
TypeId, TypeSpace,
};
@@ -398,9 +399,18 @@ fn value_for_struct_props(
let type_entry = type_space.id_to_entry.get(&prop.type_id).unwrap();
let prop_value = type_entry.output_value(type_space, value, scope)?;
+ Some(quote! { #name_ident: #prop_value })
+ } else if let StructPropertyState::Default(default) = &prop.state {
+ // The property is absent from the whole-type default value, but it
+ // declares its own default. Use that so that `T::default()` agrees
+ // with deserializing the (partial) default value, which fills in
+ // absent properties via their serde default functions.
+ let type_entry = type_space.id_to_entry.get(&prop.type_id).unwrap();
+ let prop_value = type_entry.output_value(type_space, &default.0, scope)?;
+
Some(quote! { #name_ident: #prop_value })
} else {
- Some(quote! { #name_ident: Default::default() })
+ Some(quote! { #name_ident: ::std::default::Default::default() })
}
});
@@ -643,7 +653,7 @@ mod tests {
a: "aaaa".to_string(),
b: 7_u32,
c: ::std::option::Option::Some("cccc".to_string()),
- d: Default::default()
+ d: ::std::default::Default::default()
}
}
.to_string()
@@ -685,7 +695,7 @@ mod tests {
a: "aaaa".to_string(),
b: 7_u32,
c: ::std::option::Option::Some("cccc".to_string()),
- d: Default::default()
+ d: ::std::default::Default::default()
}
}
.to_string()
diff --git a/typify/tests/schemas/types-with-defaults.json b/typify/tests/schemas/types-with-defaults.json
index f3666710..613e145b 100644
--- a/typify/tests/schemas/types-with-defaults.json
+++ b/typify/tests/schemas/types-with-defaults.json
@@ -86,6 +86,47 @@
}
}
},
+ "SeparatorConfig": {
+ "type": "object",
+ "additionalProperties": false,
+ "default": {},
+ "properties": {
+ "lineThickness": {
+ "type": "integer",
+ "default": 1
+ },
+ "lineColor": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "default": "#B2000000"
+ }
+ }
+ },
+ "SeparatorHolder": {
+ "type": "object",
+ "properties": {
+ "separatorAll": {
+ "default": {},
+ "allOf": [
+ {
+ "$ref": "#/definitions/SeparatorConfig"
+ }
+ ]
+ },
+ "separatorSome": {
+ "default": {
+ "lineThickness": 5
+ },
+ "allOf": [
+ {
+ "$ref": "#/definitions/SeparatorConfig"
+ }
+ ]
+ }
+ }
+ },
"UInt": {
"type": "integer"
},
diff --git a/typify/tests/schemas/types-with-defaults.rs b/typify/tests/schemas/types-with-defaults.rs
index 383ece76..9f2db94d 100644
--- a/typify/tests/schemas/types-with-defaults.rs
+++ b/typify/tests/schemas/types-with-defaults.rs
@@ -160,6 +160,111 @@ impl OuterThing {
Default::default()
}
}
+#[doc = "`SeparatorConfig`"]
+#[doc = r""]
+#[doc = r" JSON schema
"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = " \"default\": {},"]
+#[doc = " \"type\": \"object\","]
+#[doc = " \"properties\": {"]
+#[doc = " \"lineColor\": {"]
+#[doc = " \"default\": \"#B2000000\","]
+#[doc = " \"type\": ["]
+#[doc = " \"string\","]
+#[doc = " \"null\""]
+#[doc = " ]"]
+#[doc = " },"]
+#[doc = " \"lineThickness\": {"]
+#[doc = " \"default\": 1,"]
+#[doc = " \"type\": \"integer\""]
+#[doc = " }"]
+#[doc = " },"]
+#[doc = " \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" "]
+#[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)]
+#[serde(deny_unknown_fields)]
+pub struct SeparatorConfig {
+ #[serde(
+ rename = "lineColor",
+ default = "defaults::separator_config_line_color"
+ )]
+ pub line_color: ::std::option::Option<::std::string::String>,
+ #[serde(rename = "lineThickness", default = "defaults::default_u64::")]
+ pub line_thickness: i64,
+}
+impl ::std::default::Default for SeparatorConfig {
+ fn default() -> Self {
+ Self {
+ line_color: defaults::separator_config_line_color(),
+ line_thickness: defaults::default_u64::(),
+ }
+ }
+}
+impl SeparatorConfig {
+ pub fn builder() -> builder::SeparatorConfig {
+ Default::default()
+ }
+}
+#[doc = "`SeparatorHolder`"]
+#[doc = r""]
+#[doc = r" JSON schema
"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = " \"type\": \"object\","]
+#[doc = " \"properties\": {"]
+#[doc = " \"separatorAll\": {"]
+#[doc = " \"default\": {},"]
+#[doc = " \"allOf\": ["]
+#[doc = " {"]
+#[doc = " \"$ref\": \"#/definitions/SeparatorConfig\""]
+#[doc = " }"]
+#[doc = " ]"]
+#[doc = " },"]
+#[doc = " \"separatorSome\": {"]
+#[doc = " \"default\": {"]
+#[doc = " \"lineThickness\": 5"]
+#[doc = " },"]
+#[doc = " \"allOf\": ["]
+#[doc = " {"]
+#[doc = " \"$ref\": \"#/definitions/SeparatorConfig\""]
+#[doc = " }"]
+#[doc = " ]"]
+#[doc = " }"]
+#[doc = " }"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" "]
+#[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)]
+pub struct SeparatorHolder {
+ #[serde(
+ rename = "separatorAll",
+ default = "defaults::separator_holder_separator_all"
+ )]
+ pub separator_all: SeparatorConfig,
+ #[serde(
+ rename = "separatorSome",
+ default = "defaults::separator_holder_separator_some"
+ )]
+ pub separator_some: SeparatorConfig,
+}
+impl ::std::default::Default for SeparatorHolder {
+ fn default() -> Self {
+ Self {
+ separator_all: defaults::separator_holder_separator_all(),
+ separator_some: defaults::separator_holder_separator_some(),
+ }
+ }
+}
+impl SeparatorHolder {
+ pub fn builder() -> builder::SeparatorHolder {
+ Default::default()
+ }
+}
#[doc = "`TestBed`"]
#[doc = r""]
#[doc = r" JSON schema
"]
@@ -252,7 +357,7 @@ pub struct ThingWithDefaults {
impl ::std::default::Default for ThingWithDefaults {
fn default() -> Self {
ThingWithDefaults {
- a: Default::default(),
+ a: ::std::default::Default::default(),
type_: ::std::option::Option::Some("bee".to_string()),
}
}
@@ -505,6 +610,117 @@ pub mod builder {
}
}
#[derive(Clone, Debug)]
+ pub struct SeparatorConfig {
+ line_color: ::std::result::Result<
+ ::std::option::Option<::std::string::String>,
+ ::std::string::String,
+ >,
+ line_thickness: ::std::result::Result,
+ }
+ impl ::std::default::Default for SeparatorConfig {
+ fn default() -> Self {
+ Self {
+ line_color: Ok(super::defaults::separator_config_line_color()),
+ line_thickness: Ok(super::defaults::default_u64::()),
+ }
+ }
+ }
+ impl SeparatorConfig {
+ pub fn line_color(mut self, value: T) -> Self
+ where
+ T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
+ T::Error: ::std::fmt::Display,
+ {
+ self.line_color = value
+ .try_into()
+ .map_err(|e| format!("error converting supplied value for line_color: {e}"));
+ self
+ }
+ pub fn line_thickness(mut self, value: T) -> Self
+ where
+ T: ::std::convert::TryInto,
+ T::Error: ::std::fmt::Display,
+ {
+ self.line_thickness = value
+ .try_into()
+ .map_err(|e| format!("error converting supplied value for line_thickness: {e}"));
+ self
+ }
+ }
+ impl ::std::convert::TryFrom for super::SeparatorConfig {
+ type Error = super::error::ConversionError;
+ fn try_from(
+ value: SeparatorConfig,
+ ) -> ::std::result::Result {
+ Ok(Self {
+ line_color: value.line_color?,
+ line_thickness: value.line_thickness?,
+ })
+ }
+ }
+ impl ::std::convert::From for SeparatorConfig {
+ fn from(value: super::SeparatorConfig) -> Self {
+ Self {
+ line_color: Ok(value.line_color),
+ line_thickness: Ok(value.line_thickness),
+ }
+ }
+ }
+ #[derive(Clone, Debug)]
+ pub struct SeparatorHolder {
+ separator_all: ::std::result::Result,
+ separator_some: ::std::result::Result,
+ }
+ impl ::std::default::Default for SeparatorHolder {
+ fn default() -> Self {
+ Self {
+ separator_all: Ok(super::defaults::separator_holder_separator_all()),
+ separator_some: Ok(super::defaults::separator_holder_separator_some()),
+ }
+ }
+ }
+ impl SeparatorHolder {
+ pub fn separator_all(mut self, value: T) -> Self
+ where
+ T: ::std::convert::TryInto,
+ T::Error: ::std::fmt::Display,
+ {
+ self.separator_all = value
+ .try_into()
+ .map_err(|e| format!("error converting supplied value for separator_all: {e}"));
+ self
+ }
+ pub fn separator_some(mut self, value: T) -> Self
+ where
+ T: ::std::convert::TryInto,
+ T::Error: ::std::fmt::Display,
+ {
+ self.separator_some = value
+ .try_into()
+ .map_err(|e| format!("error converting supplied value for separator_some: {e}"));
+ self
+ }
+ }
+ impl ::std::convert::TryFrom for super::SeparatorHolder {
+ type Error = super::error::ConversionError;
+ fn try_from(
+ value: SeparatorHolder,
+ ) -> ::std::result::Result {
+ Ok(Self {
+ separator_all: value.separator_all?,
+ separator_some: value.separator_some?,
+ })
+ }
+ }
+ impl ::std::convert::From for SeparatorHolder {
+ fn from(value: super::SeparatorHolder) -> Self {
+ Self {
+ separator_all: Ok(value.separator_all),
+ separator_some: Ok(value.separator_some),
+ }
+ }
+ }
+ #[derive(Clone, Debug)]
pub struct TestBed {
any: ::std::result::Result<::std::vec::Vec<::serde_json::Value>, ::std::string::String>,
id: ::std::result::Result<::uuid::Uuid, ::std::string::String>,
@@ -659,6 +875,13 @@ pub mod builder {
}
#[doc = r" Generation of default values for serde."]
pub mod defaults {
+ pub(super) fn default_u64() -> T
+ where
+ T: ::std::convert::TryFrom,
+ >::Error: ::std::fmt::Debug,
+ {
+ T::try_from(V).unwrap()
+ }
pub(super) fn default_nzu64() -> T
where
T: ::std::convert::TryFrom<::std::num::NonZeroU64>,
@@ -676,6 +899,21 @@ pub mod defaults {
{
::std::option::Option::Some(::std::num::NonZeroU64::new(1).unwrap())
}
+ pub(super) fn separator_config_line_color() -> ::std::option::Option<::std::string::String> {
+ ::std::option::Option::Some("#B2000000".to_string())
+ }
+ pub(super) fn separator_holder_separator_all() -> super::SeparatorConfig {
+ super::SeparatorConfig {
+ line_color: ::std::option::Option::Some("#B2000000".to_string()),
+ line_thickness: 1_i64,
+ }
+ }
+ pub(super) fn separator_holder_separator_some() -> super::SeparatorConfig {
+ super::SeparatorConfig {
+ line_color: ::std::option::Option::Some("#B2000000".to_string()),
+ line_thickness: 5_i64,
+ }
+ }
pub(super) fn test_bed_any() -> ::std::vec::Vec<::serde_json::Value> {
vec![
::serde_json::from_str::<::serde_json::Value>("[8,6,7]").unwrap(),