poem_stackvec/
lib.rs

1#[cfg(feature = "smallvec")]
2pub mod smallvec;
3#[cfg(feature = "smallvec")]
4pub use smallvec::PoemSmallVec;
5
6#[cfg(feature = "arrayvec")]
7pub mod arrayvec;
8#[cfg(feature = "arrayvec")]
9pub use arrayvec::PoemArrayVec;
10
11#[cfg(feature = "heapless")]
12pub mod heapless;
13#[cfg(feature = "heapless")]
14pub use heapless::PoemHeaplessVec;
15
16pub(crate) mod util;
17
18#[cfg(test)]
19mod tests {
20    use poem_openapi::{registry::MetaSchemaRef, types::Type};
21
22    pub(crate) fn check_openapi_props<T: Type, const MAX: usize>() 
23        where <T as Type>::RawElementValueType: Type
24    {
25        match T::schema_ref() {
26            MetaSchemaRef::Inline(box_meta) => {
27                assert_eq!(box_meta.nullable, false);
28                assert_eq!(box_meta.min_items, Some(1));
29                assert_eq!(box_meta.max_items, Some(MAX));
30                // (min/max)-length is supposed to be for strings, but poem uses it for arrays too?
31                assert_eq!(box_meta.min_length, Some(1));
32                assert_eq!(box_meta.max_length, Some(MAX));
33                assert_eq!(box_meta.title, Some(format!("1 to {MAX} items of type {}", <T as Type>::RawElementValueType::name())));
34            },
35            MetaSchemaRef::Reference(s) => {
36                panic!("expected Inline schema, got Reference: {s}");
37            },
38        }
39    }
40
41    // Group tests for PoemSmallVec
42    #[cfg(feature = "smallvec")]
43    mod smallvec_tests {
44        use crate::PoemSmallVec;
45        use poem_openapi::{registry::MetaSchemaRef, types::{ParseFromParameter, ParseFromJSON, Type}};
46        use serde_json::json;
47
48        #[test]
49        fn specifies_correct_openapi_props() {
50            match PoemSmallVec::<u32, 4>::schema_ref() {
51                MetaSchemaRef::Inline(box_meta) => {
52                    assert_eq!(box_meta.nullable, false);
53                    assert_eq!(box_meta.min_items, Some(1));
54                    assert_eq!(box_meta.max_items, None);
55                    assert_eq!(box_meta.min_length, Some(1));
56                    assert_eq!(box_meta.max_length, None);
57                    assert_eq!(box_meta.title, Some(format!("at least 1 item of type {}", <PoemSmallVec::<u32, 4> as Type>::RawElementValueType::name())));
58                },
59                MetaSchemaRef::Reference(s) => {
60                    panic!("expected Inline schema, got Reference: {s}");
61                },
62            }
63        }
64
65        #[test]
66        fn parse_single_element() {
67            let vec = PoemSmallVec::<i32, 4>::parse_from_parameter("42")
68                .expect("should parse single element");
69            assert_eq!(vec.as_slice(), &[42]);
70        }
71
72        #[test]
73        fn parse_multiple_elements() {
74            let input = vec!["1", "2", "3"];
75            let vec = PoemSmallVec::<i32, 4>::parse_from_parameters(input)
76                .expect("should parse multiple elements");
77            assert_eq!(vec.as_slice(), &[1, 2, 3]);
78        }
79
80        #[test]
81        fn parse_invalid_single() {
82            assert!(PoemSmallVec::<i32, 4>::parse_from_parameter("not_a_number").is_err());
83        }
84
85        #[test]
86        fn parse_invalid_multiple() {
87            let input = vec!["10", "xx", "30"];
88            assert!(PoemSmallVec::<i32, 4>::parse_from_parameters(input).is_err());
89        }
90
91        #[test]
92        fn parse_json_valid_array() {
93            let value = json!([1, 2, 3]);
94            let vec = PoemSmallVec::<i32, 4>::parse_from_json(Some(value))
95                .expect("should parse valid JSON array");
96            assert_eq!(vec.as_slice(), &[1, 2, 3]);
97        }
98
99        #[test]
100        fn parse_json_invalid_type() {
101            let value = json!({"not": "an array"});
102            assert!(PoemSmallVec::<i32, 4>::parse_from_json(Some(value)).is_err());
103        }
104    }
105
106    // Group tests for PoemArrayVec
107    #[cfg(feature = "arrayvec")]
108    mod arrayvec_tests {
109        use crate::PoemArrayVec;
110        use poem_openapi::types::{ParseFromJSON, ParseFromParameter};
111        use serde_json::json;
112
113        #[test]
114        fn specifies_correct_openapi_props() {
115            super::check_openapi_props::<PoemArrayVec<u16, 8>, 8>();
116        }
117
118        #[test]
119        fn parse_array_single_element() {
120            let vec = PoemArrayVec::<i32, 4>::parse_from_parameter("42")
121                .expect("should parse single element");
122            assert_eq!(vec.as_slice(), &[42]);
123        }
124
125        #[test]
126        fn parse_array_multiple_elements() {
127            let input = vec!["1", "2", "3"];
128            let vec = PoemArrayVec::<i32, 4>::parse_from_parameters(input)
129                .expect("should parse multiple elements");
130            assert_eq!(vec.as_slice(), &[1, 2, 3]);
131        }
132
133        #[test]
134        fn parse_invalid_array_single() {
135            assert!(PoemArrayVec::<i32, 4>::parse_from_parameter("not_a_number").is_err());
136        }
137
138        #[test]
139        fn parse_invalid_array_multiple() {
140            let input = vec!["10", "xx", "30"];
141            assert!(PoemArrayVec::<i32, 4>::parse_from_parameters(input).is_err());
142        }
143
144        #[test]
145        fn parse_json_valid_array() {
146            let value = json!([1, 2, 3]);
147            let vec = PoemArrayVec::<i32, 4>::parse_from_json(Some(value))
148                .expect("should parse valid JSON array");
149            assert_eq!(vec.as_slice(), &[1, 2, 3]);
150        }
151
152        #[test]
153        fn parse_json_invalid_type() {
154            let value = json!({"not": "an array"});
155            assert!(PoemArrayVec::<i32, 4>::parse_from_json(Some(value)).is_err());
156        }
157    }
158
159    // Group tests for PoemHeaplessVec
160    #[cfg(feature = "heapless")]
161    mod heapless_tests {
162        use crate::PoemHeaplessVec;
163        use poem_openapi::types::{ParseFromParameter, ParseFromJSON};
164        use serde_json::json;
165
166        #[test]
167        fn specifies_correct_openapi_props() {
168            super::check_openapi_props::<PoemHeaplessVec<u64, 2>, 2>();
169        }
170
171        #[test]
172        fn parse_heapless_single_element() {
173            let vec = PoemHeaplessVec::<i32, 4>::parse_from_parameter("42")
174                .expect("should parse single element");
175            assert_eq!(vec.as_slice(), &[42]);
176        }
177
178        #[test]
179        fn parse_heapless_multiple_elements() {
180            let input = vec!["1", "2", "3"];
181            let vec = PoemHeaplessVec::<i32, 4>::parse_from_parameters(input)
182                .expect("should parse multiple elements");
183            assert_eq!(vec.as_slice(), &[1, 2, 3]);
184        }
185
186        #[test]
187        fn parse_heapless_invalid_single() {
188            assert!(PoemHeaplessVec::<i32, 4>::parse_from_parameter("not_a_number").is_err());
189        }
190
191        #[test]
192        fn parse_heapless_invalid_multiple() {
193            let input = vec!["10", "xx", "30"];
194            assert!(PoemHeaplessVec::<i32, 4>::parse_from_parameters(input).is_err());
195        }
196
197        #[test]
198        fn parse_json_valid_array() {
199            let value = json!([1, 2, 3]);
200            let vec = PoemHeaplessVec::<i32, 4>::parse_from_json(Some(value))
201                .expect("should parse valid JSON array");
202            assert_eq!(vec.as_slice(), &[1, 2, 3]);
203        }
204
205        #[test]
206        fn parse_json_invalid_type() {
207            let value = json!({"not": "an array"});
208            assert!(PoemHeaplessVec::<i32, 4>::parse_from_json(Some(value)).is_err());
209        }
210    }
211}