Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions typify-impl/src/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ impl TypeEntry {
/// The return value indicates whether the default is the "intrinsic",
/// typical default for the given type, can be handled by generic function,
/// or requires a bespoke function to generate the value. This contains
/// additional validation logic compared with [`value()`] but is able to skip the parts where we actually emit code.
/// additional validation logic compared with [`value()`] but is able to
/// skip the parts where we actually emit code.
///
/// [`Value`]: serde_json::Value
pub(crate) fn validate_value(
Expand Down Expand Up @@ -172,7 +173,11 @@ impl TypeEntry {
}

TypeEntryDetails::Newtype(TypeEntryNewtype { type_id, .. }) => {
validate_type_id(type_id, type_space, default)
// Validate the inner type, but irrespective of the result,
// we'll need a custom function to make a default of the outer
// newtype.
let _ = validate_type_id(type_id, type_space, default)?;
Ok(DefaultKind::Specific)
}
TypeEntryDetails::Option(type_id) => {
if let serde_json::Value::Null = default {
Expand Down
3 changes: 2 additions & 1 deletion typify-impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use std::collections::{BTreeMap, BTreeSet};

use conversions::SchemaCache;
use log::info;
use log::{debug, info};
use output::OutputSpace;
use proc_macro2::TokenStream;
use quote::{format_ident, quote, ToTokens};
Expand Down Expand Up @@ -696,6 +696,7 @@ impl TypeSpace {
for index in base_id..self.next_id {
let type_id = TypeId(index);
let mut type_entry = self.id_to_entry.get(&type_id).unwrap().clone();
debug!("finalizing type entry: {} {:#?}", index, &type_entry);
type_entry.finalize(self)?;
self.id_to_entry.insert(type_id, type_entry);
}
Expand Down
16 changes: 16 additions & 0 deletions typify/tests/schemas/types-with-defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@
"default": 1
}
}
},
"UInt": {
"type": "integer"
},
"UIntContainer": {
"type": "object",
"properties": {
"max_path": {
"default": 1,
"allOf": [
{
"$ref": "#/$definitions/UInt"
}
]
}
}
}
}
}
132 changes: 132 additions & 0 deletions typify/tests/schemas/types-with-defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,95 @@ impl ThingWithDefaults {
Default::default()
}
}
#[doc = "`UInt`"]
#[doc = r""]
#[doc = r" <details><summary>JSON schema</summary>"]
#[doc = r""]
#[doc = r" ```json"]
#[doc = "{"]
#[doc = " \"type\": \"integer\""]
#[doc = "}"]
#[doc = r" ```"]
#[doc = r" </details>"]
#[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct UInt(pub i64);
impl ::std::ops::Deref for UInt {
type Target = i64;
fn deref(&self) -> &i64 {
&self.0
}
}
impl ::std::convert::From<UInt> for i64 {
fn from(value: UInt) -> Self {
value.0
}
}
impl ::std::convert::From<i64> for UInt {
fn from(value: i64) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for UInt {
type Err = <i64 as ::std::str::FromStr>::Err;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.parse()?))
}
}
impl ::std::convert::TryFrom<&str> for UInt {
type Error = <i64 as ::std::str::FromStr>::Err;
fn try_from(value: &str) -> ::std::result::Result<Self, Self::Error> {
value.parse()
}
}
impl ::std::convert::TryFrom<String> for UInt {
type Error = <i64 as ::std::str::FromStr>::Err;
fn try_from(value: String) -> ::std::result::Result<Self, Self::Error> {
value.parse()
}
}
impl ::std::fmt::Display for UInt {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
#[doc = "`UIntContainer`"]
#[doc = r""]
#[doc = r" <details><summary>JSON schema</summary>"]
#[doc = r""]
#[doc = r" ```json"]
#[doc = "{"]
#[doc = " \"type\": \"object\","]
#[doc = " \"properties\": {"]
#[doc = " \"max_path\": {"]
#[doc = " \"default\": 1,"]
#[doc = " \"allOf\": ["]
#[doc = " {"]
#[doc = " \"$ref\": \"#/$definitions/UInt\""]
#[doc = " }"]
#[doc = " ]"]
#[doc = " }"]
#[doc = " }"]
#[doc = "}"]
#[doc = r" ```"]
#[doc = r" </details>"]
#[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)]
pub struct UIntContainer {
#[serde(default = "defaults::u_int_container_max_path")]
pub max_path: UInt,
}
impl ::std::default::Default for UIntContainer {
fn default() -> Self {
Self {
max_path: defaults::u_int_container_max_path(),
}
}
}
impl UIntContainer {
pub fn builder() -> builder::UIntContainer {
Default::default()
}
}
#[doc = r" Types for composing complex structures."]
pub mod builder {
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -527,6 +616,46 @@ pub mod builder {
}
}
}
#[derive(Clone, Debug)]
pub struct UIntContainer {
max_path: ::std::result::Result<super::UInt, ::std::string::String>,
}
impl ::std::default::Default for UIntContainer {
fn default() -> Self {
Self {
max_path: Ok(super::defaults::u_int_container_max_path()),
}
}
}
impl UIntContainer {
pub fn max_path<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::UInt>,
T::Error: ::std::fmt::Display,
{
self.max_path = value
.try_into()
.map_err(|e| format!("error converting supplied value for max_path: {e}"));
self
}
}
impl ::std::convert::TryFrom<UIntContainer> for super::UIntContainer {
type Error = super::error::ConversionError;
fn try_from(
value: UIntContainer,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
max_path: value.max_path?,
})
}
}
impl ::std::convert::From<super::UIntContainer> for UIntContainer {
fn from(value: super::UIntContainer) -> Self {
Self {
max_path: Ok(value.max_path),
}
}
}
}
#[doc = r" Generation of default values for serde."]
pub mod defaults {
Expand Down Expand Up @@ -556,5 +685,8 @@ pub mod defaults {
pub(super) fn test_bed_id() -> ::uuid::Uuid {
::serde_json::from_str::<::uuid::Uuid>("\"abc123-is-this-a-uuid\"").unwrap()
}
pub(super) fn u_int_container_max_path() -> super::UInt {
super::UInt(1_i64)
}
}
fn main() {}