poem_openapi/types/external/
array.rs1use std::borrow::Cow;
2
3use serde_json::Value;
4
5use crate::{
6 registry::{MetaSchema, MetaSchemaRef, Registry},
7 types::{ParseError, ParseFromJSON, ParseFromParameter, ParseResult, ToJSON, Type},
8};
9
10impl<T: Type, const LEN: usize> Type for [T; LEN] {
11 const IS_REQUIRED: bool = true;
12
13 type RawValueType = Self;
14
15 type RawElementValueType = T::RawValueType;
16
17 fn name() -> Cow<'static, str> {
18 format!("array_{}", T::name()).into()
19 }
20
21 fn schema_ref() -> MetaSchemaRef {
22 MetaSchemaRef::Inline(Box::new(MetaSchema {
23 items: Some(Box::new(T::schema_ref())),
24 max_length: Some(LEN),
25 min_length: Some(LEN),
26 ..MetaSchema::new("array")
27 }))
28 }
29
30 fn register(registry: &mut Registry) {
31 T::register(registry);
32 }
33
34 fn as_raw_value(&self) -> Option<&Self::RawValueType> {
35 Some(self)
36 }
37
38 fn raw_element_iter<'a>(
39 &'a self,
40 ) -> Box<dyn Iterator<Item = &'a Self::RawElementValueType> + 'a> {
41 Box::new(self.iter().filter_map(|item| item.as_raw_value()))
42 }
43}
44
45impl<T: ParseFromJSON, const LEN: usize> ParseFromJSON for [T; LEN] {
46 fn parse_from_json(value: Option<Value>) -> ParseResult<Self> {
47 let value = value.unwrap_or_default();
48 match value {
49 Value::Array(values) => {
50 if values.len() != LEN {
51 return Err(ParseError::custom(format!(
52 "the length of the list must be `{LEN}`."
53 )));
54 }
55
56 let mut res = Vec::with_capacity(values.len());
57 for value in values {
58 res.push(T::parse_from_json(Some(value)).map_err(ParseError::propagate)?);
59 }
60
61 Ok(res.try_into().ok().unwrap())
62 }
63 _ => Err(ParseError::expected_type(value)),
64 }
65 }
66}
67
68impl<T: ParseFromParameter, const LEN: usize> ParseFromParameter for [T; LEN] {
69 fn parse_from_parameter(_value: &str) -> ParseResult<Self> {
70 unreachable!()
71 }
72
73 fn parse_from_parameters<I: IntoIterator<Item = A>, A: AsRef<str>>(
74 iter: I,
75 ) -> ParseResult<Self> {
76 let mut values = Vec::new();
77
78 for s in iter {
79 values.push(
80 T::parse_from_parameters(std::iter::once(s.as_ref()))
81 .map_err(ParseError::propagate)?,
82 );
83 }
84
85 if values.len() != LEN {
86 return Err(ParseError::custom(format!(
87 "the length of the list must be `{LEN}`."
88 )));
89 }
90
91 Ok(values.try_into().ok().unwrap())
92 }
93}
94
95impl<T: ToJSON, const LEN: usize> ToJSON for [T; LEN] {
96 fn to_json(&self) -> Option<Value> {
97 let mut values = Vec::with_capacity(self.len());
98 for item in self {
99 if let Some(value) = item.to_json() {
100 values.push(value);
101 }
102 }
103 Some(Value::Array(values))
104 }
105}