poem_openapi/types/external/
optional.rs1use std::borrow::Cow;
2
3use poem::{http::HeaderValue, web::Field as PoemField};
4use serde_json::Value;
5
6use crate::{
7 registry::{MetaSchemaRef, Registry},
8 types::{
9 ParseError, ParseFromJSON, ParseFromMultipartField, ParseFromParameter, ParseResult,
10 ToHeader, ToJSON, Type,
11 },
12};
13
14impl<T: Type> Type for Option<T> {
15 const IS_REQUIRED: bool = false;
16
17 type RawValueType = T::RawValueType;
18
19 type RawElementValueType = T::RawElementValueType;
20
21 fn name() -> Cow<'static, str> {
22 format!("optional_{}", T::name()).into()
23 }
24
25 fn schema_ref() -> MetaSchemaRef {
26 T::schema_ref()
27 }
28
29 fn register(registry: &mut Registry) {
30 T::register(registry);
31 }
32
33 fn as_raw_value(&self) -> Option<&Self::RawValueType> {
34 match self {
35 Some(value) => value.as_raw_value(),
36 None => None,
37 }
38 }
39
40 fn raw_element_iter<'a>(
41 &'a self,
42 ) -> Box<dyn Iterator<Item = &'a Self::RawElementValueType> + 'a> {
43 match self {
44 Some(value) => value.raw_element_iter(),
45 None => Box::new(std::iter::empty()),
46 }
47 }
48
49 #[inline]
50 fn is_none(&self) -> bool {
51 <Option<T>>::is_none(self)
52 }
53}
54
55impl<T: ParseFromJSON> ParseFromJSON for Option<T> {
56 fn parse_from_json(value: Option<Value>) -> ParseResult<Self> {
57 match value.unwrap_or_default() {
58 Value::Null => Ok(None),
59 value => Ok(Some(
60 T::parse_from_json(Some(value)).map_err(ParseError::propagate)?,
61 )),
62 }
63 }
64}
65
66impl<T: ParseFromParameter> ParseFromParameter for Option<T> {
67 fn parse_from_parameter(_value: &str) -> ParseResult<Self> {
68 unreachable!()
69 }
70
71 fn parse_from_parameters<I: IntoIterator<Item = A>, A: AsRef<str>>(
72 iter: I,
73 ) -> ParseResult<Self> {
74 let mut iter = iter.into_iter().peekable();
75
76 if iter.peek().is_none() {
77 return Ok(None);
78 }
79
80 T::parse_from_parameters(iter)
81 .map_err(ParseError::propagate)
82 .map(Some)
83 }
84}
85
86impl<T: ParseFromMultipartField> ParseFromMultipartField for Option<T> {
87 async fn parse_from_multipart(value: Option<PoemField>) -> ParseResult<Self> {
88 match value {
89 Some(value) => T::parse_from_multipart(Some(value))
90 .await
91 .map_err(ParseError::propagate)
92 .map(Some),
93 None => Ok(None),
94 }
95 }
96}
97
98impl<T: ToJSON> ToJSON for Option<T> {
99 fn to_json(&self) -> Option<Value> {
100 match self {
101 Some(value) => value.to_json(),
102 None => Some(Value::Null),
103 }
104 }
105}
106
107impl<T: ToHeader> ToHeader for Option<T> {
108 fn to_header(&self) -> Option<HeaderValue> {
109 match self {
110 Some(value) => value.to_header(),
111 None => None,
112 }
113 }
114}