Skip to content

Commit

Permalink
handle default values for fields represented as NonZeroU{8,16,32} (#608)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahl authored Jun 12, 2024
1 parent e6905e0 commit d36f65e
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 3 deletions.
27 changes: 24 additions & 3 deletions typify-impl/src/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ impl From<&DefaultImpl> for TokenStream {
T::try_from(V).unwrap()
}
},
DefaultImpl::NZU64 => quote! {
pub(super) fn default_nzu64<T, const V: u64>() -> T
where
T: std::convert::TryFrom<std::num::NonZeroU64>,
<T as std::convert::TryFrom<std::num::NonZeroU64>>::Error:
std::fmt::Debug,
{
T::try_from(std::num::NonZeroU64::try_from(V).unwrap())
.unwrap()
}
},
}
}
}
Expand Down Expand Up @@ -272,11 +283,17 @@ impl TypeEntry {
},
// Note that min and max values are handled already by the
// conversion routines since we have those close at hand.
TypeEntryDetails::Integer(_) => match (default.as_u64(), default.as_i64()) {
TypeEntryDetails::Integer(itype) => match (default.as_u64(), default.as_i64()) {
(None, None) => Err(Error::invalid_value()),
(Some(0), _) => Ok(DefaultKind::Intrinsic),
(_, Some(0)) => unreachable!(),
(Some(_), _) => Ok(DefaultKind::Generic(DefaultImpl::U64)),
(Some(_), _) => {
if itype.starts_with("std::num::NonZero") {
Ok(DefaultKind::Generic(DefaultImpl::NZU64))
} else {
Ok(DefaultKind::Generic(DefaultImpl::U64))
}
}
(_, Some(_)) => Ok(DefaultKind::Generic(DefaultImpl::I64)),
},
TypeEntryDetails::Float(_) => {
Expand Down Expand Up @@ -319,7 +336,11 @@ impl TypeEntry {
TypeEntryDetails::Boolean => Some("defaults::default_bool::<true>".to_string()),
TypeEntryDetails::Integer(name) => {
if let Some(value) = default.as_u64() {
Some(format!("defaults::default_u64::<{}, {}>", name, value))
if name.starts_with("std::num::NonZero") {
Some(format!("defaults::default_nzu64::<{}, {}>", name, value))
} else {
Some(format!("defaults::default_u64::<{}, {}>", name, value))
}
} else if let Some(value) = default.as_i64() {
Some(format!("defaults::default_i64::<{}, {}>", name, value))
} else {
Expand Down
1 change: 1 addition & 0 deletions typify-impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ pub(crate) enum DefaultImpl {
Boolean,
I64,
U64,
NZU64,
}

/// Settings that alter type generation.
Expand Down
17 changes: 17 additions & 0 deletions typify/tests/schemas/types-with-defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,23 @@
"default": "1970-01-01T00:00:00Z"
}
}
},
"MrDefaultNumbers": {
"type": "object",
"properties": {
"little_u8": {
"type": "integer",
"format": "uint8",
"minimum": 1,
"default": 2
},
"little_u16": {
"type": "integer",
"format": "uint16",
"minimum": 1,
"default": 3
}
}
}
}
}
43 changes: 43 additions & 0 deletions typify/tests/schemas/types-with-defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,42 @@ impl From<&Doodad> for Doodad {
value.clone()
}
}
#[doc = "MrDefaultNumbers"]
#[doc = r""]
#[doc = r" <details><summary>JSON schema</summary>"]
#[doc = r""]
#[doc = r" ```json"]
#[doc = "{"]
#[doc = " \"type\": \"object\","]
#[doc = " \"properties\": {"]
#[doc = " \"little_u16\": {"]
#[doc = " \"default\": 3,"]
#[doc = " \"type\": \"integer\","]
#[doc = " \"format\": \"uint16\","]
#[doc = " \"minimum\": 1.0"]
#[doc = " },"]
#[doc = " \"little_u8\": {"]
#[doc = " \"default\": 2,"]
#[doc = " \"type\": \"integer\","]
#[doc = " \"format\": \"uint8\","]
#[doc = " \"minimum\": 1.0"]
#[doc = " }"]
#[doc = " }"]
#[doc = "}"]
#[doc = r" ```"]
#[doc = r" </details>"]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MrDefaultNumbers {
#[serde(default = "defaults::default_nzu64::<std::num::NonZeroU16, 3>")]
pub little_u16: std::num::NonZeroU16,
#[serde(default = "defaults::default_nzu64::<std::num::NonZeroU8, 2>")]
pub little_u8: std::num::NonZeroU8,
}
impl From<&MrDefaultNumbers> for MrDefaultNumbers {
fn from(value: &MrDefaultNumbers) -> Self {
value.clone()
}
}
#[doc = "OuterThing"]
#[doc = r""]
#[doc = r" <details><summary>JSON schema</summary>"]
Expand Down Expand Up @@ -183,6 +219,13 @@ impl Default for ThingWithDefaults {
}
#[doc = r" Generation of default values for serde."]
pub mod defaults {
pub(super) fn default_nzu64<T, const V: u64>() -> T
where
T: std::convert::TryFrom<std::num::NonZeroU64>,
<T as std::convert::TryFrom<std::num::NonZeroU64>>::Error: std::fmt::Debug,
{
T::try_from(std::num::NonZeroU64::try_from(V).unwrap()).unwrap()
}
pub(super) fn doodad_when() -> chrono::DateTime<chrono::offset::Utc> {
serde_json::from_str::<chrono::DateTime<chrono::offset::Utc>>("\"1970-01-01T00:00:00Z\"")
.unwrap()
Expand Down

0 comments on commit d36f65e

Please sign in to comment.