poem_openapi/types/external/
vec.rs

1use 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}