poem_openapi/types/external/
floats.rs1use std::borrow::Cow;
2
3use poem::{http::HeaderValue, web::Field};
4use serde_json::{Number, Value};
5
6use crate::{
7 registry::{MetaSchema, MetaSchemaRef},
8 types::{
9 ParseError, ParseFromJSON, ParseFromMultipartField, ParseFromParameter, ParseResult,
10 ToHeader, ToJSON, Type,
11 },
12};
13
14macro_rules! impl_type_for_floats {
15 ($(($ty:ty, $format:literal)),*) => {
16 $(
17 impl Type for $ty {
18 const IS_REQUIRED: bool = true;
19
20 type RawValueType = Self;
21
22 type RawElementValueType = Self;
23
24 fn name() -> Cow<'static, str> {
25 format!("number_{}", $format).into()
26 }
27
28 fn schema_ref() -> MetaSchemaRef {
29 MetaSchemaRef::Inline(Box::new(MetaSchema::new_with_format("number", $format)))
30 }
31
32 fn as_raw_value(&self) -> Option<&Self::RawValueType> {
33 Some(self)
34 }
35
36 fn raw_element_iter<'a>(
37 &'a self
38 ) -> Box<dyn Iterator<Item = &'a Self::RawElementValueType> + 'a> {
39 Box::new(self.as_raw_value().into_iter())
40 }
41 }
42
43 impl ParseFromJSON for $ty {
44 fn parse_from_json(value: Option<Value>) -> ParseResult<Self> {
45 let value = value.unwrap_or_default();
46 if let Value::Number(n) = value {
47 let n = n
48 .as_f64()
49 .ok_or_else(|| ParseError::from("invalid number"))?;
50 Ok(n as Self)
51 } else {
52 Err(ParseError::expected_type(value))
53 }
54 }
55 }
56
57 impl ParseFromParameter for $ty {
58 fn parse_from_parameter(value: &str) -> ParseResult<Self> {
59 value.parse().map_err(ParseError::custom)
60 }
61 }
62
63 impl ParseFromMultipartField for $ty {
64 async fn parse_from_multipart(field: Option<Field>) -> ParseResult<Self> {
65 match field {
66 Some(field) => Ok(field.text().await?.parse()?),
67 None => Err(ParseError::expected_input()),
68 }
69 }
70 }
71
72 impl ToJSON for $ty {
73 fn to_json(&self) -> Option<Value> {
74 Number::from_f64(*self as f64).map(Value::Number)
75 }
76 }
77
78 impl ToHeader for $ty {
79 fn to_header(&self) -> Option<HeaderValue> {
80 match HeaderValue::from_str(&format!("{}", self)) {
81 Ok(value) => Some(value),
82 Err(_) => None,
83 }
84 }
85 }
86
87 )*
88 };
89}
90
91impl_type_for_floats!((f32, "float"), (f64, "double"));