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