1use crate::{
2 rules::Rules, AsyncCheck, Context, LengthType, SchemaContext, SchemaMode, SchemaReport, Stage,
3 StringType, TypeKind, ValidationError, ValidationErrors, Value,
4};
5use serde::de::{self, Visitor};
6use serde_json::{json, value::RawValue};
7use std::{
8 borrow::Cow,
9 collections::{BTreeMap, HashMap, HashSet},
10 fmt,
11 hash::BuildHasher,
12 marker::PhantomData,
13};
14
15#[derive(Debug, Clone)]
17pub enum Input<'de> {
18 Borrowed(&'de RawValue),
19 Owned(Value),
20 Object(BTreeMap<String, Input<'de>>),
21}
22impl<'de> Input<'de> {
23 pub fn into_value(self, ctx: &mut Context) -> Option<Value> {
24 match self {
25 Self::Object(object) => Self::from_object(object, ctx),
26 Self::Owned(value) => Some(value),
27 Self::Borrowed(raw) => serde_json::from_str(raw.get())
28 .map_err(|e| ctx.push(json_error(e)))
29 .ok(),
30 }
31 }
32 pub fn object(self, ctx: &mut Context) -> Option<BTreeMap<String, Self>> {
33 match self {
34 Self::Object(object) => Some(object),
35 Self::Borrowed(raw) => {
36 serde_json::from_str::<BTreeMap<String, &'de RawValue>>(raw.get())
37 .map(|map| {
38 map.into_iter()
39 .map(|(k, v)| (k, Self::Borrowed(v)))
40 .collect()
41 })
42 .map_err(|_| ctx.push(type_error("object")))
43 .ok()
44 }
45 Self::Owned(Value::Object(map)) => {
46 Some(map.into_iter().map(|(k, v)| (k, Self::Owned(v))).collect())
47 }
48 _ => {
49 ctx.push(type_error("object"));
50 None
51 }
52 }
53 }
54 pub fn array(self, ctx: &mut Context) -> Option<Vec<Self>> {
55 match self {
56 Self::Borrowed(raw) => serde_json::from_str::<Vec<&'de RawValue>>(raw.get())
57 .map(|items| items.into_iter().map(Self::Borrowed).collect())
58 .map_err(|_| ctx.push(type_error("array")))
59 .ok(),
60 Self::Owned(Value::Array(items)) => Some(items.into_iter().map(Self::Owned).collect()),
61 _ => {
62 ctx.push(type_error("array"));
63 None
64 }
65 }
66 }
67 pub fn from_object(object: BTreeMap<String, Self>, ctx: &mut Context) -> Option<Value> {
68 let mut result = serde_json::Map::new();
69 for (key, value) in object {
70 result.insert(key, value.into_value(ctx)?);
71 }
72 Some(Value::Object(result))
73 }
74 pub fn is_null(&self) -> bool {
75 match self {
76 Self::Borrowed(raw) => raw.get() == "null",
77 Self::Owned(v) => v.is_null(),
78 Self::Object(_) => false,
79 }
80 }
81}
82pub(crate) fn json_error(error: serde_json::Error) -> ValidationError {
83 ValidationError::new("json_invalid", error.to_string())
84 .with_stage(Stage::Parse)
85 .with_param("line", error.line())
86 .with_param("column", error.column())
87}
88fn type_error(expected: &str) -> ValidationError {
89 ValidationError::new("type_error", format!("expected {expected}")).with_stage(Stage::Parse)
90}
91
92pub trait BorrowType<'de>: Sized {
94 fn decode(value: Input<'de>, ctx: &mut Context, coerce: bool) -> Option<Self>;
95 fn encode(&self, ctx: &mut Context) -> Value;
96 fn encode_input(&self, ctx: &mut Context) -> Value {
97 self.encode(ctx)
98 }
99 fn schema(ctx: &mut SchemaContext, coerce: bool) -> Value;
100 fn validate_into(&self, _ctx: &mut Context) {}
101 fn prepare_default(self, ctx: &mut Context) -> Option<Self> {
102 self.validate_into(ctx);
103 Some(self)
104 }
105 fn normalize(self, rules: &Rules, ctx: &mut Context) -> Option<Self> {
106 if !rules.normalizes() {
107 return Some(self);
108 }
109 let mut value = self.encode_input(ctx);
110 rules.prepare(&mut value);
111 Self::decode(Input::Owned(value), ctx, false)
112 }
113 fn validate_rules(&self, rules: &Rules, ctx: &mut Context) {
114 rules.validate(&self.encode(ctx), ctx);
115 }
116 fn missing() -> Option<Self> {
117 None
118 }
119 fn allows_missing() -> bool {
120 false
121 }
122 fn kind() -> TypeKind {
123 TypeKind::Any
124 }
125 fn async_required(_seen: &mut HashSet<&'static str>) -> bool {
126 false
127 }
128}
129
130pub trait BorrowModel<'de>: BorrowType<'de> {
132 fn parse_json(input: &'de str) -> Result<Self, ValidationErrors> {
133 let raw = serde_json::from_str::<&'de RawValue>(input).map_err(json_error)?;
134 Self::parse_raw(raw)
135 }
136 fn parse_slice(input: &'de [u8]) -> Result<Self, ValidationErrors> {
137 let raw = serde_json::from_slice::<&'de RawValue>(input).map_err(json_error)?;
138 Self::parse_raw(raw)
139 }
140 fn parse_raw(raw: &'de RawValue) -> Result<Self, ValidationErrors> {
141 crate::asynchronous::sync_guard(Self::async_required(&mut HashSet::new()))?;
142 let mut ctx = Context::new();
143 let value = Self::decode(Input::Borrowed(raw), &mut ctx, false);
144 ctx.finish(value)
145 }
146 fn validate(&self) -> Result<(), ValidationErrors> {
147 crate::asynchronous::sync_guard(Self::async_required(&mut HashSet::new()))?;
148 let mut ctx = Context::new();
149 self.validate_into(&mut ctx);
150 ctx.result()
151 }
152 fn dump(&self) -> Result<Value, ValidationErrors> {
153 self.validate()?;
154 let mut ctx = Context::new();
155 let value = self.encode(&mut ctx);
156 ctx.finish(Some(value))
157 }
158 fn dump_json(&self) -> Result<String, ValidationErrors> {
159 Ok(self.dump()?.to_string())
160 }
161 fn json_schema(mode: SchemaMode) -> Value {
162 let mut ctx = SchemaContext::new(mode);
163 let root = Self::schema(&mut ctx, false);
164 ctx.finish(root)
165 }
166 fn schema_report(mode: SchemaMode) -> SchemaReport {
167 SchemaReport::new(Self::json_schema(mode))
168 }
169 fn parse_validated_json(
170 input: &'de str,
171 ) -> Result<BorrowValidated<'de, Self>, ValidationErrors> {
172 Self::parse_json(input).map(|value| BorrowValidated(value, PhantomData))
173 }
174 fn parse_json_async(
175 input: &'de str,
176 ) -> impl std::future::Future<Output = Result<Self, ValidationErrors>> + Send
177 where
178 Self: AsyncCheck + Send,
179 {
180 async move {
181 let raw = serde_json::from_str::<&'de RawValue>(input).map_err(json_error)?;
182 let mut ctx = Context::new();
183 let value = Self::decode(Input::Borrowed(raw), &mut ctx, false);
184 let value = ctx.finish(value)?;
185 let mut ctx = Context::new();
186 value.check_async(&mut ctx).await;
187 ctx.result()?;
188 Ok(value)
189 }
190 }
191 fn validate_async(
192 &self,
193 ) -> impl std::future::Future<Output = Result<(), ValidationErrors>> + Send
194 where
195 Self: AsyncCheck,
196 {
197 async move {
198 let mut ctx = Context::new();
199 self.validate_into(&mut ctx);
200 ctx.result()?;
201 let mut ctx = Context::new();
202 self.check_async(&mut ctx).await;
203 ctx.result()
204 }
205 }
206 fn dump_async(
207 &self,
208 ) -> impl std::future::Future<Output = Result<Value, ValidationErrors>> + Send
209 where
210 Self: AsyncCheck,
211 {
212 async move {
213 self.validate_async().await?;
214 let mut ctx = Context::new();
215 let value = self.encode(&mut ctx);
216 ctx.finish(Some(value))
217 }
218 }
219 fn dump_json_async(
220 &self,
221 ) -> impl std::future::Future<Output = Result<String, ValidationErrors>> + Send
222 where
223 Self: AsyncCheck,
224 {
225 async move { Ok(self.dump_async().await?.to_string()) }
226 }
227}
228#[derive(Debug, Clone, PartialEq, Eq)]
229pub struct BorrowValidated<'de, T: BorrowModel<'de>>(T, PhantomData<&'de str>);
230impl<'de, T: BorrowModel<'de>> BorrowValidated<'de, T> {
231 pub fn new(value: T) -> Result<Self, ValidationErrors> {
232 value.validate()?;
233 Ok(Self(value, PhantomData))
234 }
235 pub fn get(&self) -> &T {
236 &self.0
237 }
238 pub fn into_inner(self) -> T {
239 self.0
240 }
241}
242impl<'de, T: BorrowModel<'de>> std::ops::Deref for BorrowValidated<'de, T> {
243 type Target = T;
244 fn deref(&self) -> &T {
245 &self.0
246 }
247}
248impl<'de, T: BorrowModel<'de>> serde::Serialize for BorrowValidated<'de, T> {
249 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
250 self.0
251 .dump()
252 .map_err(serde::ser::Error::custom)?
253 .serialize(s)
254 }
255}
256
257impl<'de, T: BorrowModel<'de>> serde::Deserialize<'de> for BorrowValidated<'de, T> {
258 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
259 let raw = <&'de RawValue as serde::Deserialize>::deserialize(deserializer)?;
260 T::parse_raw(raw)
261 .map(|value| Self(value, PhantomData))
262 .map_err(serde::de::Error::custom)
263 }
264}
265
266macro_rules! owned {
267 ($($ty:ty),* $(,)?) => {$(impl<'de> BorrowType<'de> for $ty {
268 fn decode(value:Input<'de>,ctx:&mut Context,coerce:bool)->Option<Self>{<Self as crate::JsonType>::decode_input(value,ctx,coerce)}
269 fn encode(&self,ctx:&mut Context)->Value{<Self as crate::JsonType>::encode(self,ctx)}
270 fn schema(ctx:&mut SchemaContext,coerce:bool)->Value{<Self as crate::JsonType>::schema(ctx,coerce)}
271 fn validate_into(&self,ctx:&mut Context){<Self as crate::JsonType>::validate_into(self,ctx)}
272 fn validate_rules(&self,rules:&Rules,ctx:&mut Context){<Self as crate::JsonType>::validate_rules(self,rules,ctx)}
273 fn kind()->TypeKind{<Self as crate::JsonType>::kind()}
274 })*};
275}
276owned!(
277 String,
278 bool,
279 i8,
280 i16,
281 i32,
282 i64,
283 i128,
284 isize,
285 u8,
286 u16,
287 u32,
288 u64,
289 u128,
290 usize,
291 f32,
292 f64,
293 Value,
294 ()
295);
296#[cfg(feature = "chrono")]
297owned!(
298 chrono::NaiveDate,
299 chrono::NaiveTime,
300 chrono::NaiveDateTime,
301 chrono::DateTime<chrono::Utc>,
302 chrono::DateTime<chrono::FixedOffset>
303);
304#[cfg(feature = "decimal")]
305owned!(rust_decimal::Decimal);
306
307impl<'de: 'a, 'a> BorrowType<'de> for &'a str {
308 fn decode(value: Input<'de>, ctx: &mut Context, _: bool) -> Option<Self> {
309 match value {
310 Input::Borrowed(raw) => serde_json::from_str::<&'de str>(raw.get())
311 .map_err(|_| {
312 ctx.push(
313 ValidationError::new(
314 "borrowed_string",
315 "expected an unescaped JSON string; use Cow<str> for escaped strings",
316 )
317 .with_stage(Stage::Parse),
318 )
319 })
320 .ok(),
321 _ => {
322 ctx.push(
323 ValidationError::new(
324 "borrowed_string",
325 "a borrowed string requires input backed by the original buffer",
326 )
327 .with_stage(Stage::Parse),
328 );
329 None
330 }
331 }
332 }
333 fn encode(&self, _: &mut Context) -> Value {
334 Value::String((*self).to_owned())
335 }
336 fn schema(ctx: &mut SchemaContext, _: bool) -> Value {
337 if ctx.mode == SchemaMode::Input {
338 json!({"type":"string","x-rydantic-local-rules":["borrowed_unescaped_string"]})
339 } else {
340 json!({"type":"string"})
341 }
342 }
343 fn normalize(self, rules: &Rules, ctx: &mut Context) -> Option<Self> {
344 let text = if rules.trim { self.trim() } else { self };
345 if (rules.lowercase && text.to_lowercase() != text)
346 || (rules.uppercase && text.to_uppercase() != text)
347 {
348 ctx.push(ValidationError::new(
349 "borrowed_transform",
350 "case conversion requires Cow<str> or String",
351 ));
352 None
353 } else {
354 Some(text)
355 }
356 }
357 fn kind() -> TypeKind {
358 TypeKind::String
359 }
360}
361impl StringType for &str {}
362impl LengthType for &str {}
363struct CowVisitor;
364impl<'de> Visitor<'de> for CowVisitor {
365 type Value = Cow<'de, str>;
366 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
367 f.write_str("a JSON string")
368 }
369 fn visit_borrowed_str<E: de::Error>(self, v: &'de str) -> Result<Self::Value, E> {
370 Ok(Cow::Borrowed(v))
371 }
372 fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
373 Ok(Cow::Owned(v.to_owned()))
374 }
375 fn visit_string<E: de::Error>(self, v: String) -> Result<Self::Value, E> {
376 Ok(Cow::Owned(v))
377 }
378}
379impl<'de: 'a, 'a> BorrowType<'de> for Cow<'a, str> {
380 fn decode(value: Input<'de>, ctx: &mut Context, coerce: bool) -> Option<Self> {
381 match value {
382 Input::Borrowed(raw) if raw.get().starts_with('"') => {
383 let mut deserializer = serde_json::Deserializer::from_str(raw.get());
384 serde::Deserializer::deserialize_str(&mut deserializer, CowVisitor)
385 .map_err(|e| ctx.push(json_error(e)))
386 .ok()
387 }
388 value => <String as BorrowType>::decode(value, ctx, coerce).map(Cow::Owned),
389 }
390 }
391 fn encode(&self, _: &mut Context) -> Value {
392 Value::String(self.to_string())
393 }
394 fn schema(ctx: &mut SchemaContext, coerce: bool) -> Value {
395 <String as crate::JsonType>::schema(ctx, coerce)
396 }
397 fn normalize(self, rules: &Rules, _: &mut Context) -> Option<Self> {
398 let value = match self {
399 Cow::Borrowed(v) => Cow::Borrowed(if rules.trim { v.trim() } else { v }),
400 Cow::Owned(v) => Cow::Owned(if rules.trim { v.trim().to_owned() } else { v }),
401 };
402 if rules.lowercase {
403 let v = value.to_lowercase();
404 if v != value {
405 return Some(Cow::Owned(v));
406 }
407 }
408 if rules.uppercase {
409 let v = value.to_uppercase();
410 if v != value {
411 return Some(Cow::Owned(v));
412 }
413 }
414 Some(value)
415 }
416 fn kind() -> TypeKind {
417 TypeKind::String
418 }
419}
420impl StringType for Cow<'_, str> {}
421impl LengthType for Cow<'_, str> {}
422
423impl<'de, T: BorrowType<'de>> BorrowType<'de> for Option<T> {
424 fn prepare_default(self, ctx: &mut Context) -> Option<Self> {
425 match self {
426 Some(value) => value.prepare_default(ctx).map(Some),
427 None => Some(None),
428 }
429 }
430 fn decode(value: Input<'de>, ctx: &mut Context, coerce: bool) -> Option<Self> {
431 if value.is_null() {
432 Some(None)
433 } else {
434 T::decode(value, ctx, coerce).map(Some)
435 }
436 }
437 fn encode(&self, ctx: &mut Context) -> Value {
438 self.as_ref().map_or(Value::Null, |v| v.encode(ctx))
439 }
440 fn encode_input(&self, ctx: &mut Context) -> Value {
441 self.as_ref().map_or(Value::Null, |v| v.encode_input(ctx))
442 }
443 fn schema(ctx: &mut SchemaContext, coerce: bool) -> Value {
444 json!({"anyOf":[T::schema(ctx,coerce),{"type":"null"}]})
445 }
446 fn validate_into(&self, ctx: &mut Context) {
447 if let Some(v) = self {
448 v.validate_into(ctx)
449 }
450 }
451 fn normalize(self, rules: &Rules, ctx: &mut Context) -> Option<Self> {
452 match self {
453 Some(v) => v.normalize(rules, ctx).map(Some),
454 None => Some(None),
455 }
456 }
457 fn validate_rules(&self, rules: &Rules, ctx: &mut Context) {
458 if let Some(v) = self {
459 v.validate_rules(rules, ctx)
460 }
461 }
462 fn missing() -> Option<Self> {
463 Some(None)
464 }
465 fn allows_missing() -> bool {
466 true
467 }
468 fn kind() -> TypeKind {
469 T::kind()
470 }
471 fn async_required(seen: &mut HashSet<&'static str>) -> bool {
472 T::async_required(seen)
473 }
474}
475impl<'de, T: BorrowType<'de>> BorrowType<'de> for Box<T> {
476 fn prepare_default(self, ctx: &mut Context) -> Option<Self> {
477 (*self).prepare_default(ctx).map(Box::new)
478 }
479 fn decode(value: Input<'de>, ctx: &mut Context, coerce: bool) -> Option<Self> {
480 T::decode(value, ctx, coerce).map(Box::new)
481 }
482 fn encode(&self, ctx: &mut Context) -> Value {
483 (**self).encode(ctx)
484 }
485 fn encode_input(&self, ctx: &mut Context) -> Value {
486 (**self).encode_input(ctx)
487 }
488 fn schema(ctx: &mut SchemaContext, coerce: bool) -> Value {
489 T::schema(ctx, coerce)
490 }
491 fn validate_into(&self, ctx: &mut Context) {
492 (**self).validate_into(ctx)
493 }
494 fn normalize(self, rules: &Rules, ctx: &mut Context) -> Option<Self> {
495 (*self).normalize(rules, ctx).map(Box::new)
496 }
497 fn validate_rules(&self, rules: &Rules, ctx: &mut Context) {
498 (**self).validate_rules(rules, ctx)
499 }
500 fn missing() -> Option<Self> {
501 T::missing().map(Box::new)
502 }
503 fn allows_missing() -> bool {
504 T::allows_missing()
505 }
506 fn kind() -> TypeKind {
507 T::kind()
508 }
509 fn async_required(seen: &mut HashSet<&'static str>) -> bool {
510 T::async_required(seen)
511 }
512}
513impl<'de, T: BorrowType<'de>> BorrowType<'de> for Vec<T> {
514 fn validate_rules(&self, rules: &Rules, ctx: &mut Context) {
515 rules.validate_length(self.len(), ctx)
516 }
517 fn prepare_default(self, ctx: &mut Context) -> Option<Self> {
518 let mut result = Vec::with_capacity(self.len());
519 let mut complete = true;
520 for (i, value) in self.into_iter().enumerate() {
521 match ctx.at(i, |ctx| value.prepare_default(ctx)) {
522 Some(v) => result.push(v),
523 None => complete = false,
524 }
525 }
526 complete.then_some(result)
527 }
528 fn decode(value: Input<'de>, ctx: &mut Context, coerce: bool) -> Option<Self> {
529 let items = value.array(ctx)?;
530 let mut result = Vec::with_capacity(items.len());
531 let mut complete = true;
532 for (i, value) in items.into_iter().enumerate() {
533 match ctx.at(i, |ctx| T::decode(value, ctx, coerce)) {
534 Some(v) => result.push(v),
535 None => complete = false,
536 }
537 }
538 complete.then_some(result)
539 }
540 fn encode(&self, ctx: &mut Context) -> Value {
541 Value::Array(
542 self.iter()
543 .enumerate()
544 .map(|(i, v)| ctx.at(i, |ctx| v.encode(ctx)))
545 .collect(),
546 )
547 }
548 fn encode_input(&self, ctx: &mut Context) -> Value {
549 Value::Array(
550 self.iter()
551 .enumerate()
552 .map(|(i, v)| ctx.at(i, |ctx| v.encode_input(ctx)))
553 .collect(),
554 )
555 }
556 fn schema(ctx: &mut SchemaContext, coerce: bool) -> Value {
557 json!({"type":"array","items":T::schema(ctx,coerce)})
558 }
559 fn validate_into(&self, ctx: &mut Context) {
560 for (i, v) in self.iter().enumerate() {
561 ctx.at(i, |ctx| v.validate_into(ctx));
562 }
563 }
564 fn kind() -> TypeKind {
565 TypeKind::Array
566 }
567 fn async_required(seen: &mut HashSet<&'static str>) -> bool {
568 T::async_required(seen)
569 }
570}
571impl<'de, T: BorrowType<'de>, const N: usize> BorrowType<'de> for [T; N] {
572 fn validate_rules(&self, rules: &Rules, ctx: &mut Context) {
573 rules.validate_length(self.len(), ctx)
574 }
575 fn prepare_default(self, ctx: &mut Context) -> Option<Self> {
576 <Vec<T> as BorrowType>::prepare_default(Vec::from(self), ctx)?
577 .try_into()
578 .ok()
579 }
580 fn decode(value: Input<'de>, ctx: &mut Context, coerce: bool) -> Option<Self> {
581 let items = <Vec<T> as BorrowType>::decode(value, ctx, coerce)?;
582 let len = items.len();
583 items
584 .try_into()
585 .map_err(|_| {
586 ctx.push(
587 ValidationError::new(
588 "array_length",
589 format!("array must contain exactly {N} items"),
590 )
591 .with_param("actual", len),
592 )
593 })
594 .ok()
595 }
596 fn encode(&self, ctx: &mut Context) -> Value {
597 Value::Array(
598 self.iter()
599 .enumerate()
600 .map(|(i, v)| ctx.at(i, |ctx| v.encode(ctx)))
601 .collect(),
602 )
603 }
604 fn encode_input(&self, ctx: &mut Context) -> Value {
605 Value::Array(
606 self.iter()
607 .enumerate()
608 .map(|(i, v)| ctx.at(i, |ctx| v.encode_input(ctx)))
609 .collect(),
610 )
611 }
612 fn schema(ctx: &mut SchemaContext, coerce: bool) -> Value {
613 json!({"type":"array","items":T::schema(ctx,coerce),"minItems":N,"maxItems":N})
614 }
615 fn validate_into(&self, ctx: &mut Context) {
616 for (i, v) in self.iter().enumerate() {
617 ctx.at(i, |ctx| v.validate_into(ctx));
618 }
619 }
620 fn kind() -> TypeKind {
621 TypeKind::Array
622 }
623 fn async_required(seen: &mut HashSet<&'static str>) -> bool {
624 T::async_required(seen)
625 }
626}
627impl<'de, T: BorrowType<'de>> BorrowType<'de> for BTreeMap<String, T> {
628 fn validate_rules(&self, rules: &Rules, ctx: &mut Context) {
629 rules.validate_length(self.len(), ctx)
630 }
631 fn prepare_default(self, ctx: &mut Context) -> Option<Self> {
632 let mut result = Self::new();
633 let mut complete = true;
634 for (k, v) in self {
635 match ctx.at(k.clone(), |ctx| v.prepare_default(ctx)) {
636 Some(v) => {
637 result.insert(k, v);
638 }
639 None => complete = false,
640 }
641 }
642 complete.then_some(result)
643 }
644 fn decode(value: Input<'de>, ctx: &mut Context, coerce: bool) -> Option<Self> {
645 let mut result = Self::new();
646 let mut complete = true;
647 for (k, v) in value.object(ctx)? {
648 match ctx.at(k.clone(), |ctx| T::decode(v, ctx, coerce)) {
649 Some(v) => {
650 result.insert(k, v);
651 }
652 None => complete = false,
653 }
654 }
655 complete.then_some(result)
656 }
657 fn encode(&self, ctx: &mut Context) -> Value {
658 Value::Object(
659 self.iter()
660 .map(|(k, v)| (k.clone(), ctx.at(k.clone(), |ctx| v.encode(ctx))))
661 .collect(),
662 )
663 }
664 fn encode_input(&self, ctx: &mut Context) -> Value {
665 Value::Object(
666 self.iter()
667 .map(|(k, v)| (k.clone(), ctx.at(k.clone(), |ctx| v.encode_input(ctx))))
668 .collect(),
669 )
670 }
671 fn schema(ctx: &mut SchemaContext, coerce: bool) -> Value {
672 json!({"type":"object","additionalProperties":T::schema(ctx,coerce)})
673 }
674 fn validate_into(&self, ctx: &mut Context) {
675 for (k, v) in self {
676 ctx.at(k.clone(), |ctx| v.validate_into(ctx));
677 }
678 }
679 fn kind() -> TypeKind {
680 TypeKind::Object
681 }
682 fn async_required(seen: &mut HashSet<&'static str>) -> bool {
683 T::async_required(seen)
684 }
685}
686impl<'de, T: BorrowType<'de>, S: BuildHasher + Default> BorrowType<'de> for HashMap<String, T, S> {
687 fn validate_rules(&self, rules: &Rules, ctx: &mut Context) {
688 rules.validate_length(self.len(), ctx)
689 }
690 fn prepare_default(self, ctx: &mut Context) -> Option<Self> {
691 <BTreeMap<String, T> as BorrowType>::prepare_default(self.into_iter().collect(), ctx)
692 .map(|v| v.into_iter().collect())
693 }
694 fn decode(value: Input<'de>, ctx: &mut Context, coerce: bool) -> Option<Self> {
695 <BTreeMap<String, T> as BorrowType>::decode(value, ctx, coerce)
696 .map(|v| v.into_iter().collect())
697 }
698 fn encode(&self, ctx: &mut Context) -> Value {
699 Value::Object(
700 self.iter()
701 .map(|(k, v)| (k.clone(), ctx.at(k.clone(), |ctx| v.encode(ctx))))
702 .collect(),
703 )
704 }
705 fn encode_input(&self, ctx: &mut Context) -> Value {
706 Value::Object(
707 self.iter()
708 .map(|(k, v)| (k.clone(), ctx.at(k.clone(), |ctx| v.encode_input(ctx))))
709 .collect(),
710 )
711 }
712 fn schema(ctx: &mut SchemaContext, coerce: bool) -> Value {
713 <BTreeMap<String, T> as BorrowType>::schema(ctx, coerce)
714 }
715 fn validate_into(&self, ctx: &mut Context) {
716 for (k, v) in self {
717 ctx.at(k.clone(), |ctx| v.validate_into(ctx));
718 }
719 }
720 fn kind() -> TypeKind {
721 TypeKind::Object
722 }
723 fn async_required(seen: &mut HashSet<&'static str>) -> bool {
724 T::async_required(seen)
725 }
726}
727
728owned!(Box<RawValue>);