1use alloc::{boxed::Box, string::String, vec::Vec};
43use core::{cmp::Ordering, marker::PhantomData, num::NonZeroU64, ops::Not};
44
45use hashbrown::HashMap;
46
47use crate::{
48 extend::{Extend, Extendable, ExtendableThing},
49 thing::{
50 ArraySchema, BoxedElemOrVec, DataSchema, DataSchemaSubtype, IntegerSchema, Maximum,
51 Minimum, NumberSchema, ObjectSchema, StringSchema, UncheckedArraySchema,
52 UncheckedDataSchemaSubtype, UncheckedObjectSchema,
53 },
54};
55
56use super::{
57 human_readable_info::{
58 impl_delegate_buildable_hr_info, BuildableHumanReadableInfo, HumanReadableInfo,
59 },
60 Error, Extended, MultiLanguageBuilder, ToExtend,
61};
62
63#[derive(Clone, Debug, Default, PartialEq)]
68pub struct UncheckedDataSchema<DS, AS, OS> {
69 attype: Option<Vec<String>>,
70 title: Option<String>,
71 titles: Option<MultiLanguageBuilder<String>>,
72 description: Option<String>,
73 descriptions: Option<MultiLanguageBuilder<String>>,
74 constant: Option<Value>,
75 default: Option<Value>,
76 unit: Option<String>,
77 one_of: Option<Vec<Self>>,
78 enumeration: Option<Vec<Value>>,
79 read_only: bool,
80 write_only: bool,
81 format: Option<String>,
82 subtype: Option<UncheckedDataSchemaSubtype<DS, AS, OS>>,
83 other: DS,
84}
85
86pub(crate) type UncheckedDataSchemaFromOther<Other> = UncheckedDataSchema<
87 <Other as ExtendableThing>::DataSchema,
88 <Other as ExtendableThing>::ArraySchema,
89 <Other as ExtendableThing>::ObjectSchema,
90>;
91
92pub(crate) type UncheckedDataSchemaMap<Other> = HashMap<
93 String,
94 UncheckedDataSchema<
95 <Other as ExtendableThing>::DataSchema,
96 <Other as ExtendableThing>::ArraySchema,
97 <Other as ExtendableThing>::ObjectSchema,
98 >,
99>;
100
101#[derive(Debug, PartialEq)]
112pub struct PartialDataSchemaBuilder<DS, AS, OS, Status> {
113 constant: Option<Value>,
114 default: Option<Value>,
115 unit: Option<String>,
116 one_of: Vec<UncheckedDataSchema<DS, AS, OS>>,
117 enumeration: Vec<Value>,
118 read_only: bool,
119 write_only: bool,
120 format: Option<String>,
121
122 pub other: DS,
124 _marker: PhantomData<Status>,
125}
126
127impl<DS, AS, OS> PartialDataSchemaBuilder<DS, AS, OS, ToExtend> {
128 pub(crate) fn empty() -> PartialDataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>
129 where
130 DS: Extendable,
131 {
132 PartialDataSchemaBuilder {
133 constant: Default::default(),
134 default: Default::default(),
135 unit: Default::default(),
136 one_of: Default::default(),
137 enumeration: Default::default(),
138 read_only: Default::default(),
139 write_only: Default::default(),
140 format: Default::default(),
141 other: DS::empty(),
142 _marker: PhantomData,
143 }
144 }
145}
146
147impl<DS, AS, OS> PartialDataSchemaBuilder<DS, AS, OS, ToExtend> {
148 pub fn ext_with<F, T>(self, f: F) -> PartialDataSchemaBuilder<DS::Target, AS, OS, ToExtend>
150 where
151 F: FnOnce() -> T,
152 DS: Extend<T>,
153 {
154 let Self {
155 constant,
156 default,
157 unit,
158 one_of: _,
159 enumeration,
160 read_only,
161 write_only,
162 format,
163 other,
164 _marker,
165 } = self;
166 let other = other.ext_with(f);
167 PartialDataSchemaBuilder {
168 constant,
169 default,
170 unit,
171 one_of: Default::default(),
172 enumeration,
173 read_only,
174 write_only,
175 format,
176 other,
177 _marker,
178 }
179 }
180
181 #[inline]
183 pub fn ext<T>(self, t: T) -> PartialDataSchemaBuilder<DS::Target, AS, OS, ToExtend>
184 where
185 DS: Extend<T>,
186 {
187 self.ext_with(|| t)
188 }
189
190 pub fn finish_extend(self) -> PartialDataSchemaBuilder<DS, AS, OS, Extended> {
192 let Self {
193 constant,
194 default,
195 unit,
196 one_of,
197 enumeration,
198 read_only,
199 write_only,
200 format,
201 other,
202 _marker: _,
203 } = self;
204 PartialDataSchemaBuilder {
205 constant,
206 default,
207 unit,
208 one_of,
209 enumeration,
210 read_only,
211 write_only,
212 format,
213 other,
214 _marker: PhantomData,
215 }
216 }
217}
218
219impl<DS, AS, OS> Default for PartialDataSchemaBuilder<DS, AS, OS, Extended>
220where
221 DS: Default,
222{
223 fn default() -> Self {
224 Self {
225 constant: Default::default(),
226 default: Default::default(),
227 unit: Default::default(),
228 one_of: Default::default(),
229 enumeration: Default::default(),
230 read_only: Default::default(),
231 write_only: Default::default(),
232 format: Default::default(),
233 other: Default::default(),
234 _marker: Default::default(),
235 }
236 }
237}
238
239#[derive(Debug, Default, PartialEq)]
244pub struct PartialDataSchema<DS, AS, OS> {
245 pub(super) constant: Option<Value>,
246 pub(super) default: Option<Value>,
247 pub(super) unit: Option<String>,
248 pub(super) one_of: Option<Vec<UncheckedDataSchema<DS, AS, OS>>>,
249 pub(super) enumeration: Option<Vec<Value>>,
250 pub(super) read_only: bool,
251 pub(super) write_only: bool,
252 pub(super) format: Option<String>,
253 pub(super) subtype: Option<UncheckedDataSchemaSubtype<DS, AS, OS>>,
254
255 pub other: DS,
257}
258
259#[derive(Debug, PartialEq)]
369pub struct DataSchemaBuilder<DS, AS, OS, Status> {
370 partial: PartialDataSchemaBuilder<DS, AS, OS, Status>,
371 info: HumanReadableInfo,
372}
373
374impl<DS, AS, OS> DataSchemaBuilder<DS, AS, OS, ToExtend> {
375 pub fn ext_with<F, T>(self, f: F) -> DataSchemaBuilder<DS::Target, AS, OS, ToExtend>
377 where
378 F: FnOnce() -> T,
379 DS: Extend<T>,
380 {
381 let Self { partial, info } = self;
382 let partial = partial.ext_with(f);
383 DataSchemaBuilder { partial, info }
384 }
385
386 #[inline]
388 pub fn ext<T>(self, t: T) -> DataSchemaBuilder<DS::Target, AS, OS, ToExtend>
389 where
390 DS: Extend<T>,
391 {
392 self.ext_with(|| t)
393 }
394
395 pub fn finish_extend(self) -> DataSchemaBuilder<DS, AS, OS, Extended> {
397 let Self { partial, info } = self;
398 let partial = partial.finish_extend();
399 DataSchemaBuilder { partial, info }
400 }
401}
402
403impl<DS, AS, OS> DataSchemaBuilder<DS, AS, OS, ToExtend> {
404 pub(crate) fn empty() -> DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>
405 where
406 DS: Extendable,
407 {
408 DataSchemaBuilder {
409 partial: PartialDataSchemaBuilder::<DS, _, _, _>::empty(),
410 info: Default::default(),
411 }
412 }
413}
414
415impl<DS, AS, OS> Default for DataSchemaBuilder<DS, AS, OS, Extended>
416where
417 DS: Default,
418{
419 fn default() -> Self {
420 Self {
421 partial: Default::default(),
422 info: Default::default(),
423 }
424 }
425}
426
427pub trait BuildableDataSchema<DS, AS, OS, Status>: Sized {
436 fn unit(self, value: impl Into<String>) -> Self;
438
439 fn format(self, value: impl Into<String>) -> Self;
441
442 fn default_value(self, value: impl Into<Value>) -> Self;
444}
445
446pub trait SpecializableDataSchema<DS, AS, OS>: BuildableDataSchema<DS, AS, OS, Extended> {
458 type Stateless: BuildableDataSchema<DS, AS, OS, Extended>;
460
461 type Tuple: BuildableDataSchema<DS, AS, OS, Extended>;
463
464 type Vec: BuildableDataSchema<DS, AS, OS, Extended>;
466
467 type Number: BuildableDataSchema<DS, AS, OS, Extended>;
469
470 type Integer: BuildableDataSchema<DS, AS, OS, Extended>;
472
473 type Object: BuildableDataSchema<DS, AS, OS, Extended>;
475
476 type String: BuildableDataSchema<DS, AS, OS, Extended>;
478
479 type Constant: BuildableDataSchema<DS, AS, OS, Extended>;
481
482 fn tuple(self) -> Self::Tuple
655 where
656 AS: Default;
657
658 fn vec(self) -> Self::Vec
829 where
830 AS: Default;
831
832 fn tuple_ext<F>(self, f: F) -> Self::Tuple
903 where
904 F: FnOnce(AS::Empty) -> AS,
905 AS: Extendable;
906
907 fn vec_ext<F>(self, f: F) -> Self::Vec
977 where
978 F: FnOnce(AS::Empty) -> AS,
979 AS: Extendable;
980
981 fn bool(self) -> Self::Stateless;
983
984 fn number(self) -> Self::Number;
986
987 fn integer(self) -> Self::Integer;
989
990 fn object(self) -> Self::Object
1161 where
1162 OS: Default;
1163
1164 fn object_ext<F>(self, f: F) -> Self::Object
1234 where
1235 F: FnOnce(OS::Empty) -> OS,
1236 OS: Extendable;
1237
1238 fn string(self) -> Self::String;
1240
1241 fn null(self) -> Self::Stateless;
1243
1244 fn constant(self, value: impl Into<Value>) -> Self::Constant;
1246}
1247
1248pub trait EnumerableDataSchema<DS, AS, OS, Extended>:
1260 BuildableDataSchema<DS, AS, OS, Extended>
1261{
1262 type Target: BuildableDataSchema<DS, AS, OS, Extended>;
1264
1265 fn enumeration(self, value: impl Into<Value>) -> Self::Target;
1303}
1304
1305pub trait UnionDataSchema<DS, AS, OS>: BuildableDataSchema<DS, AS, OS, Extended> {
1316 type Target: BuildableDataSchema<DS, AS, OS, Extended>;
1318
1319 fn one_of<F, T>(self, f: F) -> Self::Target
1376 where
1377 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
1378 DS: Extendable,
1379 T: Into<UncheckedDataSchema<DS, AS, OS>>;
1380}
1381
1382pub trait ReadableWriteableDataSchema<DS, AS, OS, Extended>:
1393 BuildableDataSchema<DS, AS, OS, Extended>
1394{
1395 type ReadOnly: BuildableDataSchema<DS, AS, OS, Extended>;
1397
1398 type WriteOnly: BuildableDataSchema<DS, AS, OS, Extended>;
1400
1401 fn read_only(self) -> Self::ReadOnly;
1466
1467 fn write_only(self) -> Self::WriteOnly;
1473}
1474
1475pub struct TupleDataSchemaBuilder<Inner, DS, AS, OS> {
1478 inner: Inner,
1479 items: Vec<UncheckedDataSchema<DS, AS, OS>>,
1480
1481 pub other: AS,
1483}
1484
1485pub struct VecDataSchemaBuilder<Inner, DS, AS, OS> {
1488 inner: Inner,
1489 item: Option<UncheckedDataSchema<DS, AS, OS>>,
1490 min_items: Option<u32>,
1491 max_items: Option<u32>,
1492
1493 pub other: AS,
1495}
1496
1497pub struct NumberDataSchemaBuilder<Inner> {
1499 inner: Inner,
1500 maximum: Option<Maximum<f64>>,
1501 minimum: Option<Minimum<f64>>,
1502 multiple_of: Option<f64>,
1503}
1504
1505pub struct IntegerDataSchemaBuilder<Inner> {
1507 inner: Inner,
1508 maximum: Option<Maximum<i64>>,
1509 minimum: Option<Minimum<i64>>,
1510 multiple_of: Option<NonZeroU64>,
1511}
1512
1513pub struct ObjectDataSchemaBuilder<Inner, DS, AS, OS> {
1515 inner: Inner,
1516 properties: Vec<(String, UncheckedDataSchema<DS, AS, OS>)>,
1517 required: Vec<String>,
1518
1519 pub other: OS,
1521}
1522
1523pub struct StringDataSchemaBuilder<Inner> {
1525 inner: Inner,
1526 min_length: Option<u32>,
1527 max_length: Option<u32>,
1528 pattern: Option<String>,
1529 content_encoding: Option<String>,
1530 content_media_type: Option<String>,
1531}
1532
1533pub struct EnumDataSchemaBuilder<Inner> {
1536 inner: Inner,
1537}
1538
1539pub struct OneOfDataSchemaBuilder<Inner> {
1542 inner: Inner,
1543}
1544
1545pub enum StatelessDataSchemaType {
1547 Boolean,
1549
1550 Null,
1552}
1553
1554pub struct StatelessDataSchemaBuilder<Inner> {
1556 inner: Inner,
1557 ty: Option<StatelessDataSchemaType>,
1558}
1559
1560pub struct ReadOnly<Inner> {
1562 inner: Inner,
1563}
1564
1565pub struct WriteOnly<Inner> {
1567 inner: Inner,
1568}
1569
1570macro_rules! opt_field_decl {
1571 ($($field:ident : $ty:ty),* $(,)?) => {
1572 $(
1573 #[doc = concat!("Sets the value of the `", stringify!($field), "` field.")]
1574 fn $field(self, value: $ty) -> Self;
1575 )*
1576 };
1577}
1578
1579macro_rules! opt_field_into_decl {
1580 ($($field:ident : $ty:ty),* $(,)?) => {
1581 $(
1582 #[doc = concat!("Sets the value of the `", stringify!($field), "` field.")]
1583 fn $field(self, value: impl Into<$ty>) -> Self;
1584 )*
1585 };
1586}
1587
1588pub trait VecDataSchemaBuilderLike<DS, AS, OS> {
1591 opt_field_decl!(min_items: u32, max_items: u32);
1592
1593 fn set_item<F, T>(self, f: F) -> Self
1637 where
1638 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
1639 DS: Extendable,
1640 T: Into<UncheckedDataSchema<DS, AS, OS>>;
1641}
1642
1643pub trait TupleDataSchemaBuilderLike<DS, AS, OS> {
1645 fn append<F, T>(self, f: F) -> Self
1697 where
1698 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
1699 DS: Extendable,
1700 T: Into<UncheckedDataSchema<DS, AS, OS>>;
1701}
1702
1703pub trait NumberDataSchemaBuilderLike<DS, AS, OS> {
1705 opt_field_decl!(
1706 minimum: f64,
1707 maximum: f64,
1708 exclusive_minimum: f64,
1709 exclusive_maximum: f64,
1710 multiple_of: f64,
1711 );
1712}
1713
1714pub trait IntegerDataSchemaBuilderLike<DS, AS, OS> {
1716 opt_field_decl!(
1717 minimum: i64,
1718 maximum: i64,
1719 exclusive_minimum: i64,
1720 exclusive_maximum: i64,
1721 multiple_of: NonZeroU64,
1722 );
1723}
1724
1725pub trait ObjectDataSchemaBuilderLike<DS, AS, OS> {
1727 fn property<F, T>(self, name: impl Into<String>, required: bool, f: F) -> Self
1785 where
1786 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
1787 DS: Extendable,
1788 T: Into<UncheckedDataSchema<DS, AS, OS>>;
1789}
1790
1791pub trait StringDataSchemaBuilderLike<DS, AS, OS> {
1793 opt_field_decl!(min_length: u32, max_length: u32);
1794
1795 opt_field_into_decl!(
1796 pattern: String,
1797 content_encoding: String,
1798 content_media_type: String,
1799 );
1800}
1801
1802macro_rules! opt_field_builder {
1803 ($($field:ident : $ty:ty),* $(,)?) => {
1804 $(
1805 fn $field(mut self, value: $ty) -> Self {
1806 self.$field = Some(value);
1807 self
1808 }
1809 )*
1810 };
1811}
1812
1813macro_rules! opt_field_into_builder {
1814 ($($field:ident : $ty:ty),* $(,)?) => {
1815 $(
1816 fn $field(mut self, value: impl Into<$ty>) -> Self {
1817 self.$field = Some(value.into());
1818 self
1819 }
1820 )*
1821 };
1822}
1823
1824impl<Inner, DS, AS, OS> TupleDataSchemaBuilderLike<DS, AS, OS>
1825 for TupleDataSchemaBuilder<Inner, DS, AS, OS>
1826where
1827 Inner: BuildableDataSchema<DS, AS, OS, Extended>,
1828{
1829 fn append<F, T>(mut self, f: F) -> Self
1830 where
1831 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
1832 DS: Extendable,
1833 T: Into<UncheckedDataSchema<DS, AS, OS>>,
1834 {
1835 self.items
1836 .push(f(DataSchemaBuilder::<DS, _, _, _>::empty()).into());
1837 self
1838 }
1839}
1840
1841impl<Inner, DS, AS, OS> VecDataSchemaBuilderLike<DS, AS, OS>
1842 for VecDataSchemaBuilder<Inner, DS, AS, OS>
1843where
1844 Inner: BuildableDataSchema<DS, AS, OS, Extended>,
1845{
1846 opt_field_builder!(min_items: u32, max_items: u32);
1847
1848 fn set_item<F, T>(mut self, f: F) -> Self
1849 where
1850 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
1851 DS: Extendable,
1852 T: Into<UncheckedDataSchema<DS, AS, OS>>,
1853 {
1854 self.item = Some(f(DataSchemaBuilder::<DS, _, _, _>::empty()).into());
1855 self
1856 }
1857}
1858
1859impl<Inner: BuildableDataSchema<DS, AS, OS, Extended>, DS, AS, OS>
1860 NumberDataSchemaBuilderLike<DS, AS, OS> for NumberDataSchemaBuilder<Inner>
1861{
1862 opt_field_builder!(multiple_of: f64);
1863
1864 fn minimum(mut self, value: f64) -> Self {
1865 self.minimum = Some(Minimum::Inclusive(value));
1866 self
1867 }
1868
1869 fn exclusive_minimum(mut self, value: f64) -> Self {
1870 self.minimum = Some(Minimum::Exclusive(value));
1871 self
1872 }
1873
1874 fn maximum(mut self, value: f64) -> Self {
1875 self.maximum = Some(Maximum::Inclusive(value));
1876 self
1877 }
1878
1879 fn exclusive_maximum(mut self, value: f64) -> Self {
1880 self.maximum = Some(Maximum::Exclusive(value));
1881 self
1882 }
1883}
1884
1885impl<Inner: BuildableDataSchema<DS, AS, OS, Extended>, DS, AS, OS>
1886 IntegerDataSchemaBuilderLike<DS, AS, OS> for IntegerDataSchemaBuilder<Inner>
1887{
1888 opt_field_builder!(multiple_of: NonZeroU64);
1889
1890 fn minimum(mut self, value: i64) -> Self {
1891 self.minimum = Some(Minimum::Inclusive(value));
1892 self
1893 }
1894
1895 fn exclusive_minimum(mut self, value: i64) -> Self {
1896 self.minimum = Some(Minimum::Exclusive(value));
1897 self
1898 }
1899
1900 fn maximum(mut self, value: i64) -> Self {
1901 self.maximum = Some(Maximum::Inclusive(value));
1902 self
1903 }
1904
1905 fn exclusive_maximum(mut self, value: i64) -> Self {
1906 self.maximum = Some(Maximum::Exclusive(value));
1907 self
1908 }
1909}
1910
1911impl<Inner, DS, AS, OS> ObjectDataSchemaBuilderLike<DS, AS, OS>
1912 for ObjectDataSchemaBuilder<Inner, DS, AS, OS>
1913where
1914 Inner: BuildableDataSchema<DS, AS, OS, Extended>,
1915{
1916 fn property<F, T>(mut self, name: impl Into<String>, required: bool, f: F) -> Self
1917 where
1918 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
1919 DS: Extendable,
1920 T: Into<UncheckedDataSchema<DS, AS, OS>>,
1921 {
1922 let data_schema = f(DataSchemaBuilder::<DS, _, _, _>::empty()).into();
1923 let name = name.into();
1924
1925 if required {
1926 self.required.push(name.clone());
1927 }
1928
1929 self.properties.push((name, data_schema));
1930 self
1931 }
1932}
1933
1934impl<Inner: BuildableDataSchema<DS, AS, OS, Extended>, DS, AS, OS>
1935 StringDataSchemaBuilderLike<DS, AS, OS> for StringDataSchemaBuilder<Inner>
1936{
1937 opt_field_builder!(min_length: u32, max_length: u32);
1938
1939 opt_field_into_builder!(
1940 pattern: String,
1941 content_encoding: String,
1942 content_media_type: String,
1943 );
1944}
1945
1946macro_rules! impl_inner_delegate_schema_builder_like_vec {
1947 ($inner:ident) => {
1948 #[inline]
1949 fn min_items(mut self, value: u32) -> Self {
1950 self.$inner = self.$inner.min_items(value);
1951 self
1952 }
1953
1954 #[inline]
1955 fn max_items(mut self, value: u32) -> Self {
1956 self.$inner = self.$inner.max_items(value);
1957 self
1958 }
1959
1960 #[inline]
1961 fn set_item<F, T>(mut self, f: F) -> Self
1962 where
1963 F: FnOnce(
1964 crate::builder::data_schema::DataSchemaBuilder<
1965 <DS as Extendable>::Empty,
1966 AS,
1967 OS,
1968 crate::builder::ToExtend,
1969 >,
1970 ) -> T,
1971 DS: Extendable,
1972 T: Into<crate::builder::data_schema::UncheckedDataSchema<DS, AS, OS>>,
1973 {
1974 self.$inner = self.$inner.set_item(f);
1975 self
1976 }
1977 };
1978}
1979
1980macro_rules! impl_inner_delegate_schema_builder_like_tuple {
1981 ($inner:ident) => {
1982 #[inline]
1983 fn append<F, T>(mut self, f: F) -> Self
1984 where
1985 F: FnOnce(
1986 crate::builder::data_schema::DataSchemaBuilder<
1987 <DS as Extendable>::Empty,
1988 AS,
1989 OS,
1990 crate::builder::ToExtend,
1991 >,
1992 ) -> T,
1993 DS: Extendable,
1994 T: Into<crate::builder::data_schema::UncheckedDataSchema<DS, AS, OS>>,
1995 {
1996 self.$inner = self.$inner.append(f);
1997 self
1998 }
1999 };
2000}
2001
2002macro_rules! impl_inner_delegate_schema_builder_like_number {
2003 ($inner:ident) => {
2004 #[inline]
2005 fn minimum(mut self, value: f64) -> Self {
2006 self.$inner = self.$inner.minimum(value);
2007 self
2008 }
2009
2010 #[inline]
2011 fn maximum(mut self, value: f64) -> Self {
2012 self.$inner = self.$inner.maximum(value);
2013 self
2014 }
2015
2016 #[inline]
2017 fn exclusive_minimum(mut self, value: f64) -> Self {
2018 self.$inner = self.$inner.exclusive_minimum(value);
2019 self
2020 }
2021
2022 #[inline]
2023 fn exclusive_maximum(mut self, value: f64) -> Self {
2024 self.$inner = self.$inner.exclusive_maximum(value);
2025 self
2026 }
2027
2028 #[inline]
2029 fn multiple_of(mut self, value: f64) -> Self {
2030 self.$inner = self.$inner.multiple_of(value);
2031 self
2032 }
2033 };
2034}
2035
2036macro_rules! impl_inner_delegate_schema_builder_like_integer {
2037 ($inner:ident) => {
2038 #[inline]
2039 fn minimum(mut self, value: i64) -> Self {
2040 self.$inner = self.$inner.minimum(value);
2041 self
2042 }
2043
2044 #[inline]
2045 fn maximum(mut self, value: i64) -> Self {
2046 self.$inner = self.$inner.maximum(value);
2047 self
2048 }
2049
2050 #[inline]
2051 fn exclusive_minimum(mut self, value: i64) -> Self {
2052 self.$inner = self.$inner.exclusive_minimum(value);
2053 self
2054 }
2055
2056 #[inline]
2057 fn exclusive_maximum(mut self, value: i64) -> Self {
2058 self.$inner = self.$inner.exclusive_maximum(value);
2059 self
2060 }
2061
2062 #[inline]
2063 fn multiple_of(mut self, value: core::num::NonZeroU64) -> Self {
2064 self.$inner = self.$inner.multiple_of(value);
2065 self
2066 }
2067 };
2068}
2069
2070macro_rules! impl_inner_delegate_schema_builder_like_object {
2071 ($inner:ident) => {
2072 #[inline]
2073 fn property<F, T>(mut self, name: impl Into<String>, required: bool, f: F) -> Self
2074 where
2075 F: FnOnce(
2076 crate::builder::data_schema::DataSchemaBuilder<
2077 <DS as Extendable>::Empty,
2078 AS,
2079 OS,
2080 crate::builder::ToExtend,
2081 >,
2082 ) -> T,
2083 DS: Extendable,
2084 T: Into<crate::builder::data_schema::UncheckedDataSchema<DS, AS, OS>>,
2085 {
2086 self.$inner = self.$inner.property(name, required, f);
2087 self
2088 }
2089 };
2090}
2091
2092macro_rules! impl_delegate_schema_builder_like {
2093 ($( $ty:ident <$( $generic:ident ),+> on $inner:ident ),+ $(,)?) => {
2094 $(
2095 impl<DS, AS, OS, $($generic: crate::builder::data_schema::VecDataSchemaBuilderLike<DS, AS, OS>),+ > crate::builder::data_schema::VecDataSchemaBuilderLike<DS, AS, OS> for $ty< $($generic),+ > {
2096 crate::builder::data_schema::impl_inner_delegate_schema_builder_like_vec!($inner);
2097 }
2098
2099 impl<DS, AS, OS, $($generic: crate::builder::data_schema::TupleDataSchemaBuilderLike<DS, AS, OS>),+ > crate::builder::data_schema::TupleDataSchemaBuilderLike<DS, AS, OS> for $ty< $($generic),+ > {
2100 crate::builder::data_schema::impl_inner_delegate_schema_builder_like_tuple!($inner);
2101 }
2102
2103 impl<DS, AS, OS, $($generic: crate::builder::data_schema::NumberDataSchemaBuilderLike<DS, AS, OS>),+ > crate::builder::data_schema::NumberDataSchemaBuilderLike<DS, AS, OS> for $ty< $($generic),+ > {
2104 crate::builder::data_schema::impl_inner_delegate_schema_builder_like_number!($inner);
2105 }
2106
2107 impl<DS, AS, OS, $($generic: crate::builder::data_schema::IntegerDataSchemaBuilderLike<DS, AS, OS>),+ > crate::builder::data_schema::IntegerDataSchemaBuilderLike<DS, AS, OS> for $ty< $($generic),+ > {
2108 crate::builder::data_schema::impl_inner_delegate_schema_builder_like_integer!($inner);
2109 }
2110
2111 impl<DS, AS, OS, $($generic: crate::builder::data_schema::ObjectDataSchemaBuilderLike<DS, AS, OS>),+ > crate::builder::data_schema::ObjectDataSchemaBuilderLike<DS, AS, OS> for $ty< $($generic),+ > {
2112 crate::builder::data_schema::impl_inner_delegate_schema_builder_like_object!($inner);
2113 }
2114 )+
2115 };
2116}
2117pub(super) use impl_delegate_schema_builder_like;
2118pub(super) use impl_inner_delegate_schema_builder_like_integer;
2119pub(super) use impl_inner_delegate_schema_builder_like_number;
2120pub(super) use impl_inner_delegate_schema_builder_like_object;
2121pub(super) use impl_inner_delegate_schema_builder_like_tuple;
2122pub(super) use impl_inner_delegate_schema_builder_like_vec;
2123
2124impl_delegate_schema_builder_like!(ReadOnly<Inner> on inner, WriteOnly<Innner> on inner);
2125
2126macro_rules! buildable_data_schema_delegate {
2127 ($self:ident . $field:ident -> $fn:ident($($arg:ident),*)) => {{
2128 $self.$field = $self.$field.$fn($($arg),*);
2129 $self
2130 }};
2131}
2132
2133macro_rules! impl_delegate_buildable_data_schema {
2134 () => {};
2135
2136 ($kind:ident <DS, AS, OS $(, $($ty:ident),+)?> : $inner:ident $(, $($rest:tt)*)?) => {
2137 impl <DS, AS, OS $(, $($ty),+)? > crate::builder::data_schema::BuildableDataSchema<DS, AS, OS, crate::builder::Extended> for $kind <$($($ty),+ ,)? DS, AS, OS>
2138 $(
2139 where
2140 $($ty: crate::builder::data_schema::BuildableDataSchema<DS, AS, OS, crate::builder::Extended>),+
2141 )?
2142 {
2143 #[inline]
2144 fn unit(mut self, value: impl Into<String>) -> Self {
2145 crate::builder::data_schema::buildable_data_schema_delegate!(self.$inner -> unit(value))
2146 }
2147
2148 #[inline]
2149 fn format(mut self, value: impl Into<String>) -> Self {
2150 crate::builder::data_schema::buildable_data_schema_delegate!(self.$inner -> format(value))
2151 }
2152
2153 #[inline]
2154 fn default_value(mut self, value: impl Into<Value>) -> Self {
2155 crate::builder::data_schema::buildable_data_schema_delegate!(self.$inner -> default_value(value))
2156 }
2157 }
2158
2159 $(
2160 crate::builder::data_schema::impl_delegate_buildable_data_schema!($($rest)*);
2161 )?
2162 };
2163
2164 ($kind:ident $(<$($ty:ident),+>)? : $inner:ident $(, $($rest:tt)*)?) => {
2165 impl <DS, AS, OS, $($($ty),+)? > crate::builder::data_schema::BuildableDataSchema<DS, AS, OS, crate::builder::Extended> for $kind $(<$($ty),+>)?
2166 $(
2167 where
2168 $($ty: crate::builder::data_schema::BuildableDataSchema<DS, AS, OS, crate::builder::Extended>),+
2169 )?
2170 {
2171 #[inline]
2172 fn unit(mut self, value: impl Into<String>) -> Self {
2173 crate::builder::data_schema::buildable_data_schema_delegate!(self.$inner -> unit(value))
2174 }
2175
2176 #[inline]
2177 fn format(mut self, value: impl Into<String>) -> Self {
2178 crate::builder::data_schema::buildable_data_schema_delegate!(self.$inner -> format(value))
2179 }
2180
2181 #[inline]
2182 fn default_value(mut self, value: impl Into<Value>) -> Self {
2183 crate::builder::data_schema::buildable_data_schema_delegate!(self.$inner -> default_value(value))
2184 }
2185 }
2186
2187 $(
2188 crate::builder::data_schema::impl_delegate_buildable_data_schema!($($rest)*);
2189 )?
2190 };
2191
2192 ($kind:ident $(<$($ty:ident),+>)? $(, $($rest:tt)*)? ) => {
2193 crate::builder::data_schema::impl_delegate_buildable_data_schema!($kind $(<$($ty),+>)?: inner $(, $($rest)*)?);
2194 };
2195}
2196
2197impl_delegate_buildable_data_schema!(
2198 TupleDataSchemaBuilder<DS, AS, OS, Inner>,
2199 VecDataSchemaBuilder<DS, AS, OS, Inner>,
2200 NumberDataSchemaBuilder<Inner>,
2201 IntegerDataSchemaBuilder<Inner>,
2202 ObjectDataSchemaBuilder<DS, AS, OS, Inner>,
2203 StringDataSchemaBuilder<Inner>,
2204 StatelessDataSchemaBuilder<Inner>,
2205 ReadOnly<Inner>,
2206 WriteOnly<Inner>,
2207 EnumDataSchemaBuilder<Inner>,
2208 OneOfDataSchemaBuilder<Inner>,
2209);
2210
2211impl<DS, AS, OS, Status> BuildableDataSchema<DS, AS, OS, Status>
2212 for DataSchemaBuilder<DS, AS, OS, Status>
2213{
2214 #[inline]
2215 fn unit(mut self, value: impl Into<String>) -> Self {
2216 buildable_data_schema_delegate!(self.partial -> unit(value))
2217 }
2218
2219 #[inline]
2220 fn format(mut self, value: impl Into<String>) -> Self {
2221 buildable_data_schema_delegate!(self.partial-> format(value))
2222 }
2223
2224 #[inline]
2225 fn default_value(mut self, value: impl Into<Value>) -> Self {
2226 buildable_data_schema_delegate!(self.partial -> default_value(value))
2227 }
2228}
2229
2230pub(crate) use buildable_data_schema_delegate;
2231pub(crate) use impl_delegate_buildable_data_schema;
2232use serde_json::Value;
2233
2234macro_rules! trait_opt_field_builder {
2235 ($($field:ident : $ty:ty),* $(,)?) => {
2236 $(
2237 fn $field(mut self, value: impl Into<$ty>) -> Self {
2238 self.$field = Some(value.into());
2239 self
2240 }
2241 )*
2242 };
2243}
2244
2245impl_delegate_buildable_hr_info! (
2246 DataSchemaBuilder<DS, AS, OS, Status> on info,
2247);
2248
2249impl<DS, AS, OS, Status> BuildableDataSchema<DS, AS, OS, Status>
2250 for PartialDataSchemaBuilder<DS, AS, OS, Status>
2251{
2252 trait_opt_field_builder!(unit: String, format: String);
2253
2254 fn default_value(mut self, value: impl Into<Value>) -> Self {
2255 self.default = Some(value.into());
2256 self
2257 }
2258}
2259
2260impl_delegate_buildable_hr_info!(
2261 TupleDataSchemaBuilder<Inner: BuildableHumanReadableInfo, DS, AS, OS> on inner,
2262 VecDataSchemaBuilder<Inner: BuildableHumanReadableInfo, DS, AS, OS> on inner,
2263 NumberDataSchemaBuilder<Inner: BuildableHumanReadableInfo> on inner,
2264 IntegerDataSchemaBuilder<Inner: BuildableHumanReadableInfo> on inner,
2265 ObjectDataSchemaBuilder<Inner: BuildableHumanReadableInfo, DS, AS, OS> on inner,
2266 StringDataSchemaBuilder<Inner: BuildableHumanReadableInfo> on inner,
2267 EnumDataSchemaBuilder<Inner: BuildableHumanReadableInfo> on inner,
2268 OneOfDataSchemaBuilder<Inner: BuildableHumanReadableInfo> on inner,
2269 StatelessDataSchemaBuilder<Inner: BuildableHumanReadableInfo> on inner,
2270 ReadOnly<Inner: BuildableHumanReadableInfo> on inner,
2271 WriteOnly<Inner: BuildableHumanReadableInfo> on inner,
2272);
2273
2274macro_rules! impl_specializable_data_schema {
2275 ($($ty:ty $( : $($inner_path:ident).+ )? ),+ $(,)?) => {
2276 $(
2277 impl<DS, AS, OS> SpecializableDataSchema<DS, AS, OS> for $ty {
2278 type Stateless = StatelessDataSchemaBuilder<Self>;
2279 type Tuple = TupleDataSchemaBuilder<Self, DS, AS, OS>;
2280 type Vec = VecDataSchemaBuilder<Self, DS, AS, OS>;
2281 type Number = NumberDataSchemaBuilder<Self>;
2282 type Integer = IntegerDataSchemaBuilder<Self>;
2283 type Object = ObjectDataSchemaBuilder<Self, DS, AS, OS>;
2284 type String = StringDataSchemaBuilder<Self>;
2285 type Constant = ReadOnly<StatelessDataSchemaBuilder<Self>>;
2286
2287 fn tuple(self) -> Self::Tuple
2288 where
2289 AS: Default
2290 {
2291 TupleDataSchemaBuilder {
2292 inner: self,
2293 items: Default::default(),
2294 other: Default::default(),
2295 }
2296 }
2297
2298 fn tuple_ext<F>(self, f: F) -> Self::Tuple
2299 where
2300 F: FnOnce(AS::Empty) -> AS,
2301 AS: Extendable,
2302 {
2303 let other = f(AS::empty());
2304
2305 TupleDataSchemaBuilder {
2306 inner: self,
2307 items: Default::default(),
2308 other,
2309 }
2310 }
2311
2312 fn vec(self) -> Self::Vec
2313 where
2314 AS: Default
2315 {
2316 VecDataSchemaBuilder {
2317 inner: self,
2318 item: Default::default(),
2319 min_items: Default::default(),
2320 max_items: Default::default(),
2321 other: Default::default(),
2322 }
2323 }
2324
2325 fn vec_ext<F>(self, f: F) -> Self::Vec
2326 where
2327 F: FnOnce(AS::Empty) -> AS,
2328 AS: Extendable,
2329 {
2330 let other = f(AS::empty());
2331
2332 VecDataSchemaBuilder {
2333 inner: self,
2334 item: Default::default(),
2335 min_items: Default::default(),
2336 max_items: Default::default(),
2337 other,
2338 }
2339 }
2340
2341 fn bool(self) -> Self::Stateless {
2342 StatelessDataSchemaBuilder {
2343 inner: self,
2344 ty: Some(StatelessDataSchemaType::Boolean),
2345 }
2346 }
2347
2348 fn number(self) -> Self::Number {
2349 NumberDataSchemaBuilder {
2350 inner: self,
2351 maximum: Default::default(),
2352 minimum: Default::default(),
2353 multiple_of: Default::default(),
2354 }
2355 }
2356
2357 fn integer(self) -> Self::Integer {
2358 IntegerDataSchemaBuilder {
2359 inner: self,
2360 maximum: Default::default(),
2361 minimum: Default::default(),
2362 multiple_of: Default::default(),
2363 }
2364 }
2365
2366 fn object(self) -> Self::Object
2367 where
2368 OS: Default
2369 {
2370 ObjectDataSchemaBuilder {
2371 inner: self,
2372 properties: Default::default(),
2373 required: Default::default(),
2374 other: Default::default(),
2375 }
2376 }
2377
2378 fn object_ext<F>(self, f: F) -> Self::Object
2379 where
2380 F: FnOnce(OS::Empty) -> OS,
2381 OS: Extendable,
2382 {
2383 let other = f(OS::empty());
2384
2385 ObjectDataSchemaBuilder {
2386 inner: self,
2387 properties: Default::default(),
2388 required: Default::default(),
2389 other,
2390 }
2391 }
2392
2393 fn string(self) -> Self::String {
2394 StringDataSchemaBuilder {
2395 inner: self,
2396 min_length: Default::default(),
2397 max_length: Default::default(),
2398 pattern: Default::default(),
2399 content_encoding: Default::default(),
2400 content_media_type: Default::default(),
2401 }
2402 }
2403
2404 fn null(self) -> Self::Stateless {
2405 StatelessDataSchemaBuilder {
2406 inner: self,
2407 ty: Some(StatelessDataSchemaType::Null),
2408 }
2409 }
2410
2411 fn constant(mut self, value: impl Into<Value>) -> Self::Constant {
2412 self $(. $($inner_path).+)?.constant = Some(value.into());
2413 ReadOnly {
2414 inner: StatelessDataSchemaBuilder {
2415 inner: self,
2416 ty: None,
2417 },
2418 }
2419 }
2420 }
2421 )+
2422 };
2423}
2424
2425impl_specializable_data_schema!(PartialDataSchemaBuilder<DS, AS, OS, Extended>, DataSchemaBuilder<DS, AS, OS, Extended>: partial);
2426
2427macro_rules! impl_enumerable_data_schema {
2428 ($($ty:ty $( : $($inner_path:ident).+ )? ),+ $(,)?) => {
2429 $(
2430 impl<DS, AS, OS> EnumerableDataSchema<DS, AS, OS, Extended> for $ty {
2431 type Target = EnumDataSchemaBuilder<Self>;
2432
2433 fn enumeration(mut self, value: impl Into<Value>) -> EnumDataSchemaBuilder<Self> {
2434 self $(. $($inner_path).+ )?.enumeration.push(value.into());
2435 EnumDataSchemaBuilder { inner: self }
2436 }
2437 }
2438 )+
2439 };
2440}
2441
2442impl_enumerable_data_schema!(PartialDataSchemaBuilder<DS, AS, OS, Extended>, DataSchemaBuilder<DS, AS, OS, Extended>: partial);
2443
2444impl<Inner, DS, AS, OS> EnumerableDataSchema<DS, AS, OS, Extended> for ReadOnly<Inner>
2445where
2446 Inner: EnumerableDataSchema<DS, AS, OS, Extended>,
2447{
2448 type Target = ReadOnly<Inner::Target>;
2449
2450 #[inline]
2451 fn enumeration(self, value: impl Into<Value>) -> Self::Target {
2452 let Self { inner } = self;
2453
2454 let inner = inner.enumeration(value);
2455 ReadOnly { inner }
2456 }
2457}
2458
2459impl<Inner, DS, AS, OS> EnumerableDataSchema<DS, AS, OS, Extended> for WriteOnly<Inner>
2460where
2461 Inner: EnumerableDataSchema<DS, AS, OS, Extended>,
2462{
2463 type Target = WriteOnly<Inner::Target>;
2464
2465 #[inline]
2466 fn enumeration(self, value: impl Into<Value>) -> Self::Target {
2467 let Self { inner } = self;
2468
2469 let inner = inner.enumeration(value);
2470 WriteOnly { inner }
2471 }
2472}
2473
2474impl<DS, AS, OS> EnumerableDataSchema<DS, AS, OS, Extended>
2475 for EnumDataSchemaBuilder<PartialDataSchemaBuilder<DS, AS, OS, Extended>>
2476{
2477 type Target = Self;
2478
2479 #[inline]
2480 fn enumeration(mut self, value: impl Into<Value>) -> Self::Target {
2481 self.inner.enumeration.push(value.into());
2482 self
2483 }
2484}
2485
2486impl<DS, AS, OS> EnumerableDataSchema<DS, AS, OS, Extended>
2487 for EnumDataSchemaBuilder<DataSchemaBuilder<DS, AS, OS, Extended>>
2488{
2489 type Target = Self;
2490
2491 #[inline]
2492 fn enumeration(mut self, value: impl Into<Value>) -> Self::Target {
2493 self.inner.partial.enumeration.push(value.into());
2494 self
2495 }
2496}
2497
2498macro_rules! impl_union_data_schema {
2499 ($($ty:ty $( : $($inner_path:ident).+ )? ),+ $(,)?) => {
2500 $(
2501 impl<DS, AS, OS> UnionDataSchema<DS, AS, OS> for $ty
2502 {
2503 type Target = OneOfDataSchemaBuilder<Self>;
2504
2505 fn one_of<F, T>(mut self, f: F) -> Self::Target
2506 where
2507 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
2508 DS: Extendable,
2509 T: Into<UncheckedDataSchema<DS, AS, OS>>,
2510 {
2511 self $(. $($inner_path).+ )? .one_of.push(f(DataSchemaBuilder::<DS, _, _, _>::empty()).into());
2512 OneOfDataSchemaBuilder { inner: self }
2513 }
2514 }
2515 )+
2516 };
2517}
2518
2519impl_union_data_schema!(PartialDataSchemaBuilder<DS, AS, OS, Extended>, DataSchemaBuilder<DS, AS, OS, Extended>: partial);
2520
2521impl<Inner, DS, AS, OS> UnionDataSchema<DS, AS, OS> for ReadOnly<Inner>
2522where
2523 Inner: UnionDataSchema<DS, AS, OS>,
2524{
2525 type Target = ReadOnly<Inner::Target>;
2526
2527 fn one_of<F, T>(self, f: F) -> Self::Target
2528 where
2529 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
2530 DS: Extendable,
2531 T: Into<UncheckedDataSchema<DS, AS, OS>>,
2532 {
2533 let Self { inner } = self;
2534 let inner = inner.one_of(f);
2535 ReadOnly { inner }
2536 }
2537}
2538
2539impl<Inner, DS, AS, OS> UnionDataSchema<DS, AS, OS> for WriteOnly<Inner>
2540where
2541 Inner: UnionDataSchema<DS, AS, OS>,
2542{
2543 type Target = WriteOnly<Inner::Target>;
2544
2545 fn one_of<F, T>(self, f: F) -> Self::Target
2546 where
2547 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
2548 DS: Extendable,
2549 T: Into<UncheckedDataSchema<DS, AS, OS>>,
2550 {
2551 let Self { inner } = self;
2552 let inner = inner.one_of(f);
2553 WriteOnly { inner }
2554 }
2555}
2556
2557impl<DS, AS, OS> UnionDataSchema<DS, AS, OS>
2558 for OneOfDataSchemaBuilder<PartialDataSchemaBuilder<DS, AS, OS, Extended>>
2559{
2560 type Target = Self;
2561
2562 fn one_of<F, T>(mut self, f: F) -> Self::Target
2563 where
2564 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
2565 DS: Extendable,
2566 T: Into<UncheckedDataSchema<DS, AS, OS>>,
2567 {
2568 self.inner
2569 .one_of
2570 .push(f(DataSchemaBuilder::<DS, _, _, _>::empty()).into());
2571 self
2572 }
2573}
2574
2575impl<DS, AS, OS> UnionDataSchema<DS, AS, OS>
2576 for OneOfDataSchemaBuilder<DataSchemaBuilder<DS, AS, OS, Extended>>
2577{
2578 type Target = Self;
2579
2580 fn one_of<F, T>(mut self, f: F) -> Self::Target
2581 where
2582 F: FnOnce(DataSchemaBuilder<<DS as Extendable>::Empty, AS, OS, ToExtend>) -> T,
2583 DS: Extendable,
2584 T: Into<UncheckedDataSchema<DS, AS, OS>>,
2585 {
2586 self.inner
2587 .partial
2588 .one_of
2589 .push(f(DataSchemaBuilder::<DS, _, _, _>::empty()).into());
2590 self
2591 }
2592}
2593
2594macro_rules! impl_rw_data_schema {
2595 ($( $ty:ty; $($inner_path:ident).+ ),+ $(,)?) => {
2596 $(
2597 impl<DS, AS, OS> ReadableWriteableDataSchema<DS, AS, OS, Extended> for $ty
2598 {
2599 type ReadOnly = ReadOnly<Self>;
2600 type WriteOnly = WriteOnly<Self>;
2601
2602 #[inline]
2603 fn read_only(mut self) -> Self::ReadOnly {
2604 self.$($inner_path).+.read_only = true;
2605 ReadOnly {
2606 inner: self,
2607 }
2608 }
2609
2610 #[inline]
2611 fn write_only(mut self) -> Self::WriteOnly {
2612 self.$($inner_path).+.write_only = true;
2613 WriteOnly {
2614 inner: self,
2615 }
2616 }
2617 }
2618 )+
2619 };
2620}
2621
2622impl_rw_data_schema!(
2623 StatelessDataSchemaBuilder<DataSchemaBuilder<DS, AS, OS, Extended>>; inner.partial,
2624 StatelessDataSchemaBuilder<PartialDataSchemaBuilder<DS, AS, OS, Extended>>; inner,
2625 TupleDataSchemaBuilder<DataSchemaBuilder<DS, AS, OS, Extended>, DS, AS, OS>; inner.partial,
2626 TupleDataSchemaBuilder<PartialDataSchemaBuilder<DS, AS, OS, Extended>, DS, AS, OS>; inner,
2627 VecDataSchemaBuilder<DataSchemaBuilder<DS, AS, OS, Extended>, DS, AS, OS>; inner.partial,
2628 VecDataSchemaBuilder<PartialDataSchemaBuilder<DS, AS, OS, Extended>, DS, AS, OS>; inner,
2629 NumberDataSchemaBuilder<DataSchemaBuilder<DS, AS, OS, Extended>>; inner.partial,
2630 NumberDataSchemaBuilder<PartialDataSchemaBuilder<DS, AS, OS, Extended>>; inner,
2631 IntegerDataSchemaBuilder<DataSchemaBuilder<DS, AS, OS, Extended>>; inner.partial,
2632 IntegerDataSchemaBuilder<PartialDataSchemaBuilder<DS, AS, OS, Extended>>; inner,
2633 ObjectDataSchemaBuilder<DataSchemaBuilder<DS, AS, OS, Extended>, DS, AS, OS>; inner.partial,
2634 ObjectDataSchemaBuilder<PartialDataSchemaBuilder<DS, AS, OS, Extended>, DS, AS, OS>; inner,
2635 StringDataSchemaBuilder<DataSchemaBuilder<DS, AS, OS, Extended>>; inner.partial,
2636 StringDataSchemaBuilder<PartialDataSchemaBuilder<DS, AS, OS, Extended>>; inner,
2637 EnumDataSchemaBuilder<DataSchemaBuilder<DS, AS, OS, Extended>>; inner.partial,
2638 EnumDataSchemaBuilder<PartialDataSchemaBuilder<DS, AS, OS, Extended>>; inner,
2639);
2640
2641impl<T, DS, AS, OS> From<ReadOnly<T>> for DataSchemaBuilder<DS, AS, OS, Extended>
2642where
2643 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
2644{
2645 fn from(data_schema: ReadOnly<T>) -> Self {
2646 let DataSchemaBuilder { mut partial, info } = data_schema.inner.into();
2647 partial.read_only = true;
2648
2649 Self { partial, info }
2650 }
2651}
2652
2653impl<T, DS, AS, OS> From<WriteOnly<T>> for DataSchemaBuilder<DS, AS, OS, Extended>
2654where
2655 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
2656{
2657 fn from(data_schema: WriteOnly<T>) -> Self {
2658 let DataSchemaBuilder { mut partial, info } = data_schema.inner.into();
2659 partial.write_only = true;
2660
2661 Self { partial, info }
2662 }
2663}
2664
2665impl<T, DS, AS, OS> From<ReadOnly<T>> for PartialDataSchemaBuilder<DS, AS, OS, Extended>
2666where
2667 T: Into<PartialDataSchemaBuilder<DS, AS, OS, Extended>>,
2668{
2669 fn from(data_schema: ReadOnly<T>) -> Self {
2670 let mut data_schema = data_schema.inner.into();
2671 data_schema.read_only = true;
2672 data_schema
2673 }
2674}
2675
2676impl<T, DS, AS, OS> From<WriteOnly<T>> for PartialDataSchemaBuilder<DS, AS, OS, Extended>
2677where
2678 T: Into<PartialDataSchemaBuilder<DS, AS, OS, Extended>>,
2679{
2680 fn from(data_schema: WriteOnly<T>) -> Self {
2681 let mut data_schema = data_schema.inner.into();
2682 data_schema.write_only = true;
2683 data_schema
2684 }
2685}
2686
2687impl<DS, AS, OS> From<StatelessDataSchemaType> for UncheckedDataSchemaSubtype<DS, AS, OS> {
2688 fn from(ty: StatelessDataSchemaType) -> Self {
2689 match ty {
2690 StatelessDataSchemaType::Boolean => UncheckedDataSchemaSubtype::Boolean,
2691 StatelessDataSchemaType::Null => UncheckedDataSchemaSubtype::Null,
2692 }
2693 }
2694}
2695
2696impl<T, DS, AS, OS> From<StatelessDataSchemaBuilder<T>> for UncheckedDataSchema<DS, AS, OS>
2697where
2698 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
2699{
2700 fn from(builder: StatelessDataSchemaBuilder<T>) -> Self {
2701 let StatelessDataSchemaBuilder { inner, ty } = builder;
2702 let DataSchemaBuilder {
2703 partial:
2704 PartialDataSchemaBuilder {
2705 constant,
2706 default,
2707 unit,
2708 one_of: _,
2709 enumeration: _,
2710 read_only,
2711 write_only,
2712 format,
2713 other,
2714 _marker: _,
2715 },
2716 info:
2717 HumanReadableInfo {
2718 attype,
2719 title,
2720 titles,
2721 description,
2722 descriptions,
2723 },
2724 } = inner.into();
2725
2726 let subtype = ty.map(Into::into);
2727
2728 UncheckedDataSchema {
2729 attype,
2730 title,
2731 titles,
2732 description,
2733 descriptions,
2734 constant,
2735 default,
2736 unit,
2737 one_of: None,
2738 enumeration: None,
2739 read_only,
2740 write_only,
2741 format,
2742 subtype,
2743 other,
2744 }
2745 }
2746}
2747
2748impl<T, DS, AS, OS> TryFrom<StatelessDataSchemaBuilder<T>> for DataSchema<DS, AS, OS>
2749where
2750 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
2751{
2752 type Error = Error;
2753
2754 fn try_from(value: StatelessDataSchemaBuilder<T>) -> Result<Self, Self::Error> {
2755 let data_schema: UncheckedDataSchema<_, _, _> = value.into();
2756 data_schema.try_into()
2757 }
2758}
2759
2760impl<T, DS, AS, OS> From<StatelessDataSchemaBuilder<T>> for PartialDataSchema<DS, AS, OS>
2761where
2762 T: Into<PartialDataSchemaBuilder<DS, AS, OS, Extended>>,
2763{
2764 fn from(builder: StatelessDataSchemaBuilder<T>) -> Self {
2765 let StatelessDataSchemaBuilder { inner, ty } = builder;
2766 let PartialDataSchemaBuilder {
2767 constant,
2768 default,
2769 unit,
2770 one_of: _,
2771 enumeration: _,
2772 read_only,
2773 write_only,
2774 format,
2775 other,
2776 _marker: _,
2777 } = inner.into();
2778
2779 let subtype = ty.map(Into::into);
2780
2781 PartialDataSchema {
2782 constant,
2783 default,
2784 unit,
2785 one_of: None,
2786 enumeration: None,
2787 read_only,
2788 write_only,
2789 format,
2790 subtype,
2791 other,
2792 }
2793 }
2794}
2795
2796impl<T, DS, AS, OS> From<TupleDataSchemaBuilder<T, DS, AS, OS>> for UncheckedDataSchema<DS, AS, OS>
2797where
2798 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
2799{
2800 fn from(builder: TupleDataSchemaBuilder<T, DS, AS, OS>) -> Self {
2801 let TupleDataSchemaBuilder {
2802 inner,
2803 items,
2804 other: other_array_schema,
2805 } = builder;
2806 let DataSchemaBuilder {
2807 partial:
2808 PartialDataSchemaBuilder {
2809 constant: _,
2810 default,
2811 unit,
2812 one_of: _,
2813 enumeration: _,
2814 read_only,
2815 write_only,
2816 format,
2817 other: other_data_schema,
2818 _marker: _,
2819 },
2820 info:
2821 HumanReadableInfo {
2822 attype,
2823 title,
2824 titles,
2825 description,
2826 descriptions,
2827 },
2828 } = inner.into();
2829
2830 let items = Some(BoxedElemOrVec::Vec(items));
2831 let subtype = Some(UncheckedDataSchemaSubtype::Array(UncheckedArraySchema {
2832 items,
2833 min_items: None,
2834 max_items: None,
2835 other: other_array_schema,
2836 }));
2837
2838 UncheckedDataSchema {
2839 attype,
2840 title,
2841 titles,
2842 description,
2843 descriptions,
2844 constant: None,
2845 default,
2846 unit,
2847 one_of: None,
2848 enumeration: None,
2849 read_only,
2850 write_only,
2851 format,
2852 subtype,
2853 other: other_data_schema,
2854 }
2855 }
2856}
2857
2858impl<T, DS, AS, OS> From<VecDataSchemaBuilder<T, DS, AS, OS>> for UncheckedDataSchema<DS, AS, OS>
2859where
2860 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
2861{
2862 fn from(builder: VecDataSchemaBuilder<T, DS, AS, OS>) -> Self {
2863 let VecDataSchemaBuilder {
2864 inner,
2865 item,
2866 min_items,
2867 max_items,
2868 other: other_array_schema,
2869 } = builder;
2870 let DataSchemaBuilder {
2871 partial:
2872 PartialDataSchemaBuilder {
2873 constant: _,
2874 default,
2875 unit,
2876 one_of: _,
2877 enumeration: _,
2878 read_only,
2879 write_only,
2880 format,
2881 other: other_data_schema,
2882 _marker: _,
2883 },
2884 info:
2885 HumanReadableInfo {
2886 attype,
2887 title,
2888 titles,
2889 description,
2890 descriptions,
2891 },
2892 } = inner.into();
2893
2894 let items = item.map(|item| BoxedElemOrVec::Elem(Box::new(item)));
2895 let subtype = Some(UncheckedDataSchemaSubtype::Array(UncheckedArraySchema {
2896 items,
2897 min_items,
2898 max_items,
2899 other: other_array_schema,
2900 }));
2901
2902 UncheckedDataSchema {
2903 attype,
2904 title,
2905 titles,
2906 description,
2907 descriptions,
2908 constant: None,
2909 default,
2910 unit,
2911 one_of: None,
2912 enumeration: None,
2913 read_only,
2914 write_only,
2915 format,
2916 subtype,
2917 other: other_data_schema,
2918 }
2919 }
2920}
2921
2922impl<T, DS, AS, OS> TryFrom<TupleDataSchemaBuilder<T, DS, AS, OS>> for DataSchema<DS, AS, OS>
2923where
2924 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
2925{
2926 type Error = Error;
2927
2928 fn try_from(value: TupleDataSchemaBuilder<T, DS, AS, OS>) -> Result<Self, Self::Error> {
2929 let data_schema: UncheckedDataSchema<_, _, _> = value.into();
2930 data_schema.try_into()
2931 }
2932}
2933
2934impl<T, DS, AS, OS> TryFrom<VecDataSchemaBuilder<T, DS, AS, OS>> for DataSchema<DS, AS, OS>
2935where
2936 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
2937{
2938 type Error = Error;
2939
2940 fn try_from(value: VecDataSchemaBuilder<T, DS, AS, OS>) -> Result<Self, Self::Error> {
2941 let data_schema: UncheckedDataSchema<_, _, _> = value.into();
2942 data_schema.try_into()
2943 }
2944}
2945
2946impl<T, DS, AS, OS> From<TupleDataSchemaBuilder<T, DS, AS, OS>> for PartialDataSchema<DS, AS, OS>
2947where
2948 T: Into<PartialDataSchemaBuilder<DS, AS, OS, Extended>>,
2949{
2950 fn from(builder: TupleDataSchemaBuilder<T, DS, AS, OS>) -> Self {
2951 let TupleDataSchemaBuilder {
2952 inner,
2953 items,
2954 other: other_array_schema,
2955 } = builder;
2956 let PartialDataSchemaBuilder {
2957 constant: _,
2958 default,
2959 unit,
2960 one_of: _,
2961 enumeration: _,
2962 read_only,
2963 write_only,
2964 format,
2965 other: other_data_schema,
2966 _marker: _,
2967 } = inner.into();
2968
2969 let items = Some(BoxedElemOrVec::Vec(items));
2970 let subtype = Some(UncheckedDataSchemaSubtype::Array(UncheckedArraySchema {
2971 items,
2972 min_items: None,
2973 max_items: None,
2974 other: other_array_schema,
2975 }));
2976
2977 PartialDataSchema {
2978 constant: None,
2979 default,
2980 unit,
2981 one_of: None,
2982 enumeration: None,
2983 read_only,
2984 write_only,
2985 format,
2986 subtype,
2987 other: other_data_schema,
2988 }
2989 }
2990}
2991
2992impl<T, DS, AS, OS> From<VecDataSchemaBuilder<T, DS, AS, OS>> for PartialDataSchema<DS, AS, OS>
2993where
2994 T: Into<PartialDataSchemaBuilder<DS, AS, OS, Extended>>,
2995{
2996 fn from(builder: VecDataSchemaBuilder<T, DS, AS, OS>) -> Self {
2997 let VecDataSchemaBuilder {
2998 inner,
2999 item,
3000 min_items,
3001 max_items,
3002 other: other_array_schema,
3003 } = builder;
3004 let PartialDataSchemaBuilder {
3005 constant: _,
3006 default,
3007 unit,
3008 one_of: _,
3009 enumeration: _,
3010 read_only,
3011 write_only,
3012 format,
3013 other: other_data_schema,
3014 _marker: _,
3015 } = inner.into();
3016
3017 let items = item.map(|item| BoxedElemOrVec::Elem(Box::new(item)));
3018 let subtype = Some(UncheckedDataSchemaSubtype::Array(UncheckedArraySchema {
3019 items,
3020 min_items,
3021 max_items,
3022 other: other_array_schema,
3023 }));
3024
3025 PartialDataSchema {
3026 constant: None,
3027 default,
3028 unit,
3029 one_of: None,
3030 enumeration: None,
3031 read_only,
3032 write_only,
3033 format,
3034 subtype,
3035 other: other_data_schema,
3036 }
3037 }
3038}
3039
3040impl<T, DS, AS, OS> From<NumberDataSchemaBuilder<T>> for UncheckedDataSchema<DS, AS, OS>
3041where
3042 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3043{
3044 fn from(builder: NumberDataSchemaBuilder<T>) -> Self {
3045 let NumberDataSchemaBuilder {
3046 inner,
3047 maximum,
3048 minimum,
3049 multiple_of,
3050 } = builder;
3051 let DataSchemaBuilder {
3052 partial:
3053 PartialDataSchemaBuilder {
3054 constant: _,
3055 default,
3056 unit,
3057 one_of: _,
3058 enumeration: _,
3059 read_only,
3060 write_only,
3061 format,
3062 other,
3063 _marker: _,
3064 },
3065 info:
3066 HumanReadableInfo {
3067 attype,
3068 title,
3069 titles,
3070 description,
3071 descriptions,
3072 },
3073 } = inner.into();
3074
3075 let subtype = Some(UncheckedDataSchemaSubtype::Number(NumberSchema {
3076 minimum,
3077 maximum,
3078 multiple_of,
3079 }));
3080
3081 UncheckedDataSchema {
3082 attype,
3083 title,
3084 titles,
3085 description,
3086 descriptions,
3087 constant: None,
3088 default,
3089 unit,
3090 one_of: None,
3091 enumeration: None,
3092 read_only,
3093 write_only,
3094 format,
3095 subtype,
3096 other,
3097 }
3098 }
3099}
3100
3101impl<T, DS, AS, OS> TryFrom<NumberDataSchemaBuilder<T>> for DataSchema<DS, AS, OS>
3102where
3103 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3104{
3105 type Error = Error;
3106
3107 fn try_from(value: NumberDataSchemaBuilder<T>) -> Result<Self, Self::Error> {
3108 let data_schema: UncheckedDataSchema<_, _, _> = value.into();
3109 data_schema.try_into()
3110 }
3111}
3112
3113impl<T, DS, AS, OS> From<NumberDataSchemaBuilder<T>> for PartialDataSchema<DS, AS, OS>
3114where
3115 T: Into<PartialDataSchemaBuilder<DS, AS, OS, Extended>>,
3116{
3117 fn from(builder: NumberDataSchemaBuilder<T>) -> Self {
3118 let NumberDataSchemaBuilder {
3119 inner,
3120 maximum,
3121 minimum,
3122 multiple_of,
3123 } = builder;
3124 let PartialDataSchemaBuilder {
3125 constant: _,
3126 default,
3127 unit,
3128 one_of: _,
3129 enumeration: _,
3130 read_only,
3131 write_only,
3132 format,
3133 other,
3134 _marker: _,
3135 } = inner.into();
3136
3137 let subtype = Some(UncheckedDataSchemaSubtype::Number(NumberSchema {
3138 minimum,
3139 maximum,
3140 multiple_of,
3141 }));
3142
3143 PartialDataSchema {
3144 constant: None,
3145 default,
3146 unit,
3147 one_of: None,
3148 enumeration: None,
3149 read_only,
3150 write_only,
3151 format,
3152 subtype,
3153 other,
3154 }
3155 }
3156}
3157
3158impl<T, DS, AS, OS> From<IntegerDataSchemaBuilder<T>> for UncheckedDataSchema<DS, AS, OS>
3159where
3160 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3161{
3162 fn from(builder: IntegerDataSchemaBuilder<T>) -> Self {
3163 let IntegerDataSchemaBuilder {
3164 inner,
3165 maximum,
3166 minimum,
3167 multiple_of,
3168 } = builder;
3169 let DataSchemaBuilder {
3170 partial:
3171 PartialDataSchemaBuilder {
3172 constant: _,
3173 default,
3174 unit,
3175 one_of: _,
3176 enumeration: _,
3177 read_only,
3178 write_only,
3179 format,
3180 other,
3181 _marker: _,
3182 },
3183 info:
3184 HumanReadableInfo {
3185 attype,
3186 title,
3187 titles,
3188 description,
3189 descriptions,
3190 },
3191 } = inner.into();
3192
3193 let subtype = Some(UncheckedDataSchemaSubtype::Integer(IntegerSchema {
3194 minimum,
3195 maximum,
3196 multiple_of,
3197 }));
3198
3199 UncheckedDataSchema {
3200 attype,
3201 title,
3202 titles,
3203 description,
3204 descriptions,
3205 constant: None,
3206 default,
3207 unit,
3208 one_of: None,
3209 enumeration: None,
3210 read_only,
3211 write_only,
3212 format,
3213 subtype,
3214 other,
3215 }
3216 }
3217}
3218
3219impl<T, DS, AS, OS> TryFrom<IntegerDataSchemaBuilder<T>> for DataSchema<DS, AS, OS>
3220where
3221 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3222{
3223 type Error = Error;
3224
3225 fn try_from(value: IntegerDataSchemaBuilder<T>) -> Result<Self, Self::Error> {
3226 let data_schema: UncheckedDataSchema<_, _, _> = value.into();
3227 data_schema.try_into()
3228 }
3229}
3230
3231impl<T, DS, AS, OS> From<IntegerDataSchemaBuilder<T>> for PartialDataSchema<DS, AS, OS>
3232where
3233 T: Into<PartialDataSchemaBuilder<DS, AS, OS, Extended>>,
3234{
3235 fn from(builder: IntegerDataSchemaBuilder<T>) -> Self {
3236 let IntegerDataSchemaBuilder {
3237 inner,
3238 maximum,
3239 minimum,
3240 multiple_of,
3241 } = builder;
3242 let PartialDataSchemaBuilder {
3243 constant: _,
3244 default,
3245 unit,
3246 one_of: _,
3247 enumeration: _,
3248 read_only,
3249 write_only,
3250 format,
3251 other,
3252 _marker: _,
3253 } = inner.into();
3254
3255 let subtype = Some(UncheckedDataSchemaSubtype::Integer(IntegerSchema {
3256 minimum,
3257 maximum,
3258 multiple_of,
3259 }));
3260
3261 PartialDataSchema {
3262 constant: None,
3263 default,
3264 unit,
3265 one_of: None,
3266 enumeration: None,
3267 read_only,
3268 write_only,
3269 format,
3270 subtype,
3271 other,
3272 }
3273 }
3274}
3275
3276impl<T, DS, AS, OS> From<ObjectDataSchemaBuilder<T, DS, AS, OS>> for UncheckedDataSchema<DS, AS, OS>
3277where
3278 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3279{
3280 fn from(builder: ObjectDataSchemaBuilder<T, DS, AS, OS>) -> Self {
3281 let ObjectDataSchemaBuilder {
3282 inner,
3283 properties,
3284 required,
3285 other: other_object_schema,
3286 } = builder;
3287 let DataSchemaBuilder {
3288 partial:
3289 PartialDataSchemaBuilder {
3290 constant: _,
3291 default,
3292 unit,
3293 one_of: _,
3294 enumeration: _,
3295 read_only,
3296 write_only,
3297 format,
3298 other: other_data_schema,
3299 _marker: _,
3300 },
3301 info:
3302 HumanReadableInfo {
3303 attype,
3304 title,
3305 titles,
3306 description,
3307 descriptions,
3308 },
3309 } = inner.into();
3310
3311 let properties = properties
3312 .is_empty()
3313 .not()
3314 .then(|| properties.into_iter().collect());
3315 let required = required.is_empty().not().then_some(required);
3316 let subtype = Some(UncheckedDataSchemaSubtype::Object(UncheckedObjectSchema {
3317 properties,
3318 required,
3319 other: other_object_schema,
3320 }));
3321
3322 UncheckedDataSchema {
3323 attype,
3324 title,
3325 titles,
3326 description,
3327 descriptions,
3328 constant: None,
3329 default,
3330 unit,
3331 one_of: None,
3332 enumeration: None,
3333 read_only,
3334 write_only,
3335 format,
3336 subtype,
3337 other: other_data_schema,
3338 }
3339 }
3340}
3341
3342impl<T, DS, AS, OS> TryFrom<ObjectDataSchemaBuilder<T, DS, AS, OS>> for DataSchema<DS, AS, OS>
3343where
3344 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3345{
3346 type Error = Error;
3347
3348 fn try_from(value: ObjectDataSchemaBuilder<T, DS, AS, OS>) -> Result<Self, Self::Error> {
3349 let data_schema: UncheckedDataSchema<_, _, _> = value.into();
3350 data_schema.try_into()
3351 }
3352}
3353
3354impl<T, DS, AS, OS> From<ObjectDataSchemaBuilder<T, DS, AS, OS>> for PartialDataSchema<DS, AS, OS>
3355where
3356 T: Into<PartialDataSchemaBuilder<DS, AS, OS, Extended>>,
3357{
3358 fn from(builder: ObjectDataSchemaBuilder<T, DS, AS, OS>) -> Self {
3359 let ObjectDataSchemaBuilder {
3360 inner,
3361 properties,
3362 required,
3363 other: other_object_schema,
3364 } = builder;
3365 let PartialDataSchemaBuilder {
3366 constant: _,
3367 default,
3368 unit,
3369 one_of: _,
3370 enumeration: _,
3371 read_only,
3372 write_only,
3373 format,
3374 other: other_data_schema,
3375 _marker: _,
3376 } = inner.into();
3377
3378 let properties = properties
3379 .is_empty()
3380 .not()
3381 .then(|| properties.into_iter().collect());
3382 let required = required.is_empty().not().then_some(required);
3383 let subtype = Some(UncheckedDataSchemaSubtype::Object(UncheckedObjectSchema {
3384 properties,
3385 required,
3386 other: other_object_schema,
3387 }));
3388
3389 PartialDataSchema {
3390 constant: None,
3391 default,
3392 unit,
3393 one_of: None,
3394 enumeration: None,
3395 read_only,
3396 write_only,
3397 format,
3398 subtype,
3399 other: other_data_schema,
3400 }
3401 }
3402}
3403
3404impl<T, DS, AS, OS> From<StringDataSchemaBuilder<T>> for UncheckedDataSchema<DS, AS, OS>
3405where
3406 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3407{
3408 fn from(builder: StringDataSchemaBuilder<T>) -> Self {
3409 let StringDataSchemaBuilder {
3410 inner,
3411 min_length,
3412 max_length,
3413 pattern,
3414 content_encoding,
3415 content_media_type,
3416 } = builder;
3417
3418 let DataSchemaBuilder {
3419 partial:
3420 PartialDataSchemaBuilder {
3421 constant: _,
3422 default,
3423 unit,
3424 one_of: _,
3425 enumeration: _,
3426 read_only,
3427 write_only,
3428 format,
3429 other,
3430 _marker: _,
3431 },
3432 info:
3433 HumanReadableInfo {
3434 attype,
3435 title,
3436 titles,
3437 description,
3438 descriptions,
3439 },
3440 } = inner.into();
3441
3442 let subtype = Some(UncheckedDataSchemaSubtype::String(StringSchema {
3443 min_length,
3444 max_length,
3445 pattern,
3446 content_encoding,
3447 content_media_type,
3448 }));
3449
3450 UncheckedDataSchema {
3451 attype,
3452 title,
3453 titles,
3454 description,
3455 descriptions,
3456 constant: None,
3457 default,
3458 unit,
3459 one_of: None,
3460 enumeration: None,
3461 read_only,
3462 write_only,
3463 format,
3464 subtype,
3465 other,
3466 }
3467 }
3468}
3469
3470impl<T, DS, AS, OS> TryFrom<StringDataSchemaBuilder<T>> for DataSchema<DS, AS, OS>
3471where
3472 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3473{
3474 type Error = Error;
3475
3476 fn try_from(value: StringDataSchemaBuilder<T>) -> Result<Self, Self::Error> {
3477 let data_schema: UncheckedDataSchema<_, _, _> = value.into();
3478 data_schema.try_into()
3479 }
3480}
3481
3482impl<T, DS, AS, OS> From<StringDataSchemaBuilder<T>> for PartialDataSchema<DS, AS, OS>
3483where
3484 T: Into<PartialDataSchemaBuilder<DS, AS, OS, Extended>>,
3485{
3486 fn from(builder: StringDataSchemaBuilder<T>) -> Self {
3487 let StringDataSchemaBuilder {
3488 inner,
3489 min_length,
3490 max_length,
3491 pattern,
3492 content_encoding,
3493 content_media_type,
3494 } = builder;
3495
3496 let PartialDataSchemaBuilder {
3497 constant: _,
3498 default,
3499 unit,
3500 one_of: _,
3501 enumeration: _,
3502 read_only,
3503 write_only,
3504 format,
3505 other,
3506 _marker: _,
3507 } = inner.into();
3508
3509 let subtype = Some(UncheckedDataSchemaSubtype::String(StringSchema {
3510 min_length,
3511 max_length,
3512 pattern,
3513 content_encoding,
3514 content_media_type,
3515 }));
3516
3517 PartialDataSchema {
3518 constant: None,
3519 default,
3520 unit,
3521 one_of: None,
3522 enumeration: None,
3523 read_only,
3524 write_only,
3525 format,
3526 subtype,
3527 other,
3528 }
3529 }
3530}
3531
3532impl<T, DS, AS, OS> From<ReadOnly<T>> for UncheckedDataSchema<DS, AS, OS>
3533where
3534 T: Into<UncheckedDataSchema<DS, AS, OS>>,
3535{
3536 fn from(builder: ReadOnly<T>) -> Self {
3537 let data_schema = builder.inner.into();
3538 Self {
3539 read_only: true,
3540 ..data_schema
3541 }
3542 }
3543}
3544
3545impl<T, DS, AS, OS> TryFrom<ReadOnly<T>> for DataSchema<DS, AS, OS>
3546where
3547 T: Into<UncheckedDataSchema<DS, AS, OS>>,
3548{
3549 type Error = Error;
3550
3551 fn try_from(value: ReadOnly<T>) -> Result<Self, Self::Error> {
3552 let data_schema: UncheckedDataSchema<_, _, _> = value.into();
3553 data_schema.try_into()
3554 }
3555}
3556
3557impl<T, DS, AS, OS> From<WriteOnly<T>> for UncheckedDataSchema<DS, AS, OS>
3558where
3559 T: Into<UncheckedDataSchema<DS, AS, OS>>,
3560{
3561 fn from(builder: WriteOnly<T>) -> Self {
3562 let data_schema = builder.inner.into();
3563 Self {
3564 read_only: false,
3565 ..data_schema
3566 }
3567 }
3568}
3569
3570impl<T, DS, AS, OS> TryFrom<WriteOnly<T>> for DataSchema<DS, AS, OS>
3571where
3572 T: Into<UncheckedDataSchema<DS, AS, OS>>,
3573{
3574 type Error = Error;
3575
3576 fn try_from(value: WriteOnly<T>) -> Result<Self, Self::Error> {
3577 let data_schema: UncheckedDataSchema<_, _, _> = value.into();
3578 data_schema.try_into()
3579 }
3580}
3581
3582impl<T, DS, AS, OS> From<ReadOnly<T>> for PartialDataSchema<DS, AS, OS>
3583where
3584 T: Into<PartialDataSchema<DS, AS, OS>>,
3585{
3586 fn from(builder: ReadOnly<T>) -> Self {
3587 let data_schema = builder.inner.into();
3588 Self {
3589 read_only: true,
3590 ..data_schema
3591 }
3592 }
3593}
3594
3595impl<T, DS, AS, OS> From<WriteOnly<T>> for PartialDataSchema<DS, AS, OS>
3596where
3597 T: Into<PartialDataSchema<DS, AS, OS>>,
3598{
3599 fn from(builder: WriteOnly<T>) -> Self {
3600 let data_schema = builder.inner.into();
3601 Self {
3602 read_only: false,
3603 ..data_schema
3604 }
3605 }
3606}
3607
3608impl<T, DS, AS, OS> From<EnumDataSchemaBuilder<T>> for UncheckedDataSchema<DS, AS, OS>
3609where
3610 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3611{
3612 fn from(builder: EnumDataSchemaBuilder<T>) -> Self {
3613 let DataSchemaBuilder {
3614 partial:
3615 PartialDataSchemaBuilder {
3616 constant: _,
3617 default,
3618 unit,
3619 one_of: _,
3620 enumeration,
3621 read_only,
3622 write_only,
3623 format,
3624 other,
3625 _marker: _,
3626 },
3627 info:
3628 HumanReadableInfo {
3629 attype,
3630 title,
3631 titles,
3632 description,
3633 descriptions,
3634 },
3635 } = builder.inner.into();
3636
3637 let enumeration = Some(enumeration);
3638 Self {
3639 attype,
3640 title,
3641 titles,
3642 description,
3643 descriptions,
3644 constant: None,
3645 default,
3646 unit,
3647 one_of: None,
3648 enumeration,
3649 read_only,
3650 write_only,
3651 format,
3652 subtype: None,
3653 other,
3654 }
3655 }
3656}
3657
3658impl<T, DS, AS, OS> TryFrom<EnumDataSchemaBuilder<T>> for DataSchema<DS, AS, OS>
3659where
3660 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3661{
3662 type Error = Error;
3663
3664 fn try_from(value: EnumDataSchemaBuilder<T>) -> Result<Self, Self::Error> {
3665 let data_schema: UncheckedDataSchema<_, _, _> = value.into();
3666 data_schema.try_into()
3667 }
3668}
3669
3670impl<T, DS, AS, OS> From<EnumDataSchemaBuilder<T>> for PartialDataSchema<DS, AS, OS>
3671where
3672 T: Into<PartialDataSchemaBuilder<DS, AS, OS, Extended>>,
3673{
3674 fn from(builder: EnumDataSchemaBuilder<T>) -> Self {
3675 let PartialDataSchemaBuilder {
3676 constant: _,
3677 default,
3678 unit,
3679 one_of: _,
3680 enumeration,
3681 read_only,
3682 write_only,
3683 format,
3684 other,
3685 _marker: _,
3686 } = builder.inner.into();
3687
3688 let enumeration = Some(enumeration);
3689 Self {
3690 constant: None,
3691 default,
3692 unit,
3693 one_of: None,
3694 enumeration,
3695 read_only,
3696 write_only,
3697 format,
3698 subtype: None,
3699 other,
3700 }
3701 }
3702}
3703
3704impl<T, DS, AS, OS> From<OneOfDataSchemaBuilder<T>> for UncheckedDataSchema<DS, AS, OS>
3705where
3706 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3707{
3708 fn from(builder: OneOfDataSchemaBuilder<T>) -> Self {
3709 let DataSchemaBuilder {
3710 partial:
3711 PartialDataSchemaBuilder {
3712 constant: _,
3713 default,
3714 unit,
3715 one_of,
3716 enumeration: _,
3717 read_only,
3718 write_only,
3719 format,
3720 other,
3721 _marker: _,
3722 },
3723 info:
3724 HumanReadableInfo {
3725 attype,
3726 title,
3727 titles,
3728 description,
3729 descriptions,
3730 },
3731 } = builder.inner.into();
3732
3733 let one_of = Some(one_of);
3734 Self {
3735 attype,
3736 title,
3737 titles,
3738 description,
3739 descriptions,
3740 constant: None,
3741 default,
3742 unit,
3743 one_of,
3744 enumeration: None,
3745 read_only,
3746 write_only,
3747 format,
3748 subtype: None,
3749 other,
3750 }
3751 }
3752}
3753
3754impl<T, DS, AS, OS> TryFrom<OneOfDataSchemaBuilder<T>> for DataSchema<DS, AS, OS>
3755where
3756 T: Into<DataSchemaBuilder<DS, AS, OS, Extended>>,
3757{
3758 type Error = Error;
3759
3760 fn try_from(value: OneOfDataSchemaBuilder<T>) -> Result<Self, Self::Error> {
3761 let data_schema: UncheckedDataSchema<_, _, _> = value.into();
3762 data_schema.try_into()
3763 }
3764}
3765
3766impl<T, DS, AS, OS> From<OneOfDataSchemaBuilder<T>> for PartialDataSchema<DS, AS, OS>
3767where
3768 T: Into<PartialDataSchemaBuilder<DS, AS, OS, Extended>>,
3769{
3770 fn from(builder: OneOfDataSchemaBuilder<T>) -> Self {
3771 let PartialDataSchemaBuilder {
3772 constant: _,
3773 default,
3774 unit,
3775 one_of,
3776 enumeration: _,
3777 read_only,
3778 write_only,
3779 format,
3780 other,
3781 _marker: _,
3782 } = builder.inner.into();
3783
3784 let one_of = Some(one_of);
3785 Self {
3786 constant: None,
3787 default,
3788 unit,
3789 one_of,
3790 enumeration: None,
3791 read_only,
3792 write_only,
3793 format,
3794 subtype: None,
3795 other,
3796 }
3797 }
3798}
3799
3800pub(super) trait CheckableDataSchema {
3801 fn check(&self) -> Result<(), Error>;
3802}
3803
3804impl<DS, AS, OS> CheckableDataSchema for UncheckedDataSchema<DS, AS, OS> {
3805 fn check(&self) -> Result<(), Error> {
3806 check_data_schema_subtype(&self.subtype)?;
3807 check_one_of_schema(self.one_of.as_deref())?;
3808 Ok(())
3809 }
3810}
3811
3812impl<DS, AS, OS> CheckableDataSchema for PartialDataSchema<DS, AS, OS> {
3813 fn check(&self) -> Result<(), Error> {
3814 check_data_schema_subtype(&self.subtype)?;
3815 check_one_of_schema(self.one_of.as_deref())?;
3816 Ok(())
3817 }
3818}
3819
3820pub(super) fn check_data_schema_subtype<DS, AS, OS>(
3821 mut subtype: &Option<UncheckedDataSchemaSubtype<DS, AS, OS>>,
3822) -> Result<(), Error> {
3823 use UncheckedDataSchemaSubtype::*;
3824
3825 let mut stack = Vec::new();
3826
3827 loop {
3828 if let Some(subtype) = subtype.as_ref() {
3829 match subtype {
3830 Array(array) => {
3831 match (array.min_items, array.max_items) {
3832 (Some(min), Some(max))
3833 if matches!(min.partial_cmp(&max), None | Some(Ordering::Greater)) =>
3834 {
3835 return Err(Error::InvalidMinMax)
3836 }
3837 _ => {}
3838 };
3839
3840 if let Some(items) = &array.items {
3841 match items {
3842 BoxedElemOrVec::Elem(item) => stack.push(item.as_ref()),
3843 BoxedElemOrVec::Vec(items) => stack.extend(items.iter()),
3844 }
3845 }
3846 }
3847 Number(number) => {
3848 match (number.minimum, number.maximum) {
3849 (Some(x), _) if x.is_nan() => return Err(Error::NanMinMax),
3850 (_, Some(x)) if x.is_nan() => return Err(Error::NanMinMax),
3851 (Some(min), Some(max))
3852 if matches!(min.partial_cmp(&max), None | Some(Ordering::Greater)) =>
3853 {
3854 return Err(Error::InvalidMinMax)
3855 }
3856 _ => {}
3857 }
3858
3859 match number.multiple_of {
3860 Some(multiple_of) if multiple_of <= 0. => {
3861 return Err(Error::InvalidMultipleOf)
3862 }
3863 _ => {}
3864 }
3865 }
3866 Integer(integer) => match (integer.minimum, integer.maximum) {
3867 (Some(min), Some(max))
3868 if matches!(min.partial_cmp(&max), None | Some(Ordering::Greater)) =>
3869 {
3870 return Err(Error::InvalidMinMax)
3871 }
3872 _ => {}
3873 },
3874 Object(UncheckedObjectSchema {
3875 properties: Some(properties),
3876 ..
3877 }) => stack.extend(properties.values()),
3878 Object(_) | String(_) | Boolean | Null => {}
3879 }
3880 }
3881
3882 match stack.pop() {
3883 Some(new_data_schema) => {
3884 if let Some(children) = new_data_schema.one_of.as_deref() {
3885 stack.extend(children.iter());
3886 }
3887
3888 subtype = &new_data_schema.subtype
3889 }
3890 None => break Ok(()),
3891 }
3892 }
3893}
3894
3895fn check_one_of_schema<T>(one_of: Option<&[T]>) -> Result<(), Error>
3896where
3897 T: CheckableDataSchema,
3898{
3899 one_of
3900 .map(|one_of| one_of.iter().try_for_each(|schema| schema.check()))
3901 .unwrap_or(Ok(()))
3902}
3903
3904impl<DS, AS, OS> TryFrom<UncheckedDataSchema<DS, AS, OS>> for DataSchema<DS, AS, OS> {
3905 type Error = Error;
3906
3907 fn try_from(data_schema: UncheckedDataSchema<DS, AS, OS>) -> Result<Self, Self::Error> {
3908 let UncheckedDataSchema {
3909 attype,
3910 title,
3911 titles,
3912 description,
3913 descriptions,
3914 constant,
3915 default,
3916 unit,
3917 one_of,
3918 enumeration,
3919 read_only,
3920 write_only,
3921 format,
3922 subtype,
3923 other,
3924 } = data_schema;
3925
3926 let titles = titles.map(|titles| titles.build()).transpose()?;
3927 let descriptions = descriptions
3928 .map(|descriptions| descriptions.build())
3929 .transpose()?;
3930 let one_of = one_of
3931 .map(|one_of| {
3932 one_of
3933 .into_iter()
3934 .map(|data_schema| data_schema.try_into())
3935 .collect()
3936 })
3937 .transpose()?;
3938 let subtype = subtype.map(|subtype| subtype.try_into()).transpose()?;
3939
3940 Ok(Self {
3941 attype,
3942 title,
3943 titles,
3944 description,
3945 descriptions,
3946 constant,
3947 default,
3948 unit,
3949 one_of,
3950 enumeration,
3951 read_only,
3952 write_only,
3953 format,
3954 subtype,
3955 other,
3956 })
3957 }
3958}
3959
3960pub(crate) fn uri_variables_contains_arrays_objects<Other>(
3961 uri_variables: &UncheckedDataSchemaMap<Other>,
3962) -> bool
3963where
3964 Other: ExtendableThing,
3965{
3966 uri_variables.values().any(|schema| {
3967 matches!(
3968 &schema.subtype,
3969 Some(UncheckedDataSchemaSubtype::Object(_) | UncheckedDataSchemaSubtype::Array(_))
3970 )
3971 })
3972}
3973
3974impl<DS, AS, OS> TryFrom<UncheckedDataSchemaSubtype<DS, AS, OS>> for DataSchemaSubtype<DS, AS, OS> {
3975 type Error = Error;
3976
3977 fn try_from(value: UncheckedDataSchemaSubtype<DS, AS, OS>) -> Result<Self, Self::Error> {
3978 use UncheckedDataSchemaSubtype::*;
3979
3980 let out = match value {
3981 Array(array) => DataSchemaSubtype::Array(array.try_into()?),
3982 Boolean => DataSchemaSubtype::Boolean,
3983 Number(number) => DataSchemaSubtype::Number(number),
3984 Integer(integer) => DataSchemaSubtype::Integer(integer),
3985 Object(object) => DataSchemaSubtype::Object(object.try_into()?),
3986 String(string) => DataSchemaSubtype::String(string),
3987 Null => DataSchemaSubtype::Null,
3988 };
3989
3990 Ok(out)
3991 }
3992}
3993
3994impl<DS, AS, OS> TryFrom<UncheckedArraySchema<DS, AS, OS>> for ArraySchema<DS, AS, OS> {
3995 type Error = Error;
3996
3997 fn try_from(value: UncheckedArraySchema<DS, AS, OS>) -> Result<Self, Self::Error> {
3998 let UncheckedArraySchema {
3999 items,
4000 min_items,
4001 max_items,
4002 other,
4003 } = value;
4004 let items = items
4005 .map(|items| match items {
4006 BoxedElemOrVec::Elem(item) => (*item)
4007 .try_into()
4008 .map(|item| BoxedElemOrVec::Elem(Box::new(item))),
4009 BoxedElemOrVec::Vec(items) => items
4010 .into_iter()
4011 .map(TryInto::try_into)
4012 .collect::<Result<_, _>>()
4013 .map(BoxedElemOrVec::Vec),
4014 })
4015 .transpose()?;
4016
4017 Ok(Self {
4018 items,
4019 min_items,
4020 max_items,
4021 other,
4022 })
4023 }
4024}
4025
4026impl<DS, AS, OS> TryFrom<UncheckedObjectSchema<DS, AS, OS>> for ObjectSchema<DS, AS, OS> {
4027 type Error = Error;
4028
4029 fn try_from(value: UncheckedObjectSchema<DS, AS, OS>) -> Result<Self, Self::Error> {
4030 let UncheckedObjectSchema {
4031 properties,
4032 required,
4033 other,
4034 } = value;
4035 let properties = properties
4036 .map(|properties| {
4037 properties
4038 .into_iter()
4039 .map(|(k, v)| v.try_into().map(|v| (k, v)))
4040 .collect()
4041 })
4042 .transpose()?;
4043
4044 Ok(Self {
4045 properties,
4046 required,
4047 other,
4048 })
4049 }
4050}
4051
4052#[cfg(test)]
4053mod tests {
4054 use alloc::{boxed::Box, string::*, vec};
4055 use serde::{Deserialize, Serialize};
4056 use serde_json::json;
4057
4058 use crate::{
4059 extend::ExtendableThing,
4060 hlist::{Cons, Nil},
4061 thing::{ArraySchema, BoxedElemOrVec, DataSchemaFromOther, ObjectSchema},
4062 };
4063
4064 use super::*;
4065
4066 #[test]
4067 fn null_simple() {
4068 let data_schema: DataSchemaFromOther<Nil> =
4069 DataSchemaBuilder::default().null().try_into().unwrap();
4070 assert_eq!(
4071 data_schema,
4072 DataSchema {
4073 attype: None,
4074 title: None,
4075 titles: None,
4076 description: None,
4077 descriptions: None,
4078 constant: None,
4079 default: None,
4080 unit: None,
4081 one_of: None,
4082 enumeration: None,
4083 read_only: false,
4084 write_only: false,
4085 format: None,
4086 subtype: Some(DataSchemaSubtype::Null),
4087 other: Nil,
4088 }
4089 );
4090 }
4091
4092 #[test]
4093 fn null_partial() {
4094 let data_schema: PartialDataSchema<Nil, Nil, Nil> =
4095 PartialDataSchemaBuilder::default().null().into();
4096 assert_eq!(
4097 data_schema,
4098 PartialDataSchema {
4099 constant: None,
4100 default: None,
4101 unit: None,
4102 one_of: None,
4103 enumeration: None,
4104 read_only: false,
4105 write_only: false,
4106 format: None,
4107 subtype: Some(UncheckedDataSchemaSubtype::Null),
4108 other: Nil,
4109 }
4110 );
4111 }
4112
4113 #[test]
4114 fn boolean_simple() {
4115 let data_schema: DataSchemaFromOther<Nil> =
4116 DataSchemaBuilder::default().bool().try_into().unwrap();
4117 assert_eq!(
4118 data_schema,
4119 DataSchema {
4120 attype: None,
4121 title: None,
4122 titles: None,
4123 description: None,
4124 descriptions: None,
4125 constant: None,
4126 default: None,
4127 unit: None,
4128 one_of: None,
4129 enumeration: None,
4130 read_only: false,
4131 write_only: false,
4132 format: None,
4133 subtype: Some(DataSchemaSubtype::Boolean),
4134 other: Nil,
4135 }
4136 );
4137 }
4138
4139 #[test]
4140 fn boolean_partial() {
4141 let data_schema: PartialDataSchema<Nil, Nil, Nil> =
4142 PartialDataSchemaBuilder::default().bool().into();
4143 assert_eq!(
4144 data_schema,
4145 PartialDataSchema {
4146 constant: None,
4147 default: None,
4148 unit: None,
4149 one_of: None,
4150 enumeration: None,
4151 read_only: false,
4152 write_only: false,
4153 format: None,
4154 subtype: Some(UncheckedDataSchemaSubtype::Boolean),
4155 other: Nil,
4156 }
4157 );
4158 }
4159
4160 #[test]
4161 fn string_simple() {
4162 let data_schema: DataSchemaFromOther<Nil> =
4163 DataSchemaBuilder::default().string().try_into().unwrap();
4164 assert_eq!(
4165 data_schema,
4166 DataSchema {
4167 attype: None,
4168 title: None,
4169 titles: None,
4170 description: None,
4171 descriptions: None,
4172 constant: None,
4173 default: None,
4174 unit: None,
4175 one_of: None,
4176 enumeration: None,
4177 read_only: false,
4178 write_only: false,
4179 format: None,
4180 subtype: Some(DataSchemaSubtype::String(StringSchema {
4181 max_length: None,
4182 min_length: None,
4183 pattern: None,
4184 content_encoding: None,
4185 content_media_type: None,
4186 })),
4187 other: Nil,
4188 }
4189 );
4190 }
4191
4192 #[test]
4193 fn string_partial() {
4194 let data_schema: PartialDataSchema<Nil, Nil, Nil> =
4195 PartialDataSchemaBuilder::default().string().into();
4196 assert_eq!(
4197 data_schema,
4198 PartialDataSchema {
4199 constant: None,
4200 default: None,
4201 unit: None,
4202 one_of: None,
4203 enumeration: None,
4204 read_only: false,
4205 write_only: false,
4206 format: None,
4207 subtype: Some(UncheckedDataSchemaSubtype::String(StringSchema {
4208 min_length: None,
4209 max_length: None,
4210 pattern: None,
4211 content_encoding: None,
4212 content_media_type: None,
4213 })),
4214 other: Nil,
4215 }
4216 );
4217 }
4218
4219 #[test]
4220 fn empty_simple_vec() {
4221 let data_schema: DataSchemaFromOther<Nil> =
4222 DataSchemaBuilder::default().vec().try_into().unwrap();
4223 assert_eq!(
4224 data_schema,
4225 DataSchema {
4226 attype: None,
4227 title: None,
4228 titles: None,
4229 description: None,
4230 descriptions: None,
4231 constant: None,
4232 default: None,
4233 unit: None,
4234 one_of: None,
4235 enumeration: None,
4236 read_only: false,
4237 write_only: false,
4238 format: None,
4239 subtype: Some(DataSchemaSubtype::Array(ArraySchema {
4240 items: None,
4241 min_items: None,
4242 max_items: None,
4243 other: Nil,
4244 })),
4245 other: Nil,
4246 }
4247 );
4248 }
4249
4250 #[test]
4251 fn empty_partial_vec() {
4252 let data_schema: PartialDataSchema<Nil, Nil, Nil> =
4253 PartialDataSchemaBuilder::default().vec().into();
4254 assert_eq!(
4255 data_schema,
4256 PartialDataSchema {
4257 constant: None,
4258 default: None,
4259 unit: None,
4260 one_of: None,
4261 enumeration: None,
4262 read_only: false,
4263 write_only: false,
4264 format: None,
4265 subtype: Some(UncheckedDataSchemaSubtype::Array(UncheckedArraySchema {
4266 items: None,
4267 min_items: None,
4268 max_items: None,
4269 other: Nil,
4270 })),
4271 other: Nil,
4272 }
4273 );
4274 }
4275
4276 #[test]
4277 fn empty_simple_tuple() {
4278 let data_schema: DataSchemaFromOther<Nil> =
4279 DataSchemaBuilder::default().tuple().try_into().unwrap();
4280 assert_eq!(
4281 data_schema,
4282 DataSchema {
4283 attype: None,
4284 title: None,
4285 titles: None,
4286 description: None,
4287 descriptions: None,
4288 constant: None,
4289 default: None,
4290 unit: None,
4291 one_of: None,
4292 enumeration: None,
4293 read_only: false,
4294 write_only: false,
4295 format: None,
4296 subtype: Some(DataSchemaSubtype::Array(ArraySchema {
4297 items: Some(BoxedElemOrVec::Vec(vec![])),
4298 min_items: None,
4299 max_items: None,
4300 other: Nil,
4301 })),
4302 other: Nil,
4303 }
4304 );
4305 }
4306
4307 #[test]
4308 fn empty_partial_tuple() {
4309 let data_schema: PartialDataSchema<Nil, Nil, Nil> =
4310 PartialDataSchemaBuilder::default().tuple().into();
4311 assert_eq!(
4312 data_schema,
4313 PartialDataSchema {
4314 constant: None,
4315 default: None,
4316 unit: None,
4317 one_of: None,
4318 enumeration: None,
4319 read_only: false,
4320 write_only: false,
4321 format: None,
4322 subtype: Some(UncheckedDataSchemaSubtype::Array(UncheckedArraySchema {
4323 items: Some(BoxedElemOrVec::Vec(vec![])),
4324 min_items: None,
4325 max_items: None,
4326 other: Nil,
4327 })),
4328 other: Nil,
4329 }
4330 );
4331 }
4332
4333 #[test]
4334 fn number_simple() {
4335 let data_schema: DataSchemaFromOther<Nil> =
4336 DataSchemaBuilder::default().number().try_into().unwrap();
4337 assert_eq!(
4338 data_schema,
4339 DataSchema {
4340 attype: None,
4341 title: None,
4342 titles: None,
4343 description: None,
4344 descriptions: None,
4345 constant: None,
4346 default: None,
4347 unit: None,
4348 one_of: None,
4349 enumeration: None,
4350 read_only: false,
4351 write_only: false,
4352 format: None,
4353 subtype: Some(DataSchemaSubtype::Number(NumberSchema {
4354 maximum: None,
4355 minimum: None,
4356 multiple_of: None,
4357 })),
4358 other: Nil,
4359 }
4360 );
4361 }
4362 #[test]
4363 fn number_partial() {
4364 let data_schema: PartialDataSchema<Nil, Nil, Nil> =
4365 PartialDataSchemaBuilder::default().number().into();
4366 assert_eq!(
4367 data_schema,
4368 PartialDataSchema {
4369 constant: None,
4370 default: None,
4371 unit: None,
4372 one_of: None,
4373 enumeration: None,
4374 read_only: false,
4375 write_only: false,
4376 format: None,
4377 subtype: Some(UncheckedDataSchemaSubtype::Number(NumberSchema {
4378 maximum: None,
4379 minimum: None,
4380 multiple_of: None,
4381 })),
4382 other: Nil,
4383 }
4384 );
4385 }
4386
4387 #[test]
4388 fn integer_simple() {
4389 let data_schema: DataSchemaFromOther<Nil> =
4390 DataSchemaBuilder::default().integer().try_into().unwrap();
4391 assert_eq!(
4392 data_schema,
4393 DataSchema {
4394 attype: None,
4395 title: None,
4396 titles: None,
4397 description: None,
4398 descriptions: None,
4399 constant: None,
4400 default: None,
4401 unit: None,
4402 one_of: None,
4403 enumeration: None,
4404 read_only: false,
4405 write_only: false,
4406 format: None,
4407 subtype: Some(DataSchemaSubtype::Integer(IntegerSchema {
4408 maximum: None,
4409 minimum: None,
4410 multiple_of: None,
4411 })),
4412 other: Nil,
4413 }
4414 );
4415 }
4416
4417 #[test]
4418 fn partial_simple() {
4419 let data_schema: PartialDataSchema<Nil, Nil, Nil> =
4420 PartialDataSchemaBuilder::default().integer().into();
4421 assert_eq!(
4422 data_schema,
4423 PartialDataSchema {
4424 constant: None,
4425 default: None,
4426 unit: None,
4427 one_of: None,
4428 enumeration: None,
4429 read_only: false,
4430 write_only: false,
4431 format: None,
4432 subtype: Some(UncheckedDataSchemaSubtype::Integer(IntegerSchema {
4433 maximum: None,
4434 minimum: None,
4435 multiple_of: None,
4436 })),
4437 other: Nil,
4438 }
4439 );
4440 }
4441
4442 #[test]
4443 fn empty_simple_object() {
4444 let data_schema: DataSchemaFromOther<Nil> =
4445 DataSchemaBuilder::default().object().try_into().unwrap();
4446 assert_eq!(
4447 data_schema,
4448 DataSchema {
4449 attype: None,
4450 title: None,
4451 titles: None,
4452 description: None,
4453 descriptions: None,
4454 constant: None,
4455 default: None,
4456 unit: None,
4457 one_of: None,
4458 enumeration: None,
4459 read_only: false,
4460 write_only: false,
4461 format: None,
4462 subtype: Some(DataSchemaSubtype::Object(ObjectSchema {
4463 properties: None,
4464 required: None,
4465 other: Nil,
4466 })),
4467 other: Nil,
4468 }
4469 );
4470 }
4471
4472 #[test]
4473 fn empty_partial_object() {
4474 let data_schema: PartialDataSchema<Nil, Nil, Nil> =
4475 PartialDataSchemaBuilder::default().object().into();
4476 assert_eq!(
4477 data_schema,
4478 PartialDataSchema {
4479 constant: None,
4480 default: None,
4481 unit: None,
4482 one_of: None,
4483 enumeration: None,
4484 read_only: false,
4485 write_only: false,
4486 format: None,
4487 subtype: Some(UncheckedDataSchemaSubtype::Object(UncheckedObjectSchema {
4488 properties: None,
4489 required: None,
4490 other: Nil,
4491 })),
4492 other: Nil,
4493 }
4494 );
4495 }
4496
4497 #[test]
4498 fn constant_simple() {
4499 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
4500 .constant(json!({ "hello": 42 }))
4501 .try_into()
4502 .unwrap();
4503 assert_eq!(
4504 data_schema,
4505 DataSchema {
4506 attype: None,
4507 title: None,
4508 titles: None,
4509 description: None,
4510 descriptions: None,
4511 constant: Some(json!({
4512 "hello": 42,
4513 })),
4514 default: None,
4515 unit: None,
4516 one_of: None,
4517 enumeration: None,
4518 read_only: true,
4519 write_only: false,
4520 format: None,
4521 subtype: None,
4522 other: Nil,
4523 }
4524 );
4525 }
4526
4527 #[test]
4528 fn constant_partial() {
4529 let data_schema: PartialDataSchema<Nil, Nil, Nil> = PartialDataSchemaBuilder::default()
4530 .constant(json!({ "hello": 42 }))
4531 .into();
4532 assert_eq!(
4533 data_schema,
4534 PartialDataSchema {
4535 constant: Some(json!({
4536 "hello": 42,
4537 })),
4538 default: None,
4539 unit: None,
4540 one_of: None,
4541 enumeration: None,
4542 read_only: true,
4543 write_only: false,
4544 format: None,
4545 subtype: None,
4546 other: Nil,
4547 }
4548 );
4549 }
4550
4551 #[test]
4552 fn enum_simple() {
4553 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
4554 .enumeration("hello")
4555 .enumeration("world")
4556 .enumeration(42)
4557 .try_into()
4558 .unwrap();
4559 assert_eq!(
4560 data_schema,
4561 DataSchema {
4562 attype: None,
4563 title: None,
4564 titles: None,
4565 description: None,
4566 descriptions: None,
4567 constant: None,
4568 default: None,
4569 unit: None,
4570 one_of: None,
4571 enumeration: Some(vec!["hello".into(), "world".into(), 42.into()]),
4572 read_only: false,
4573 write_only: false,
4574 format: None,
4575 subtype: None,
4576 other: Nil,
4577 }
4578 );
4579 }
4580
4581 #[test]
4582 fn enum_partial() {
4583 let data_schema: PartialDataSchema<Nil, Nil, Nil> = PartialDataSchemaBuilder::default()
4584 .enumeration("hello")
4585 .enumeration("world")
4586 .enumeration(42)
4587 .into();
4588 assert_eq!(
4589 data_schema,
4590 PartialDataSchema {
4591 constant: None,
4592 default: None,
4593 unit: None,
4594 one_of: None,
4595 enumeration: Some(vec!["hello".into(), "world".into(), 42.into()]),
4596 read_only: false,
4597 write_only: false,
4598 format: None,
4599 subtype: None,
4600 other: Nil,
4601 }
4602 );
4603 }
4604
4605 #[test]
4606 fn read_only_simple() {
4607 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
4608 .bool()
4609 .read_only()
4610 .try_into()
4611 .unwrap();
4612 assert_eq!(
4613 data_schema,
4614 DataSchema {
4615 attype: None,
4616 title: None,
4617 titles: None,
4618 description: None,
4619 descriptions: None,
4620 constant: None,
4621 default: None,
4622 unit: None,
4623 one_of: None,
4624 enumeration: None,
4625 read_only: true,
4626 write_only: false,
4627 format: None,
4628 subtype: Some(DataSchemaSubtype::Boolean),
4629 other: Nil,
4630 }
4631 );
4632 }
4633
4634 #[test]
4635 fn read_only_partial() {
4636 let data_schema: PartialDataSchema<Nil, Nil, Nil> = PartialDataSchemaBuilder::default()
4637 .bool()
4638 .read_only()
4639 .into();
4640 assert_eq!(
4641 data_schema,
4642 PartialDataSchema {
4643 constant: None,
4644 default: None,
4645 unit: None,
4646 one_of: None,
4647 enumeration: None,
4648 read_only: true,
4649 write_only: false,
4650 format: None,
4651 subtype: Some(UncheckedDataSchemaSubtype::Boolean),
4652 other: Nil,
4653 }
4654 );
4655 }
4656
4657 #[test]
4658 fn read_only_to_builder() {
4659 let data_schema_builder: DataSchemaBuilder<Nil, Nil, Nil, Extended> = ReadOnly {
4660 inner: DataSchemaBuilder::default(),
4661 }
4662 .into();
4663 assert_eq!(
4664 data_schema_builder,
4665 DataSchemaBuilder {
4666 partial: PartialDataSchemaBuilder {
4667 constant: None,
4668 default: None,
4669 unit: None,
4670 one_of: vec![],
4671 enumeration: vec![],
4672 read_only: true,
4673 write_only: false,
4674 format: None,
4675 other: Nil,
4676 _marker: PhantomData,
4677 },
4678 info: Default::default(),
4679 }
4680 );
4681 }
4682
4683 #[test]
4684 fn read_only_to_partial_builder() {
4685 let data_schema_builder: PartialDataSchemaBuilder<Nil, Nil, Nil, Extended> = ReadOnly {
4686 inner: PartialDataSchemaBuilder::default(),
4687 }
4688 .into();
4689 assert_eq!(
4690 data_schema_builder,
4691 PartialDataSchemaBuilder {
4692 constant: None,
4693 default: None,
4694 unit: None,
4695 one_of: vec![],
4696 enumeration: vec![],
4697 read_only: true,
4698 write_only: false,
4699 format: None,
4700 other: Nil,
4701 _marker: PhantomData,
4702 },
4703 );
4704 }
4705
4706 #[test]
4707 fn write_only_simple() {
4708 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
4709 .bool()
4710 .write_only()
4711 .try_into()
4712 .unwrap();
4713 assert_eq!(
4714 data_schema,
4715 DataSchema {
4716 attype: None,
4717 title: None,
4718 titles: None,
4719 description: None,
4720 descriptions: None,
4721 constant: None,
4722 default: None,
4723 unit: None,
4724 one_of: None,
4725 enumeration: None,
4726 read_only: false,
4727 write_only: true,
4728 format: None,
4729 subtype: Some(DataSchemaSubtype::Boolean),
4730 other: Nil,
4731 }
4732 );
4733 }
4734
4735 #[test]
4736 fn write_only_partial() {
4737 let data_schema: PartialDataSchema<Nil, Nil, Nil> = PartialDataSchemaBuilder::default()
4738 .bool()
4739 .write_only()
4740 .into();
4741 assert_eq!(
4742 data_schema,
4743 PartialDataSchema {
4744 constant: None,
4745 default: None,
4746 unit: None,
4747 one_of: None,
4748 enumeration: None,
4749 read_only: false,
4750 write_only: true,
4751 format: None,
4752 subtype: Some(UncheckedDataSchemaSubtype::Boolean),
4753 other: Nil,
4754 }
4755 );
4756 }
4757
4758 #[test]
4759 fn write_only_to_builder() {
4760 let data_schema_builder: DataSchemaBuilder<Nil, Nil, Nil, Extended> = WriteOnly {
4761 inner: DataSchemaBuilder::default(),
4762 }
4763 .into();
4764 assert_eq!(
4765 data_schema_builder,
4766 DataSchemaBuilder {
4767 partial: PartialDataSchemaBuilder {
4768 constant: None,
4769 default: None,
4770 unit: None,
4771 one_of: vec![],
4772 enumeration: vec![],
4773 read_only: false,
4774 write_only: true,
4775 format: None,
4776 other: Nil,
4777 _marker: PhantomData,
4778 },
4779 info: Default::default(),
4780 }
4781 );
4782 }
4783
4784 #[test]
4785 fn write_only_to_partial_builder() {
4786 let data_schema_builder: PartialDataSchemaBuilder<Nil, Nil, Nil, Extended> = WriteOnly {
4787 inner: PartialDataSchemaBuilder::default(),
4788 }
4789 .into();
4790 assert_eq!(
4791 data_schema_builder,
4792 PartialDataSchemaBuilder {
4793 constant: None,
4794 default: None,
4795 unit: None,
4796 one_of: vec![],
4797 enumeration: vec![],
4798 read_only: false,
4799 write_only: true,
4800 format: None,
4801 other: Nil,
4802 _marker: PhantomData,
4803 },
4804 );
4805 }
4806
4807 #[test]
4808 fn null_full() {
4809 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
4810 .null()
4811 .attype("attype1")
4812 .attype("attype2")
4813 .title("title")
4814 .titles(|b| b.add("en", "title_en").add("it", "title_it"))
4815 .description("description")
4816 .descriptions(|b| b.add("en", "description_en").add("it", "description_it"))
4817 .default_value(["hello", "world"].as_slice())
4818 .unit("cm")
4819 .format("format")
4820 .try_into()
4821 .unwrap();
4822 assert_eq!(
4823 data_schema,
4824 DataSchema {
4825 attype: Some(vec!["attype1".to_string(), "attype2".to_string()]),
4826 title: Some("title".to_string()),
4827 titles: Some(
4828 [("en", "title_en"), ("it", "title_it")]
4829 .into_iter()
4830 .map(|(a, b)| (a.parse().unwrap(), b.to_string()))
4831 .collect()
4832 ),
4833 description: Some("description".to_string()),
4834 descriptions: Some(
4835 [("en", "description_en"), ("it", "description_it")]
4836 .into_iter()
4837 .map(|(a, b)| (a.parse().unwrap(), b.to_string()))
4838 .collect()
4839 ),
4840 constant: None,
4841 default: Some(json! { ["hello", "world"]}),
4842 unit: Some("cm".to_string()),
4843 one_of: None,
4844 enumeration: None,
4845 read_only: false,
4846 write_only: false,
4847 format: Some("format".to_string()),
4848 subtype: Some(DataSchemaSubtype::Null),
4849 other: Nil,
4850 }
4851 );
4852 }
4853
4854 #[test]
4855 fn enum_full() {
4856 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
4857 .enumeration("variant1")
4858 .enumeration("variant2")
4859 .enumeration(3u32)
4860 .attype("attype")
4861 .title("title")
4862 .titles(|b| b.add("en", "title_en").add("it", "title_it"))
4863 .description("description")
4864 .descriptions(|b| b.add("en", "description_en").add("it", "description_it"))
4865 .default_value(["hello", "world"].as_slice())
4866 .unit("cm")
4867 .format("format")
4868 .try_into()
4869 .unwrap();
4870 assert_eq!(
4871 data_schema,
4872 DataSchema {
4873 attype: Some(vec!["attype".to_string()]),
4874 title: Some("title".to_string()),
4875 titles: Some(
4876 [("en", "title_en"), ("it", "title_it")]
4877 .into_iter()
4878 .map(|(a, b)| (a.parse().unwrap(), b.to_string()))
4879 .collect()
4880 ),
4881 description: Some("description".to_string()),
4882 descriptions: Some(
4883 [("en", "description_en"), ("it", "description_it")]
4884 .into_iter()
4885 .map(|(a, b)| (a.parse().unwrap(), b.to_string()))
4886 .collect()
4887 ),
4888 constant: None,
4889 default: Some(json! { ["hello", "world"]}),
4890 unit: Some("cm".to_string()),
4891 one_of: None,
4892 enumeration: Some(vec!["variant1".into(), "variant2".into(), 3.into()]),
4893 read_only: false,
4894 write_only: false,
4895 format: Some("format".to_string()),
4896 subtype: None,
4897 other: Nil,
4898 }
4899 );
4900 }
4901
4902 #[test]
4903 fn read_only_enum() {
4904 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
4905 .enumeration("hello")
4906 .enumeration("world")
4907 .title("title")
4908 .default_value(["hello", "world"].as_slice())
4909 .read_only()
4910 .enumeration(42)
4911 .description("description")
4912 .try_into()
4913 .unwrap();
4914 assert_eq!(
4915 data_schema,
4916 DataSchema {
4917 attype: None,
4918 title: Some("title".to_string()),
4919 titles: None,
4920 description: Some("description".to_string()),
4921 descriptions: None,
4922 constant: None,
4923 default: Some(json! { ["hello", "world"]}),
4924 unit: None,
4925 one_of: None,
4926 enumeration: Some(vec!["hello".into(), "world".into(), 42.into()]),
4927 read_only: true,
4928 write_only: false,
4929 format: None,
4930 subtype: None,
4931 other: Nil,
4932 }
4933 );
4934 }
4935
4936 #[test]
4937 fn tuple_with_content() {
4938 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
4939 .tuple()
4940 .append(|b| b.finish_extend().constant("hello"))
4941 .append(|b| b.finish_extend().bool())
4942 .try_into()
4943 .unwrap();
4944 assert_eq!(
4945 data_schema,
4946 DataSchema {
4947 attype: None,
4948 title: None,
4949 titles: None,
4950 description: None,
4951 descriptions: None,
4952 constant: None,
4953 default: None,
4954 unit: None,
4955 one_of: None,
4956 enumeration: None,
4957 read_only: false,
4958 write_only: false,
4959 format: None,
4960 subtype: Some(DataSchemaSubtype::Array(ArraySchema {
4961 items: Some(BoxedElemOrVec::Vec(vec![
4962 DataSchema {
4963 attype: None,
4964 title: None,
4965 titles: None,
4966 description: None,
4967 descriptions: None,
4968 constant: Some("hello".into()),
4969 default: None,
4970 unit: None,
4971 one_of: None,
4972 enumeration: None,
4973 read_only: true,
4974 write_only: false,
4975 format: None,
4976 subtype: None,
4977 other: Nil,
4978 },
4979 DataSchema {
4980 attype: None,
4981 title: None,
4982 titles: None,
4983 description: None,
4984 descriptions: None,
4985 constant: None,
4986 default: None,
4987 unit: None,
4988 one_of: None,
4989 enumeration: None,
4990 read_only: false,
4991 write_only: false,
4992 format: None,
4993 subtype: Some(DataSchemaSubtype::Boolean),
4994 other: Nil,
4995 },
4996 ])),
4997 min_items: None,
4998 max_items: None,
4999 other: Nil,
5000 })),
5001 other: Nil,
5002 }
5003 );
5004 }
5005
5006 #[test]
5007 fn vec_with_content() {
5008 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5009 .vec()
5010 .min_items(0)
5011 .max_items(5)
5012 .set_item(|b| b.finish_extend().constant("hello"))
5013 .try_into()
5014 .unwrap();
5015 assert_eq!(
5016 data_schema,
5017 DataSchema {
5018 attype: None,
5019 title: None,
5020 titles: None,
5021 description: None,
5022 descriptions: None,
5023 constant: None,
5024 default: None,
5025 unit: None,
5026 one_of: None,
5027 enumeration: None,
5028 read_only: false,
5029 write_only: false,
5030 format: None,
5031 subtype: Some(DataSchemaSubtype::Array(ArraySchema {
5032 items: Some(BoxedElemOrVec::Elem(Box::new(DataSchema {
5033 attype: None,
5034 title: None,
5035 titles: None,
5036 description: None,
5037 descriptions: None,
5038 constant: Some("hello".into()),
5039 default: None,
5040 unit: None,
5041 one_of: None,
5042 enumeration: None,
5043 read_only: true,
5044 write_only: false,
5045 format: None,
5046 subtype: None,
5047 other: Nil,
5048 },))),
5049 min_items: Some(0),
5050 max_items: Some(5),
5051 other: Nil,
5052 })),
5053 other: Nil,
5054 }
5055 );
5056 }
5057
5058 #[test]
5059 fn tuple_partial_with_content() {
5060 let data_schema: PartialDataSchema<Nil, Nil, Nil> = PartialDataSchemaBuilder::default()
5061 .tuple()
5062 .append(|b| b.finish_extend().constant("hello"))
5063 .append(|b| b.finish_extend().bool())
5064 .try_into()
5065 .unwrap();
5066 assert_eq!(
5067 data_schema,
5068 PartialDataSchema {
5069 constant: None,
5070 default: None,
5071 unit: None,
5072 one_of: None,
5073 enumeration: None,
5074 read_only: false,
5075 write_only: false,
5076 format: None,
5077 subtype: Some(UncheckedDataSchemaSubtype::Array(UncheckedArraySchema {
5078 items: Some(BoxedElemOrVec::Vec(vec![
5079 UncheckedDataSchema {
5080 attype: None,
5081 title: None,
5082 titles: None,
5083 description: None,
5084 descriptions: None,
5085 constant: Some("hello".into()),
5086 default: None,
5087 unit: None,
5088 one_of: None,
5089 enumeration: None,
5090 read_only: true,
5091 write_only: false,
5092 format: None,
5093 subtype: None,
5094 other: Nil,
5095 },
5096 UncheckedDataSchema {
5097 attype: None,
5098 title: None,
5099 titles: None,
5100 description: None,
5101 descriptions: None,
5102 constant: None,
5103 default: None,
5104 unit: None,
5105 one_of: None,
5106 enumeration: None,
5107 read_only: false,
5108 write_only: false,
5109 format: None,
5110 subtype: Some(UncheckedDataSchemaSubtype::Boolean),
5111 other: Nil,
5112 },
5113 ])),
5114 min_items: None,
5115 max_items: None,
5116 other: Nil,
5117 })),
5118 other: Nil,
5119 }
5120 );
5121 }
5122
5123 #[test]
5124 fn vec_partial_with_content() {
5125 let data_schema: PartialDataSchema<Nil, Nil, Nil> = PartialDataSchemaBuilder::default()
5126 .vec()
5127 .min_items(0)
5128 .max_items(5)
5129 .set_item(|b| b.finish_extend().constant("hello"))
5130 .try_into()
5131 .unwrap();
5132 assert_eq!(
5133 data_schema,
5134 PartialDataSchema {
5135 constant: None,
5136 default: None,
5137 unit: None,
5138 one_of: None,
5139 enumeration: None,
5140 read_only: false,
5141 write_only: false,
5142 format: None,
5143 subtype: Some(UncheckedDataSchemaSubtype::Array(UncheckedArraySchema {
5144 items: Some(BoxedElemOrVec::Elem(Box::new(UncheckedDataSchema {
5145 attype: None,
5146 title: None,
5147 titles: None,
5148 description: None,
5149 descriptions: None,
5150 constant: Some("hello".into()),
5151 default: None,
5152 unit: None,
5153 one_of: None,
5154 enumeration: None,
5155 read_only: true,
5156 write_only: false,
5157 format: None,
5158 subtype: None,
5159 other: Nil,
5160 },))),
5161 min_items: Some(0),
5162 max_items: Some(5),
5163 other: Nil,
5164 })),
5165 other: Nil,
5166 }
5167 );
5168 }
5169
5170 #[test]
5171 fn object_with_content() {
5172 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5173 .object()
5174 .property("hello", false, |b| b.finish_extend().bool())
5175 .property("world", true, |b| b.title("title").finish_extend().number())
5176 .try_into()
5177 .unwrap();
5178 assert_eq!(
5179 data_schema,
5180 DataSchema {
5181 attype: None,
5182 title: None,
5183 titles: None,
5184 description: None,
5185 descriptions: None,
5186 constant: None,
5187 default: None,
5188 unit: None,
5189 one_of: None,
5190 enumeration: None,
5191 read_only: false,
5192 write_only: false,
5193 format: None,
5194 subtype: Some(DataSchemaSubtype::Object(ObjectSchema {
5195 properties: Some(
5196 [
5197 (
5198 "hello".to_string(),
5199 DataSchema {
5200 attype: None,
5201 title: None,
5202 titles: None,
5203 description: None,
5204 descriptions: None,
5205 constant: None,
5206 default: None,
5207 unit: None,
5208 one_of: None,
5209 enumeration: None,
5210 read_only: false,
5211 write_only: false,
5212 format: None,
5213 subtype: Some(DataSchemaSubtype::Boolean),
5214 other: Nil,
5215 }
5216 ),
5217 (
5218 "world".to_string(),
5219 DataSchema {
5220 attype: None,
5221 title: Some("title".to_string()),
5222 titles: None,
5223 description: None,
5224 descriptions: None,
5225 constant: None,
5226 default: None,
5227 unit: None,
5228 one_of: None,
5229 enumeration: None,
5230 read_only: false,
5231 write_only: false,
5232 format: None,
5233 subtype: Some(DataSchemaSubtype::Number(NumberSchema {
5234 maximum: None,
5235 minimum: None,
5236 multiple_of: None,
5237 })),
5238 other: Nil,
5239 }
5240 )
5241 ]
5242 .into_iter()
5243 .collect()
5244 ),
5245 required: Some(vec!["world".to_string()]),
5246 other: Nil,
5247 })),
5248 other: Nil,
5249 }
5250 );
5251 }
5252
5253 #[test]
5254 fn object_partial_with_content() {
5255 let data_schema: PartialDataSchema<Nil, Nil, Nil> = PartialDataSchemaBuilder::default()
5256 .object()
5257 .property("hello", false, |b| b.finish_extend().bool())
5258 .property("world", true, |b| b.finish_extend().title("title").number())
5259 .try_into()
5260 .unwrap();
5261 assert_eq!(
5262 data_schema,
5263 PartialDataSchema {
5264 constant: None,
5265 default: None,
5266 unit: None,
5267 one_of: None,
5268 enumeration: None,
5269 read_only: false,
5270 write_only: false,
5271 format: None,
5272 subtype: Some(UncheckedDataSchemaSubtype::Object(UncheckedObjectSchema {
5273 properties: Some(
5274 [
5275 (
5276 "hello".to_string(),
5277 UncheckedDataSchema {
5278 attype: None,
5279 title: None,
5280 titles: None,
5281 description: None,
5282 descriptions: None,
5283 constant: None,
5284 default: None,
5285 unit: None,
5286 one_of: None,
5287 enumeration: None,
5288 read_only: false,
5289 write_only: false,
5290 format: None,
5291 subtype: Some(UncheckedDataSchemaSubtype::Boolean),
5292 other: Nil,
5293 }
5294 ),
5295 (
5296 "world".to_string(),
5297 UncheckedDataSchema {
5298 attype: None,
5299 title: Some("title".to_string()),
5300 titles: None,
5301 description: None,
5302 descriptions: None,
5303 constant: None,
5304 default: None,
5305 unit: None,
5306 one_of: None,
5307 enumeration: None,
5308 read_only: false,
5309 write_only: false,
5310 format: None,
5311 subtype: Some(UncheckedDataSchemaSubtype::Number(
5312 NumberSchema {
5313 maximum: None,
5314 minimum: None,
5315 multiple_of: None,
5316 }
5317 )),
5318 other: Nil,
5319 }
5320 )
5321 ]
5322 .into_iter()
5323 .collect()
5324 ),
5325 required: Some(vec!["world".to_string()]),
5326 other: Nil,
5327 })),
5328 other: Nil,
5329 }
5330 );
5331 }
5332
5333 #[test]
5334 fn integer_with_data() {
5335 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5336 .integer()
5337 .exclusive_minimum(10)
5338 .maximum(5)
5339 .multiple_of(NonZeroU64::new(2).unwrap())
5340 .try_into()
5341 .unwrap();
5342 assert_eq!(
5343 data_schema,
5344 DataSchema {
5345 attype: None,
5346 title: None,
5347 titles: None,
5348 description: None,
5349 descriptions: None,
5350 constant: None,
5351 default: None,
5352 unit: None,
5353 one_of: None,
5354 enumeration: None,
5355 read_only: false,
5356 write_only: false,
5357 format: None,
5358 subtype: Some(DataSchemaSubtype::Integer(IntegerSchema {
5359 maximum: Some(Maximum::Inclusive(5)),
5360 minimum: Some(Minimum::Exclusive(10)),
5361 multiple_of: Some(NonZeroU64::new(2).unwrap()),
5362 })),
5363 other: Nil,
5364 },
5365 );
5366
5367 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5368 .integer()
5369 .minimum(10)
5370 .exclusive_maximum(5)
5371 .try_into()
5372 .unwrap();
5373 assert_eq!(
5374 data_schema,
5375 DataSchema {
5376 attype: None,
5377 title: None,
5378 titles: None,
5379 description: None,
5380 descriptions: None,
5381 constant: None,
5382 default: None,
5383 unit: None,
5384 one_of: None,
5385 enumeration: None,
5386 read_only: false,
5387 write_only: false,
5388 format: None,
5389 subtype: Some(DataSchemaSubtype::Integer(IntegerSchema {
5390 maximum: Some(Maximum::Exclusive(5)),
5391 minimum: Some(Minimum::Inclusive(10)),
5392 multiple_of: None,
5393 })),
5394 other: Nil,
5395 },
5396 );
5397 }
5398
5399 #[test]
5400 fn number_with_data() {
5401 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5402 .number()
5403 .exclusive_minimum(10.)
5404 .maximum(5.)
5405 .multiple_of(2.)
5406 .try_into()
5407 .unwrap();
5408 assert_eq!(
5409 data_schema,
5410 DataSchema {
5411 attype: None,
5412 title: None,
5413 titles: None,
5414 description: None,
5415 descriptions: None,
5416 constant: None,
5417 default: None,
5418 unit: None,
5419 one_of: None,
5420 enumeration: None,
5421 read_only: false,
5422 write_only: false,
5423 format: None,
5424 subtype: Some(DataSchemaSubtype::Number(NumberSchema {
5425 maximum: Some(Maximum::Inclusive(5.)),
5426 minimum: Some(Minimum::Exclusive(10.)),
5427 multiple_of: Some(2.),
5428 })),
5429 other: Nil,
5430 },
5431 );
5432
5433 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5434 .number()
5435 .minimum(10.)
5436 .exclusive_maximum(5.)
5437 .multiple_of(2.)
5438 .try_into()
5439 .unwrap();
5440 assert_eq!(
5441 data_schema,
5442 DataSchema {
5443 attype: None,
5444 title: None,
5445 titles: None,
5446 description: None,
5447 descriptions: None,
5448 constant: None,
5449 default: None,
5450 unit: None,
5451 one_of: None,
5452 enumeration: None,
5453 read_only: false,
5454 write_only: false,
5455 format: None,
5456 subtype: Some(DataSchemaSubtype::Number(NumberSchema {
5457 maximum: Some(Maximum::Exclusive(5.)),
5458 minimum: Some(Minimum::Inclusive(10.)),
5459 multiple_of: Some(2.),
5460 })),
5461 other: Nil,
5462 },
5463 );
5464 }
5465
5466 #[test]
5467 fn string_with_data() {
5468 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5469 .string()
5470 .min_length(5)
5471 .max_length(32)
5472 .pattern("pattern")
5473 .content_encoding("content encoding")
5474 .content_media_type("content media type")
5475 .try_into()
5476 .unwrap();
5477 assert_eq!(
5478 data_schema,
5479 DataSchema {
5480 attype: None,
5481 title: None,
5482 titles: None,
5483 description: None,
5484 descriptions: None,
5485 constant: None,
5486 default: None,
5487 unit: None,
5488 one_of: None,
5489 enumeration: None,
5490 read_only: false,
5491 write_only: false,
5492 format: None,
5493 subtype: Some(DataSchemaSubtype::String(StringSchema {
5494 min_length: Some(5),
5495 max_length: Some(32),
5496 pattern: Some("pattern".to_string()),
5497 content_encoding: Some("content encoding".to_string()),
5498 content_media_type: Some("content media type".to_string()),
5499 })),
5500 other: Nil,
5501 },
5502 );
5503 }
5504
5505 #[test]
5506 fn one_of_simple() {
5507 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5508 .one_of(|b| b.finish_extend().number())
5509 .one_of(|b| b.finish_extend().integer())
5510 .one_of(|b| b.finish_extend().string())
5511 .try_into()
5512 .unwrap();
5513 assert_eq!(
5514 data_schema,
5515 DataSchema {
5516 attype: None,
5517 title: None,
5518 titles: None,
5519 description: None,
5520 descriptions: None,
5521 constant: None,
5522 default: None,
5523 unit: None,
5524 one_of: Some(vec![
5525 DataSchema {
5526 attype: None,
5527 title: None,
5528 titles: None,
5529 description: None,
5530 descriptions: None,
5531 constant: None,
5532 default: None,
5533 unit: None,
5534 one_of: None,
5535 enumeration: None,
5536 read_only: false,
5537 write_only: false,
5538 format: None,
5539 subtype: Some(DataSchemaSubtype::Number(NumberSchema {
5540 maximum: None,
5541 minimum: None,
5542 multiple_of: None,
5543 })),
5544 other: Nil,
5545 },
5546 DataSchema {
5547 attype: None,
5548 title: None,
5549 titles: None,
5550 description: None,
5551 descriptions: None,
5552 constant: None,
5553 default: None,
5554 unit: None,
5555 one_of: None,
5556 enumeration: None,
5557 read_only: false,
5558 write_only: false,
5559 format: None,
5560 subtype: Some(DataSchemaSubtype::Integer(IntegerSchema {
5561 maximum: None,
5562 minimum: None,
5563 multiple_of: None,
5564 })),
5565 other: Nil,
5566 },
5567 DataSchema {
5568 attype: None,
5569 title: None,
5570 titles: None,
5571 description: None,
5572 descriptions: None,
5573 constant: None,
5574 default: None,
5575 unit: None,
5576 one_of: None,
5577 enumeration: None,
5578 read_only: false,
5579 write_only: false,
5580 format: None,
5581 subtype: Some(DataSchemaSubtype::String(StringSchema {
5582 min_length: None,
5583 max_length: None,
5584 pattern: None,
5585 content_encoding: None,
5586 content_media_type: None,
5587 })),
5588 other: Nil,
5589 },
5590 ]),
5591 enumeration: None,
5592 read_only: false,
5593 write_only: false,
5594 format: None,
5595 subtype: None,
5596 other: Nil,
5597 },
5598 );
5599 }
5600
5601 #[test]
5602 fn one_of_nested() {
5603 let data_schema: DataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5604 .object()
5605 .property("hello", true, |b| {
5606 b.finish_extend()
5607 .one_of(|b| b.finish_extend().string())
5608 .one_of(|b| b.finish_extend().integer())
5609 })
5610 .try_into()
5611 .unwrap();
5612 assert_eq!(
5613 data_schema,
5614 DataSchema {
5615 attype: None,
5616 title: None,
5617 titles: None,
5618 description: None,
5619 descriptions: None,
5620 constant: None,
5621 default: None,
5622 unit: None,
5623 one_of: None,
5624 enumeration: None,
5625 read_only: false,
5626 write_only: false,
5627 format: None,
5628 subtype: Some(DataSchemaSubtype::Object(ObjectSchema {
5629 properties: Some(
5630 [(
5631 "hello".to_string(),
5632 DataSchema {
5633 attype: None,
5634 title: None,
5635 titles: None,
5636 description: None,
5637 descriptions: None,
5638 constant: None,
5639 default: None,
5640 unit: None,
5641 one_of: Some(vec![
5642 DataSchema {
5643 attype: None,
5644 title: None,
5645 titles: None,
5646 description: None,
5647 descriptions: None,
5648 constant: None,
5649 default: None,
5650 unit: None,
5651 one_of: None,
5652 enumeration: None,
5653 read_only: false,
5654 write_only: false,
5655 format: None,
5656 subtype: Some(DataSchemaSubtype::String(StringSchema {
5657 min_length: None,
5658 max_length: None,
5659 pattern: None,
5660 content_encoding: None,
5661 content_media_type: None,
5662 })),
5663 other: Nil,
5664 },
5665 DataSchema {
5666 attype: None,
5667 title: None,
5668 titles: None,
5669 description: None,
5670 descriptions: None,
5671 constant: None,
5672 default: None,
5673 unit: None,
5674 one_of: None,
5675 enumeration: None,
5676 read_only: false,
5677 write_only: false,
5678 format: None,
5679 subtype: Some(DataSchemaSubtype::Integer(IntegerSchema {
5680 maximum: None,
5681 minimum: None,
5682 multiple_of: None,
5683 })),
5684 other: Nil,
5685 },
5686 ]),
5687 enumeration: None,
5688 read_only: false,
5689 write_only: false,
5690 format: None,
5691 subtype: None,
5692 other: Nil,
5693 }
5694 ),]
5695 .into_iter()
5696 .collect()
5697 ),
5698 required: Some(vec!["hello".to_string()]),
5699 other: Nil,
5700 })),
5701 other: Nil,
5702 },
5703 );
5704 }
5705
5706 #[test]
5707 fn check_valid_data_schema() {
5708 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5709 .one_of(|b| {
5710 b.finish_extend()
5711 .vec()
5712 .min_items(2)
5713 .max_items(5)
5714 .set_item(|b| {
5715 b.finish_extend()
5716 .one_of(|b| {
5717 b.finish_extend()
5718 .number()
5719 .minimum(0.)
5720 .maximum(5.)
5721 .multiple_of(2.)
5722 })
5723 .one_of(|b| b.finish_extend().integer().minimum(5).maximum(10))
5724 })
5725 })
5726 .one_of(|b| {
5727 b.finish_extend()
5728 .number()
5729 .minimum(20.)
5730 .maximum(42.)
5731 .multiple_of(7.)
5732 })
5733 .one_of(|b| {
5734 b.finish_extend().object().property("a", false, |b| {
5735 b.finish_extend().integer().minimum(10).maximum(20)
5736 })
5737 })
5738 .into();
5739
5740 assert!(data_schema.check().is_ok());
5741 }
5742
5743 #[test]
5744 fn check_invalid_data_schema() {
5745 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5746 .one_of(|b| {
5747 b.finish_extend()
5748 .vec()
5749 .min_items(5)
5750 .max_items(2)
5751 .set_item(|b| {
5752 b.finish_extend()
5753 .one_of(|b| b.finish_extend().number().minimum(0.).maximum(5.))
5754 .one_of(|b| b.finish_extend().integer().minimum(5).maximum(10))
5755 })
5756 })
5757 .one_of(|b| b.finish_extend().number().minimum(20.).maximum(42.))
5758 .one_of(|b| {
5759 b.finish_extend().object().property("a", false, |b| {
5760 b.finish_extend().integer().minimum(10).maximum(20)
5761 })
5762 })
5763 .into();
5764
5765 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
5766
5767 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5768 .one_of(|b| {
5769 b.finish_extend()
5770 .vec()
5771 .min_items(2)
5772 .max_items(5)
5773 .set_item(|b| {
5774 b.finish_extend()
5775 .one_of(|b| b.finish_extend().number().minimum(5.).maximum(0.))
5776 .one_of(|b| b.finish_extend().integer().minimum(5).maximum(10))
5777 })
5778 })
5779 .one_of(|b| b.finish_extend().number().minimum(20.).maximum(42.))
5780 .one_of(|b| {
5781 b.finish_extend().object().property("a", false, |b| {
5782 b.finish_extend().integer().minimum(10).maximum(20)
5783 })
5784 })
5785 .into();
5786
5787 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
5788
5789 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5790 .one_of(|b| {
5791 b.finish_extend()
5792 .vec()
5793 .min_items(2)
5794 .max_items(5)
5795 .set_item(|b| {
5796 b.finish_extend()
5797 .one_of(|b| b.finish_extend().number().minimum(0.).maximum(5.))
5798 .one_of(|b| b.finish_extend().integer().minimum(10).maximum(5))
5799 })
5800 })
5801 .one_of(|b| b.finish_extend().number().minimum(20.).maximum(42.))
5802 .one_of(|b| {
5803 b.finish_extend().object().property("a", false, |b| {
5804 b.finish_extend().integer().minimum(10).maximum(20)
5805 })
5806 })
5807 .into();
5808
5809 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
5810
5811 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5812 .one_of(|b| {
5813 b.finish_extend()
5814 .vec()
5815 .min_items(2)
5816 .max_items(5)
5817 .set_item(|b| {
5818 b.finish_extend()
5819 .one_of(|b| b.finish_extend().number().minimum(0.).maximum(5.))
5820 .one_of(|b| b.finish_extend().integer().minimum(5).maximum(10))
5821 })
5822 })
5823 .one_of(|b| b.finish_extend().number().minimum(42.).maximum(20.))
5824 .one_of(|b| {
5825 b.finish_extend().object().property("a", false, |b| {
5826 b.finish_extend().integer().minimum(10).maximum(20)
5827 })
5828 })
5829 .into();
5830
5831 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
5832
5833 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5834 .one_of(|b| {
5835 b.finish_extend()
5836 .vec()
5837 .min_items(2)
5838 .max_items(5)
5839 .set_item(|b| {
5840 b.finish_extend()
5841 .one_of(|b| b.finish_extend().number().minimum(0.).maximum(5.))
5842 .one_of(|b| b.finish_extend().integer().minimum(5).maximum(10))
5843 })
5844 })
5845 .one_of(|b| b.finish_extend().number().minimum(20.).maximum(f64::NAN))
5846 .one_of(|b| {
5847 b.finish_extend().object().property("a", false, |b| {
5848 b.finish_extend().integer().minimum(10).maximum(20)
5849 })
5850 })
5851 .into();
5852
5853 assert_eq!(data_schema.check().unwrap_err(), Error::NanMinMax);
5854
5855 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5856 .one_of(|b| {
5857 b.finish_extend()
5858 .vec()
5859 .min_items(2)
5860 .max_items(5)
5861 .set_item(|b| {
5862 b.finish_extend()
5863 .one_of(|b| b.finish_extend().number().minimum(0.).maximum(5.))
5864 .one_of(|b| b.finish_extend().integer().minimum(5).maximum(10))
5865 })
5866 })
5867 .one_of(|b| b.finish_extend().number().minimum(f64::NAN).maximum(42.))
5868 .one_of(|b| {
5869 b.finish_extend().object().property("a", false, |b| {
5870 b.finish_extend().integer().minimum(10).maximum(20)
5871 })
5872 })
5873 .into();
5874
5875 assert_eq!(data_schema.check().unwrap_err(), Error::NanMinMax);
5876
5877 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5878 .one_of(|b| {
5879 b.finish_extend()
5880 .vec()
5881 .min_items(2)
5882 .max_items(5)
5883 .set_item(|b| {
5884 b.finish_extend()
5885 .one_of(|b| b.finish_extend().number().minimum(0.).maximum(5.))
5886 .one_of(|b| b.finish_extend().integer().minimum(5).maximum(10))
5887 })
5888 })
5889 .one_of(|b| b.finish_extend().number().minimum(20.).maximum(42.))
5890 .one_of(|b| {
5891 b.finish_extend().object().property("a", false, |b| {
5892 b.finish_extend().integer().minimum(20).maximum(10)
5893 })
5894 })
5895 .into();
5896
5897 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
5898
5899 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5900 .one_of(|b| {
5901 b.finish_extend()
5902 .vec()
5903 .min_items(2)
5904 .max_items(5)
5905 .set_item(|b| {
5906 b.finish_extend()
5907 .one_of(|b| b.finish_extend().number().minimum(0.).maximum(5.))
5908 .one_of(|b| b.finish_extend().integer().minimum(5).maximum(10))
5909 })
5910 })
5911 .one_of(|b| b.finish_extend().number().minimum(20.).maximum(42.))
5912 .one_of(|b| {
5913 b.finish_extend()
5914 .object()
5915 .property("a", false, |b| {
5916 b.finish_extend().integer().minimum(10).maximum(20)
5917 })
5918 .property("b", false, |b| {
5919 b.finish_extend().integer().minimum(20).maximum(10)
5920 })
5921 })
5922 .into();
5923
5924 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
5925
5926 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5927 .one_of(|b| {
5928 b.finish_extend()
5929 .vec()
5930 .min_items(2)
5931 .max_items(5)
5932 .set_item(|b| {
5933 b.finish_extend()
5934 .one_of(|b| b.finish_extend().number().minimum(0.).maximum(5.))
5935 .one_of(|b| b.finish_extend().integer().minimum(5).maximum(10))
5936 })
5937 })
5938 .one_of(|b| b.finish_extend().number().minimum(20.).maximum(42.))
5939 .one_of(|b| {
5940 b.finish_extend().object().property("a", false, |b| {
5941 b.finish_extend().integer().minimum(10).maximum(20)
5942 })
5943 })
5944 .one_of(|b| {
5945 b.finish_extend()
5946 .one_of(|b| b.finish_extend().number().minimum(20.).maximum(10.))
5947 })
5948 .into();
5949
5950 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
5951
5952 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5953 .one_of(|b| {
5954 b.finish_extend()
5955 .vec()
5956 .min_items(2)
5957 .max_items(5)
5958 .set_item(|b| {
5959 b.finish_extend()
5960 .one_of(|b| {
5961 b.finish_extend()
5962 .one_of(|b| b.finish_extend().number().minimum(5.).maximum(0.))
5963 })
5964 .one_of(|b| b.finish_extend().integer().minimum(5).maximum(10))
5965 })
5966 })
5967 .one_of(|b| b.finish_extend().number().minimum(20.).maximum(42.))
5968 .one_of(|b| {
5969 b.finish_extend().object().property("a", false, |b| {
5970 b.finish_extend().integer().minimum(10).maximum(20)
5971 })
5972 })
5973 .into();
5974
5975 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
5976 }
5977
5978 #[test]
5979 fn check_invalid_data_schema_with_complex_minmax() {
5980 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5981 .integer()
5982 .exclusive_minimum(2)
5983 .maximum(2)
5984 .into();
5985
5986 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
5987
5988 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5989 .integer()
5990 .minimum(2)
5991 .exclusive_maximum(2)
5992 .into();
5993
5994 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
5995
5996 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
5997 .number()
5998 .exclusive_minimum(2.)
5999 .maximum(2.)
6000 .into();
6001
6002 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
6003
6004 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
6005 .number()
6006 .minimum(2.)
6007 .exclusive_maximum(2.)
6008 .into();
6009
6010 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMinMax);
6011 }
6012
6013 #[test]
6014 fn check_invalid_data_schema_multiple_of() {
6015 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
6016 .vec()
6017 .set_item(|b| b.finish_extend().number().multiple_of(0.))
6018 .into();
6019
6020 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMultipleOf);
6021
6022 let data_schema: UncheckedDataSchemaFromOther<Nil> = DataSchemaBuilder::default()
6023 .vec()
6024 .set_item(|b| b.finish_extend().number().multiple_of(-2.))
6025 .into();
6026
6027 assert_eq!(data_schema.check().unwrap_err(), Error::InvalidMultipleOf);
6028 }
6029
6030 #[test]
6031 fn check_valid_partial_data_schema() {
6032 let data_schema: PartialDataSchema<Nil, Nil, Nil> = PartialDataSchemaBuilder::default()
6033 .one_of(|b| {
6034 b.finish_extend()
6035 .vec()
6036 .min_items(2)
6037 .max_items(5)
6038 .set_item(|b| {
6039 b.finish_extend()
6040 .one_of(|b| {
6041 b.finish_extend()
6042 .number()
6043 .minimum(0.)
6044 .maximum(5.)
6045 .multiple_of(2.)
6046 })
6047 .one_of(|b| b.finish_extend().integer().minimum(5).maximum(10))
6048 })
6049 })
6050 .one_of(|b| {
6051 b.finish_extend()
6052 .number()
6053 .minimum(20.)
6054 .maximum(42.)
6055 .multiple_of(3.)
6056 })
6057 .one_of(|b| {
6058 b.finish_extend().object().property("a", false, |b| {
6059 b.finish_extend().integer().minimum(10).maximum(20)
6060 })
6061 })
6062 .into();
6063
6064 assert!(data_schema.check().is_ok());
6065 }
6066
6067 #[derive(Debug, PartialEq, Serialize, Deserialize)]
6068 struct A(i32);
6069 #[derive(Debug, PartialEq, Serialize, Deserialize)]
6070 struct B(String);
6071
6072 #[derive(Debug, PartialEq, Serialize, Deserialize)]
6073 struct ThingExtA {}
6074
6075 #[derive(Debug, PartialEq, Serialize, Deserialize)]
6076 struct DataSchemaExtA {
6077 a: A,
6078 }
6079
6080 #[derive(Debug, PartialEq, Serialize, Deserialize)]
6081 struct ArraySchemaExtA {
6082 b: A,
6083 }
6084
6085 #[derive(Debug, PartialEq, Serialize, Deserialize)]
6086 struct ObjectSchemaExtA {
6087 c: A,
6088 }
6089
6090 #[derive(Debug, PartialEq, Serialize, Deserialize)]
6091 struct ThingExtB {}
6092
6093 #[derive(Debug, PartialEq, Serialize, Deserialize)]
6094 struct DataSchemaExtB {
6095 d: B,
6096 }
6097
6098 #[derive(Debug, PartialEq, Serialize, Deserialize)]
6099 struct ArraySchemaExtB {
6100 e: B,
6101 }
6102
6103 #[derive(Debug, PartialEq, Serialize, Deserialize)]
6104 struct ObjectSchemaExtB {
6105 f: B,
6106 }
6107
6108 impl ExtendableThing for ThingExtA {
6109 type InteractionAffordance = ();
6110 type PropertyAffordance = ();
6111 type ActionAffordance = ();
6112 type EventAffordance = ();
6113 type Form = ();
6114 type ExpectedResponse = ();
6115 type DataSchema = DataSchemaExtA;
6116 type ObjectSchema = ObjectSchemaExtA;
6117 type ArraySchema = ArraySchemaExtA;
6118 }
6119
6120 impl ExtendableThing for ThingExtB {
6121 type InteractionAffordance = ();
6122 type PropertyAffordance = ();
6123 type ActionAffordance = ();
6124 type EventAffordance = ();
6125 type Form = ();
6126 type ExpectedResponse = ();
6127 type DataSchema = DataSchemaExtB;
6128 type ObjectSchema = ObjectSchemaExtB;
6129 type ArraySchema = ArraySchemaExtB;
6130 }
6131
6132 #[test]
6133 fn extend_data_schema() {
6134 let data_schema: DataSchemaFromOther<Cons<ThingExtB, Cons<ThingExtA, Nil>>> =
6135 DataSchemaBuilder::<Cons<ThingExtB, Cons<ThingExtA, Nil>>, _, _, _>::empty()
6136 .ext(DataSchemaExtA { a: A(1) })
6137 .ext_with(|| DataSchemaExtB {
6138 d: B("hello".to_string()),
6139 })
6140 .finish_extend()
6141 .title("title")
6142 .null()
6143 .try_into()
6144 .unwrap();
6145
6146 assert_eq!(
6147 data_schema,
6148 DataSchema {
6149 title: Some("title".to_string()),
6150 other: Nil::cons(DataSchemaExtA { a: A(1) }).cons(DataSchemaExtB {
6151 d: B("hello".to_string())
6152 }),
6153 attype: Default::default(),
6154 titles: Default::default(),
6155 description: Default::default(),
6156 descriptions: Default::default(),
6157 constant: Default::default(),
6158 default: Default::default(),
6159 unit: Default::default(),
6160 one_of: Default::default(),
6161 enumeration: Default::default(),
6162 read_only: Default::default(),
6163 write_only: Default::default(),
6164 format: Default::default(),
6165 subtype: Some(DataSchemaSubtype::Null),
6166 }
6167 );
6168 }
6169
6170 #[test]
6171 fn extend_data_schema_with_vec() {
6172 let data_schema: DataSchemaFromOther<Cons<ThingExtB, Cons<ThingExtA, Nil>>> =
6173 DataSchemaBuilder::<
6174 Cons<ThingExtB, Cons<ThingExtA, Nil>>,
6175 Cons<ArraySchemaExtB, Cons<ArraySchemaExtA, Nil>>,
6176 _,
6177 _,
6178 >::empty()
6179 .ext(DataSchemaExtA { a: A(1) })
6180 .ext_with(|| DataSchemaExtB {
6181 d: B("hello".to_string()),
6182 })
6183 .finish_extend()
6184 .title("title")
6185 .vec_ext(|b| {
6186 b.ext(ArraySchemaExtA { b: A(2) })
6187 .ext_with(|| ArraySchemaExtB {
6188 e: B("world".to_string()),
6189 })
6190 })
6191 .max_items(10)
6192 .try_into()
6193 .unwrap();
6194
6195 assert_eq!(
6196 data_schema,
6197 DataSchema {
6198 title: Some("title".to_string()),
6199 other: Nil::cons(DataSchemaExtA { a: A(1) }).cons(DataSchemaExtB {
6200 d: B("hello".to_string())
6201 }),
6202 attype: Default::default(),
6203 titles: Default::default(),
6204 description: Default::default(),
6205 descriptions: Default::default(),
6206 constant: Default::default(),
6207 default: Default::default(),
6208 unit: Default::default(),
6209 one_of: Default::default(),
6210 enumeration: Default::default(),
6211 read_only: Default::default(),
6212 write_only: Default::default(),
6213 format: Default::default(),
6214 subtype: Some(DataSchemaSubtype::Array(ArraySchema {
6215 other: Nil::cons(ArraySchemaExtA { b: A(2) }).cons(ArraySchemaExtB {
6216 e: B("world".to_string())
6217 }),
6218 max_items: Some(10),
6219 items: Default::default(),
6220 min_items: Default::default(),
6221 })),
6222 }
6223 );
6224 }
6225
6226 #[test]
6227 fn extend_data_schema_with_tuple() {
6228 let data_schema: DataSchemaFromOther<Cons<ThingExtB, Cons<ThingExtA, Nil>>> =
6229 DataSchemaBuilder::<
6230 Cons<ThingExtB, Cons<ThingExtA, Nil>>,
6231 Cons<ArraySchemaExtB, Cons<ArraySchemaExtA, Nil>>,
6232 _,
6233 _,
6234 >::empty()
6235 .ext(DataSchemaExtA { a: A(1) })
6236 .ext_with(|| DataSchemaExtB {
6237 d: B("hello".to_string()),
6238 })
6239 .finish_extend()
6240 .title("title")
6241 .tuple_ext(|b| {
6242 b.ext(ArraySchemaExtA { b: A(2) })
6243 .ext_with(|| ArraySchemaExtB {
6244 e: B("world".to_string()),
6245 })
6246 })
6247 .try_into()
6248 .unwrap();
6249
6250 assert_eq!(
6251 data_schema,
6252 DataSchema {
6253 title: Some("title".to_string()),
6254 other: Nil::cons(DataSchemaExtA { a: A(1) }).cons(DataSchemaExtB {
6255 d: B("hello".to_string())
6256 }),
6257 attype: Default::default(),
6258 titles: Default::default(),
6259 description: Default::default(),
6260 descriptions: Default::default(),
6261 constant: Default::default(),
6262 default: Default::default(),
6263 unit: Default::default(),
6264 one_of: Default::default(),
6265 enumeration: Default::default(),
6266 read_only: Default::default(),
6267 write_only: Default::default(),
6268 format: Default::default(),
6269 subtype: Some(DataSchemaSubtype::Array(ArraySchema {
6270 other: Nil::cons(ArraySchemaExtA { b: A(2) }).cons(ArraySchemaExtB {
6271 e: B("world".to_string())
6272 }),
6273 items: Some(BoxedElemOrVec::Vec(Vec::new())),
6274 max_items: Default::default(),
6275 min_items: Default::default(),
6276 })),
6277 }
6278 );
6279 }
6280
6281 #[test]
6282 fn extend_data_schema_with_object() {
6283 let data_schema: DataSchemaFromOther<Cons<ThingExtB, Cons<ThingExtA, Nil>>> =
6284 DataSchemaBuilder::<
6285 Cons<ThingExtB, Cons<ThingExtA, Nil>>,
6286 _,
6287 Cons<ObjectSchemaExtB, Cons<ObjectSchemaExtA, Nil>>,
6288 _,
6289 >::empty()
6290 .ext(DataSchemaExtA { a: A(1) })
6291 .ext_with(|| DataSchemaExtB {
6292 d: B("hello".to_string()),
6293 })
6294 .finish_extend()
6295 .title("title")
6296 .object_ext(|b| {
6297 b.ext(ObjectSchemaExtA { c: A(2) })
6298 .ext_with(|| ObjectSchemaExtB {
6299 f: B("world".to_string()),
6300 })
6301 })
6302 .property("x", false, |b| {
6303 b.ext(DataSchemaExtA { a: A(3) })
6304 .ext(DataSchemaExtB {
6305 d: B("other".to_string()),
6306 })
6307 .finish_extend()
6308 .null()
6309 })
6310 .try_into()
6311 .unwrap();
6312
6313 assert_eq!(
6314 data_schema,
6315 DataSchema {
6316 title: Some("title".to_string()),
6317 other: Nil::cons(DataSchemaExtA { a: A(1) }).cons(DataSchemaExtB {
6318 d: B("hello".to_string())
6319 }),
6320 subtype: Some(DataSchemaSubtype::Object(ObjectSchema {
6321 other: Nil::cons(ObjectSchemaExtA { c: A(2) }).cons(ObjectSchemaExtB {
6322 f: B("world".to_string())
6323 }),
6324 properties: Some(
6325 [(
6326 "x".to_string(),
6327 DataSchema {
6328 other: Nil::cons(DataSchemaExtA { a: A(3) }).cons(DataSchemaExtB {
6329 d: B("other".to_string())
6330 }),
6331 subtype: Some(DataSchemaSubtype::Null),
6332 attype: Default::default(),
6333 title: Default::default(),
6334 titles: Default::default(),
6335 description: Default::default(),
6336 descriptions: Default::default(),
6337 constant: Default::default(),
6338 default: Default::default(),
6339 unit: Default::default(),
6340 one_of: Default::default(),
6341 enumeration: Default::default(),
6342 read_only: Default::default(),
6343 write_only: Default::default(),
6344 format: Default::default(),
6345 }
6346 )]
6347 .into_iter()
6348 .collect()
6349 ),
6350 required: None,
6351 })),
6352 attype: Default::default(),
6353 titles: Default::default(),
6354 description: Default::default(),
6355 descriptions: Default::default(),
6356 constant: Default::default(),
6357 default: Default::default(),
6358 unit: Default::default(),
6359 one_of: Default::default(),
6360 enumeration: Default::default(),
6361 read_only: Default::default(),
6362 write_only: Default::default(),
6363 format: Default::default(),
6364 }
6365 );
6366 }
6367
6368 #[test]
6369 fn valid_unchecked_tuple_data_schema() {
6370 let data_schema = UncheckedArraySchema::<Nil, Nil, Nil> {
6371 items: Some(BoxedElemOrVec::Vec(vec![
6372 UncheckedDataSchema {
6373 titles: Some({
6374 let mut multilang = MultiLanguageBuilder::default();
6375 multilang.add("it", "title1").add("en", "title2");
6376 multilang
6377 }),
6378 descriptions: Some({
6379 let mut multilang = MultiLanguageBuilder::default();
6380 multilang
6381 .add("it", "description1")
6382 .add("en", "description2");
6383 multilang
6384 }),
6385 ..Default::default()
6386 },
6387 UncheckedDataSchema {
6388 titles: Some({
6389 let mut multilang = MultiLanguageBuilder::default();
6390 multilang.add("it", "title3").add("en", "title4");
6391 multilang
6392 }),
6393 descriptions: Some({
6394 let mut multilang = MultiLanguageBuilder::default();
6395 multilang
6396 .add("it", "description3")
6397 .add("en", "description4");
6398 multilang
6399 }),
6400 ..Default::default()
6401 },
6402 ])),
6403 ..Default::default()
6404 };
6405
6406 assert_eq!(
6407 ArraySchema::try_from(data_schema).unwrap(),
6408 ArraySchema {
6409 items: Some(BoxedElemOrVec::Vec(vec![
6410 DataSchema {
6411 titles: Some(
6412 [
6413 ("it".parse().unwrap(), "title1".to_string()),
6414 ("en".parse().unwrap(), "title2".to_string())
6415 ]
6416 .into_iter()
6417 .collect()
6418 ),
6419 descriptions: Some(
6420 [
6421 ("it".parse().unwrap(), "description1".to_string()),
6422 ("en".parse().unwrap(), "description2".to_string())
6423 ]
6424 .into_iter()
6425 .collect()
6426 ),
6427 ..Default::default()
6428 },
6429 DataSchema {
6430 titles: Some(
6431 [
6432 ("it".parse().unwrap(), "title3".to_string()),
6433 ("en".parse().unwrap(), "title4".to_string())
6434 ]
6435 .into_iter()
6436 .collect()
6437 ),
6438 descriptions: Some(
6439 [
6440 ("it".parse().unwrap(), "description3".to_string()),
6441 ("en".parse().unwrap(), "description4".to_string())
6442 ]
6443 .into_iter()
6444 .collect()
6445 ),
6446 ..Default::default()
6447 },
6448 ])),
6449 ..Default::default()
6450 }
6451 );
6452 }
6453
6454 #[test]
6455 fn invalid_unchecked_tuple_data_schema() {
6456 let data_schema = UncheckedArraySchema::<Nil, Nil, Nil> {
6457 items: Some(BoxedElemOrVec::Vec(vec![
6458 UncheckedDataSchema {
6459 titles: Some({
6460 let mut multilang = MultiLanguageBuilder::default();
6461 multilang.add("it", "title1").add("en", "title2");
6462 multilang
6463 }),
6464 descriptions: Some({
6465 let mut multilang = MultiLanguageBuilder::default();
6466 multilang
6467 .add("it", "description1")
6468 .add("en", "description2");
6469 multilang
6470 }),
6471 ..Default::default()
6472 },
6473 UncheckedDataSchema {
6474 titles: Some({
6475 let mut multilang = MultiLanguageBuilder::default();
6476 multilang.add("it", "title3").add("en", "title4");
6477 multilang
6478 }),
6479 descriptions: Some({
6480 let mut multilang = MultiLanguageBuilder::default();
6481 multilang
6482 .add("it", "description3")
6483 .add("e1n", "description4");
6484 multilang
6485 }),
6486 ..Default::default()
6487 },
6488 ])),
6489 ..Default::default()
6490 };
6491
6492 assert_eq!(
6493 ArraySchema::try_from(data_schema).unwrap_err(),
6494 Error::InvalidLanguageTag("e1n".to_string()),
6495 );
6496 }
6497
6498 #[test]
6499 fn valid_unchecked_vec_data_schema() {
6500 let data_schema = UncheckedArraySchema::<Nil, Nil, Nil> {
6501 items: Some(BoxedElemOrVec::Elem(Box::new(UncheckedDataSchema {
6502 titles: Some({
6503 let mut multilang = MultiLanguageBuilder::default();
6504 multilang.add("it", "title1").add("en", "title2");
6505 multilang
6506 }),
6507 descriptions: Some({
6508 let mut multilang = MultiLanguageBuilder::default();
6509 multilang
6510 .add("it", "description1")
6511 .add("en", "description2");
6512 multilang
6513 }),
6514 ..Default::default()
6515 }))),
6516 min_items: Some(1),
6517 ..Default::default()
6518 };
6519
6520 assert_eq!(
6521 ArraySchema::try_from(data_schema).unwrap(),
6522 ArraySchema {
6523 items: Some(BoxedElemOrVec::Elem(Box::new(DataSchema {
6524 titles: Some(
6525 [
6526 ("it".parse().unwrap(), "title1".to_string()),
6527 ("en".parse().unwrap(), "title2".to_string())
6528 ]
6529 .into_iter()
6530 .collect()
6531 ),
6532 descriptions: Some(
6533 [
6534 ("it".parse().unwrap(), "description1".to_string()),
6535 ("en".parse().unwrap(), "description2".to_string())
6536 ]
6537 .into_iter()
6538 .collect()
6539 ),
6540 ..Default::default()
6541 },))),
6542 min_items: Some(1),
6543 ..Default::default()
6544 }
6545 );
6546 }
6547
6548 #[test]
6549 fn invalid_unchecked_vec_data_schema() {
6550 let data_schema = UncheckedArraySchema::<Nil, Nil, Nil> {
6551 items: Some(BoxedElemOrVec::Elem(Box::new(UncheckedDataSchema {
6552 titles: Some({
6553 let mut multilang = MultiLanguageBuilder::default();
6554 multilang.add("it", "title1").add("en", "title2");
6555 multilang
6556 }),
6557 descriptions: Some({
6558 let mut multilang = MultiLanguageBuilder::default();
6559 multilang
6560 .add("it", "description1")
6561 .add("e1n", "description2");
6562 multilang
6563 }),
6564 ..Default::default()
6565 }))),
6566 min_items: Some(1),
6567 ..Default::default()
6568 };
6569
6570 assert_eq!(
6571 ArraySchema::try_from(data_schema).unwrap_err(),
6572 Error::InvalidLanguageTag("e1n".to_string()),
6573 );
6574 }
6575
6576 #[test]
6577 fn valid_unchecked_object_data_schema() {
6578 let data_schema = UncheckedObjectSchema::<Nil, Nil, Nil> {
6579 properties: Some(
6580 [
6581 (
6582 "data1".to_string(),
6583 UncheckedDataSchema {
6584 titles: Some({
6585 let mut multilang = MultiLanguageBuilder::default();
6586 multilang.add("it", "title1").add("en", "title2");
6587 multilang
6588 }),
6589 descriptions: Some({
6590 let mut multilang = MultiLanguageBuilder::default();
6591 multilang
6592 .add("it", "description1")
6593 .add("en", "description2");
6594 multilang
6595 }),
6596 ..Default::default()
6597 },
6598 ),
6599 (
6600 "data2".to_string(),
6601 UncheckedDataSchema {
6602 titles: Some({
6603 let mut multilang = MultiLanguageBuilder::default();
6604 multilang.add("it", "title3").add("en", "title4");
6605 multilang
6606 }),
6607 descriptions: Some({
6608 let mut multilang = MultiLanguageBuilder::default();
6609 multilang
6610 .add("it", "description3")
6611 .add("en", "description4");
6612 multilang
6613 }),
6614 ..Default::default()
6615 },
6616 ),
6617 ]
6618 .into_iter()
6619 .collect(),
6620 ),
6621 ..Default::default()
6622 };
6623
6624 assert_eq!(
6625 ObjectSchema::try_from(data_schema).unwrap(),
6626 ObjectSchema {
6627 properties: Some(
6628 [
6629 (
6630 "data1".to_string(),
6631 DataSchema {
6632 titles: Some(
6633 [
6634 ("it".parse().unwrap(), "title1".to_string()),
6635 ("en".parse().unwrap(), "title2".to_string())
6636 ]
6637 .into_iter()
6638 .collect()
6639 ),
6640 descriptions: Some(
6641 [
6642 ("it".parse().unwrap(), "description1".to_string()),
6643 ("en".parse().unwrap(), "description2".to_string())
6644 ]
6645 .into_iter()
6646 .collect()
6647 ),
6648 ..Default::default()
6649 }
6650 ),
6651 (
6652 "data2".to_string(),
6653 DataSchema {
6654 titles: Some(
6655 [
6656 ("it".parse().unwrap(), "title3".to_string()),
6657 ("en".parse().unwrap(), "title4".to_string())
6658 ]
6659 .into_iter()
6660 .collect()
6661 ),
6662 descriptions: Some(
6663 [
6664 ("it".parse().unwrap(), "description3".to_string()),
6665 ("en".parse().unwrap(), "description4".to_string())
6666 ]
6667 .into_iter()
6668 .collect()
6669 ),
6670 ..Default::default()
6671 }
6672 ),
6673 ]
6674 .into_iter()
6675 .collect()
6676 ),
6677 ..Default::default()
6678 }
6679 );
6680 }
6681
6682 #[test]
6683 fn invalid_unchecked_object_data_schema() {
6684 let data_schema = UncheckedObjectSchema::<Nil, Nil, Nil> {
6685 properties: Some(
6686 [
6687 (
6688 "data1".to_string(),
6689 UncheckedDataSchema {
6690 titles: Some({
6691 let mut multilang = MultiLanguageBuilder::default();
6692 multilang.add("it", "title1").add("en", "title2");
6693 multilang
6694 }),
6695 descriptions: Some({
6696 let mut multilang = MultiLanguageBuilder::default();
6697 multilang
6698 .add("it", "description1")
6699 .add("en", "description2");
6700 multilang
6701 }),
6702 ..Default::default()
6703 },
6704 ),
6705 (
6706 "data2".to_string(),
6707 UncheckedDataSchema {
6708 titles: Some({
6709 let mut multilang = MultiLanguageBuilder::default();
6710 multilang.add("it", "title3").add("en", "title4");
6711 multilang
6712 }),
6713 descriptions: Some({
6714 let mut multilang = MultiLanguageBuilder::default();
6715 multilang
6716 .add("i1t", "description3")
6717 .add("en", "description4");
6718 multilang
6719 }),
6720 ..Default::default()
6721 },
6722 ),
6723 ]
6724 .into_iter()
6725 .collect(),
6726 ),
6727 ..Default::default()
6728 };
6729
6730 assert_eq!(
6731 ObjectSchema::try_from(data_schema).unwrap_err(),
6732 Error::InvalidLanguageTag("i1t".to_string()),
6733 )
6734 }
6735
6736 #[test]
6737 fn valid_unchecked_data_schema() {
6738 let data_schema = UncheckedDataSchema::<Nil, Nil, Nil> {
6739 attype: Some(vec!["attype1".to_string(), "attype2".to_string()]),
6740 title: Some("title".to_string()),
6741 titles: Some({
6742 let mut multilang = MultiLanguageBuilder::default();
6743 multilang.add("it", "title1").add("en", "title2");
6744 multilang
6745 }),
6746 description: Some("description".to_string()),
6747 descriptions: Some({
6748 let mut multilang = MultiLanguageBuilder::default();
6749 multilang
6750 .add("it", "description1")
6751 .add("en", "description2");
6752 multilang
6753 }),
6754 unit: Some("unit".to_string()),
6755 read_only: true,
6756 write_only: true,
6757 format: Some("format".to_string()),
6758 subtype: Some(UncheckedDataSchemaSubtype::Number(NumberSchema {
6759 maximum: Some(Maximum::Inclusive(5.)),
6760 ..Default::default()
6761 })),
6762 ..Default::default()
6763 };
6764
6765 assert_eq!(
6766 DataSchema::try_from(data_schema).unwrap(),
6767 DataSchema {
6768 attype: Some(vec!["attype1".to_string(), "attype2".to_string()]),
6769 title: Some("title".to_string()),
6770 titles: Some(
6771 [
6772 ("it".parse().unwrap(), "title1".to_string()),
6773 ("en".parse().unwrap(), "title2".to_string())
6774 ]
6775 .into_iter()
6776 .collect()
6777 ),
6778 description: Some("description".to_string()),
6779 descriptions: Some(
6780 [
6781 ("it".parse().unwrap(), "description1".to_string()),
6782 ("en".parse().unwrap(), "description2".to_string())
6783 ]
6784 .into_iter()
6785 .collect()
6786 ),
6787 unit: Some("unit".to_string()),
6788 read_only: true,
6789 write_only: true,
6790 format: Some("format".to_string()),
6791 subtype: Some(DataSchemaSubtype::Number(NumberSchema {
6792 maximum: Some(Maximum::Inclusive(5.)),
6793 ..Default::default()
6794 })),
6795 ..Default::default()
6796 }
6797 );
6798 }
6799
6800 #[test]
6801 fn invalid_unchecked_data_schema() {
6802 let data_schema = UncheckedDataSchema::<Nil, Nil, Nil> {
6803 attype: Some(vec!["attype1".to_string(), "attype2".to_string()]),
6804 title: Some("title".to_string()),
6805 titles: Some({
6806 let mut multilang = MultiLanguageBuilder::default();
6807 multilang.add("it", "title1").add("en", "title2");
6808 multilang
6809 }),
6810 description: Some("description".to_string()),
6811 descriptions: Some({
6812 let mut multilang = MultiLanguageBuilder::default();
6813 multilang
6814 .add("i1t", "description1")
6815 .add("en", "description2");
6816 multilang
6817 }),
6818 unit: Some("unit".to_string()),
6819 read_only: true,
6820 write_only: true,
6821 format: Some("format".to_string()),
6822 subtype: Some(UncheckedDataSchemaSubtype::Number(NumberSchema {
6823 maximum: Some(Maximum::Inclusive(5.)),
6824 ..Default::default()
6825 })),
6826 ..Default::default()
6827 };
6828
6829 assert_eq!(
6830 DataSchema::try_from(data_schema).unwrap_err(),
6831 Error::InvalidLanguageTag("i1t".to_string()),
6832 );
6833 }
6834}