poem_stackvec/
arrayvec.rs

1use std::{borrow::Cow, ops::Deref};
2use poem_openapi::{
3    registry::MetaSchemaRef,
4    types::{ParseError, ParseFromJSON, ParseFromParameter, ParseResult, Type},
5};
6use arrayvec::ArrayVec;
7
8use crate::util::fixed_capacity_schema_ref;
9
10/// `arrayvec::ArrayVec` wrapper that works in `poem_openapi` routes
11#[derive(Debug)]
12pub struct PoemArrayVec<T, const SIZE: usize>(pub ArrayVec<T, SIZE>);
13
14impl<T, const SIZE: usize> PoemArrayVec<T, SIZE> {
15    #[inline]
16    pub fn new() -> Self {
17        PoemArrayVec(ArrayVec::new())
18    }
19    #[inline]
20    pub fn as_slice(&self) -> &[T] {
21        self.0.as_slice()
22    }
23}
24
25impl<T, const SIZE: usize> Default for PoemArrayVec<T, SIZE> {
26    fn default() -> Self {
27        Self::new()
28    }
29}
30
31impl<T, const SIZE: usize> Deref for PoemArrayVec<T, SIZE> {
32    type Target = [T];
33    
34    #[inline]
35    fn deref(&self) -> &Self::Target {
36        self.0.as_slice()
37    }
38}
39
40impl<T: Type, const SIZE: usize> Type for PoemArrayVec<T, SIZE> {
41    const IS_REQUIRED: bool = <[T; SIZE]>::IS_REQUIRED;
42    type RawValueType = Self;
43    type RawElementValueType = T;
44
45    fn name() -> Cow<'static, str> {
46        <[T; SIZE]>::name()
47    }
48
49    fn schema_ref() -> MetaSchemaRef {
50        fixed_capacity_schema_ref::<T, SIZE>()
51    }
52
53    fn as_raw_value(&self) -> Option<&Self::RawValueType> {
54        Some(self)
55    }
56
57    fn raw_element_iter<'a>(
58        &'a self,
59    ) -> Box<dyn Iterator<Item = &'a Self::RawElementValueType> + 'a> {
60        Box::new(self.0.iter())
61    }
62}
63
64impl<T: ParseFromParameter, const SIZE: usize> ParseFromParameter for PoemArrayVec<T, SIZE> {
65    fn parse_from_parameter(value: &str) -> ParseResult<Self> {
66        let mut arr = ArrayVec::new();
67        parse_param(value, &mut arr)?;
68        Ok(PoemArrayVec(arr))
69    }
70
71    fn parse_from_parameters<I: IntoIterator<Item = A>, A: AsRef<str>>(
72        iter: I,
73    ) -> ParseResult<Self> {
74        let mut arr = ArrayVec::new();
75        for part in iter {
76            parse_param(part, &mut arr)?;
77        }
78        Ok(PoemArrayVec(arr))
79    }
80}
81
82fn parse_param<S: AsRef<str>, T: ParseFromParameter, const N: usize>(value: S, vec: &mut ArrayVec<T, N>) -> Result<(), ParseError<PoemArrayVec<T, N>>> {
83   let item = T::parse_from_parameter(value.as_ref())
84        .map_err(ParseError::propagate)?;
85    vec.try_push(item)
86        .map_err(|_| ParseError::custom(format!("too many items (max {N})")))?;
87    Ok(())
88}
89
90impl<T: ParseFromJSON, const SIZE: usize> ParseFromJSON for PoemArrayVec<T, SIZE> {
91    fn parse_from_json(value: Option<serde_json::Value>) -> ParseResult<Self> {
92        let value = value.unwrap_or_default();
93        match value {
94            serde_json::Value::Array(arr) => Ok(PoemArrayVec(
95                arr.into_iter()
96                    .map(|part| T::parse_from_json(Some(part)).map_err(ParseError::propagate))
97                    .collect::<Result<_, _>>()?,
98            )),
99            _ => Err(ParseError::expected_type(value)),
100        }
101    }
102}