Skip to content

Commit 11fc5f7

Browse files
authored
correct generation of unused default functions (#990)
1 parent 42b13da commit 11fc5f7

File tree

4 files changed

+157
-3
lines changed

4 files changed

+157
-3
lines changed

typify-impl/src/defaults.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ impl TypeEntry {
137137
/// The return value indicates whether the default is the "intrinsic",
138138
/// typical default for the given type, can be handled by generic function,
139139
/// or requires a bespoke function to generate the value. This contains
140-
/// additional validation logic compared with [`value()`] but is able to skip the parts where we actually emit code.
140+
/// additional validation logic compared with [`value()`] but is able to
141+
/// skip the parts where we actually emit code.
141142
///
142143
/// [`Value`]: serde_json::Value
143144
pub(crate) fn validate_value(
@@ -172,7 +173,11 @@ impl TypeEntry {
172173
}
173174

174175
TypeEntryDetails::Newtype(TypeEntryNewtype { type_id, .. }) => {
175-
validate_type_id(type_id, type_space, default)
176+
// Validate the inner type, but irrespective of the result,
177+
// we'll need a custom function to make a default of the outer
178+
// newtype.
179+
let _ = validate_type_id(type_id, type_space, default)?;
180+
Ok(DefaultKind::Specific)
176181
}
177182
TypeEntryDetails::Option(type_id) => {
178183
if let serde_json::Value::Null = default {

typify-impl/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use std::collections::{BTreeMap, BTreeSet};
88

99
use conversions::SchemaCache;
10-
use log::info;
10+
use log::{debug, info};
1111
use output::OutputSpace;
1212
use proc_macro2::TokenStream;
1313
use quote::{format_ident, quote, ToTokens};
@@ -696,6 +696,7 @@ impl TypeSpace {
696696
for index in base_id..self.next_id {
697697
let type_id = TypeId(index);
698698
let mut type_entry = self.id_to_entry.get(&type_id).unwrap().clone();
699+
debug!("finalizing type entry: {} {:#?}", index, &type_entry);
699700
type_entry.finalize(self)?;
700701
self.id_to_entry.insert(type_id, type_entry);
701702
}

typify/tests/schemas/types-with-defaults.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,22 @@
8585
"default": 1
8686
}
8787
}
88+
},
89+
"UInt": {
90+
"type": "integer"
91+
},
92+
"UIntContainer": {
93+
"type": "object",
94+
"properties": {
95+
"max_path": {
96+
"default": 1,
97+
"allOf": [
98+
{
99+
"$ref": "#/$definitions/UInt"
100+
}
101+
]
102+
}
103+
}
88104
}
89105
}
90106
}

typify/tests/schemas/types-with-defaults.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,95 @@ impl ThingWithDefaults {
262262
Default::default()
263263
}
264264
}
265+
#[doc = "`UInt`"]
266+
#[doc = r""]
267+
#[doc = r" <details><summary>JSON schema</summary>"]
268+
#[doc = r""]
269+
#[doc = r" ```json"]
270+
#[doc = "{"]
271+
#[doc = " \"type\": \"integer\""]
272+
#[doc = "}"]
273+
#[doc = r" ```"]
274+
#[doc = r" </details>"]
275+
#[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)]
276+
#[serde(transparent)]
277+
pub struct UInt(pub i64);
278+
impl ::std::ops::Deref for UInt {
279+
type Target = i64;
280+
fn deref(&self) -> &i64 {
281+
&self.0
282+
}
283+
}
284+
impl ::std::convert::From<UInt> for i64 {
285+
fn from(value: UInt) -> Self {
286+
value.0
287+
}
288+
}
289+
impl ::std::convert::From<i64> for UInt {
290+
fn from(value: i64) -> Self {
291+
Self(value)
292+
}
293+
}
294+
impl ::std::str::FromStr for UInt {
295+
type Err = <i64 as ::std::str::FromStr>::Err;
296+
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
297+
Ok(Self(value.parse()?))
298+
}
299+
}
300+
impl ::std::convert::TryFrom<&str> for UInt {
301+
type Error = <i64 as ::std::str::FromStr>::Err;
302+
fn try_from(value: &str) -> ::std::result::Result<Self, Self::Error> {
303+
value.parse()
304+
}
305+
}
306+
impl ::std::convert::TryFrom<String> for UInt {
307+
type Error = <i64 as ::std::str::FromStr>::Err;
308+
fn try_from(value: String) -> ::std::result::Result<Self, Self::Error> {
309+
value.parse()
310+
}
311+
}
312+
impl ::std::fmt::Display for UInt {
313+
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
314+
self.0.fmt(f)
315+
}
316+
}
317+
#[doc = "`UIntContainer`"]
318+
#[doc = r""]
319+
#[doc = r" <details><summary>JSON schema</summary>"]
320+
#[doc = r""]
321+
#[doc = r" ```json"]
322+
#[doc = "{"]
323+
#[doc = " \"type\": \"object\","]
324+
#[doc = " \"properties\": {"]
325+
#[doc = " \"max_path\": {"]
326+
#[doc = " \"default\": 1,"]
327+
#[doc = " \"allOf\": ["]
328+
#[doc = " {"]
329+
#[doc = " \"$ref\": \"#/$definitions/UInt\""]
330+
#[doc = " }"]
331+
#[doc = " ]"]
332+
#[doc = " }"]
333+
#[doc = " }"]
334+
#[doc = "}"]
335+
#[doc = r" ```"]
336+
#[doc = r" </details>"]
337+
#[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)]
338+
pub struct UIntContainer {
339+
#[serde(default = "defaults::u_int_container_max_path")]
340+
pub max_path: UInt,
341+
}
342+
impl ::std::default::Default for UIntContainer {
343+
fn default() -> Self {
344+
Self {
345+
max_path: defaults::u_int_container_max_path(),
346+
}
347+
}
348+
}
349+
impl UIntContainer {
350+
pub fn builder() -> builder::UIntContainer {
351+
Default::default()
352+
}
353+
}
265354
#[doc = r" Types for composing complex structures."]
266355
pub mod builder {
267356
#[derive(Clone, Debug)]
@@ -527,6 +616,46 @@ pub mod builder {
527616
}
528617
}
529618
}
619+
#[derive(Clone, Debug)]
620+
pub struct UIntContainer {
621+
max_path: ::std::result::Result<super::UInt, ::std::string::String>,
622+
}
623+
impl ::std::default::Default for UIntContainer {
624+
fn default() -> Self {
625+
Self {
626+
max_path: Ok(super::defaults::u_int_container_max_path()),
627+
}
628+
}
629+
}
630+
impl UIntContainer {
631+
pub fn max_path<T>(mut self, value: T) -> Self
632+
where
633+
T: ::std::convert::TryInto<super::UInt>,
634+
T::Error: ::std::fmt::Display,
635+
{
636+
self.max_path = value
637+
.try_into()
638+
.map_err(|e| format!("error converting supplied value for max_path: {e}"));
639+
self
640+
}
641+
}
642+
impl ::std::convert::TryFrom<UIntContainer> for super::UIntContainer {
643+
type Error = super::error::ConversionError;
644+
fn try_from(
645+
value: UIntContainer,
646+
) -> ::std::result::Result<Self, super::error::ConversionError> {
647+
Ok(Self {
648+
max_path: value.max_path?,
649+
})
650+
}
651+
}
652+
impl ::std::convert::From<super::UIntContainer> for UIntContainer {
653+
fn from(value: super::UIntContainer) -> Self {
654+
Self {
655+
max_path: Ok(value.max_path),
656+
}
657+
}
658+
}
530659
}
531660
#[doc = r" Generation of default values for serde."]
532661
pub mod defaults {
@@ -556,5 +685,8 @@ pub mod defaults {
556685
pub(super) fn test_bed_id() -> ::uuid::Uuid {
557686
::serde_json::from_str::<::uuid::Uuid>("\"abc123-is-this-a-uuid\"").unwrap()
558687
}
688+
pub(super) fn u_int_container_max_path() -> super::UInt {
689+
super::UInt(1_i64)
690+
}
559691
}
560692
fn main() {}

0 commit comments

Comments
 (0)