poem_openapi/types/external/
vec.rs1use std::borrow::Cow;
2
3use poem::web::Field as PoemField;
4use serde_json::Value;
5
6use crate::{
7 registry::{MetaSchema, MetaSchemaRef, Registry},
8 types::{
9 ParseError, ParseFromJSON, ParseFromMultipartField, ParseFromParameter, ParseResult,
10 ToJSON, Type,
11 },
12};
13
14impl<T: Type> Type for Vec<T> {
15 const IS_REQUIRED: bool = true;
16
17 type RawValueType = Self;
18
19 type RawElementValueType = T::RawValueType;
20
21 fn name() -> Cow<'static, str> {
22 format!("list_{}", T::name()).into()
23 }
24
25 fn schema_ref() -> MetaSchemaRef {
26 MetaSchemaRef::Inline(Box::new(MetaSchema {
27 items: Some(Box::new(T::schema_ref())),
28 ..MetaSchema::new("array")
29 }))
30 }
31
32 fn register(registry: &mut Registry) {
33 T::register(registry);
34 }
35
36 fn as_raw_value(&self) -> Option<&Self::RawValueType> {
37 Some(self)
38 }
39
40 fn raw_element_iter<'a>(
41 &'a self,
42 ) -> Box<dyn Iterator<Item = &'a Self::RawElementValueType> + 'a> {
43 Box::new(self.iter().filter_map(|item| item.as_raw_value()))
44 }
45
46 fn is_empty(&self) -> bool {
47 <Vec<T>>::is_empty(self)
48 }
49}
50
51impl<T: ParseFromJSON> ParseFromJSON for Vec<T> {
52 fn parse_from_json(value: Option<Value>) -> ParseResult<Self> {
53 let value = value.unwrap_or_default();
54 match value {
55 Value::Array(values) => {
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 Ok(res)
61 }
62 _ => Err(ParseError::expected_type(value)),
63 }
64 }
65}
66
67impl<T: ParseFromParameter> ParseFromParameter for Vec<T> {
68 fn parse_from_parameter(_value: &str) -> ParseResult<Self> {
69 unreachable!()
70 }
71
72 fn parse_from_parameters<I: IntoIterator<Item = A>, A: AsRef<str>>(
73 iter: I,
74 ) -> ParseResult<Self> {
75 let mut values = Vec::new();
76 for s in iter {
77 values.push(
78 T::parse_from_parameters(std::iter::once(s.as_ref()))
79 .map_err(ParseError::propagate)?,
80 );
81 }
82 Ok(values)
83 }
84}
85
86impl<T: ParseFromMultipartField> ParseFromMultipartField for Vec<T> {
87 async fn parse_from_multipart(field: Option<PoemField>) -> ParseResult<Self> {
88 match field {
89 Some(field) => {
90 let item = T::parse_from_multipart(Some(field))
91 .await
92 .map_err(ParseError::propagate)?;
93 Ok(vec![item])
94 }
95 None => Ok(Vec::new()),
96 }
97 }
98
99 async fn parse_from_repeated_field(mut self, field: PoemField) -> ParseResult<Self> {
100 let item = T::parse_from_multipart(Some(field))
101 .await
102 .map_err(ParseError::propagate)?;
103 self.push(item);
104 Ok(self)
105 }
106}
107
108impl<T: ToJSON> ToJSON for Vec<T> {
109 fn to_json(&self) -> Option<Value> {
110 let mut values = Vec::with_capacity(self.len());
111 for item in self {
112 if let Some(value) = item.to_json() {
113 values.push(value);
114 }
115 }
116 Some(Value::Array(values))
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn parse_from_parameters() {
126 let values = Vec::<i32>::parse_from_parameters(vec!["100", "200", "300"]).unwrap();
127 assert_eq!(values, vec![100, 200, 300]);
128 }
129}