poem_openapi/types/external/
humantime.rs

1use std::{borrow::Cow, time::Duration};
2
3use poem::{http::HeaderValue, web::Field};
4use serde_json::Value;
5
6use crate::{
7    registry::{MetaSchema, MetaSchemaRef},
8    types::{
9        ParseError, ParseFromJSON, ParseFromMultipartField, ParseFromParameter, ParseResult,
10        ToHeader, ToJSON, Type,
11    },
12};
13
14impl Type for Duration {
15    const IS_REQUIRED: bool = true;
16
17    type RawValueType = Self;
18
19    type RawElementValueType = Self;
20
21    fn name() -> Cow<'static, str> {
22        "string_duration".into()
23    }
24
25    fn schema_ref() -> MetaSchemaRef {
26        MetaSchemaRef::Inline(Box::new(MetaSchema::new_with_format("string", "duration")))
27    }
28
29    fn as_raw_value(&self) -> Option<&Self::RawValueType> {
30        Some(self)
31    }
32
33    fn raw_element_iter<'a>(
34        &'a self,
35    ) -> Box<dyn Iterator<Item = &'a Self::RawElementValueType> + 'a> {
36        Box::new(self.as_raw_value().into_iter())
37    }
38}
39
40impl ParseFromJSON for Duration {
41    fn parse_from_json(value: Option<Value>) -> ParseResult<Self> {
42        let value = value.unwrap_or_default();
43        if let Value::String(value) = value {
44            Ok(humantime::parse_duration(&value)?)
45        } else {
46            Err(ParseError::expected_type(value))
47        }
48    }
49}
50
51impl ParseFromParameter for Duration {
52    fn parse_from_parameter(value: &str) -> ParseResult<Self> {
53        humantime::parse_duration(value).map_err(ParseError::custom)
54    }
55}
56
57impl ParseFromMultipartField for Duration {
58    async fn parse_from_multipart(field: Option<Field>) -> ParseResult<Self> {
59        match field {
60            Some(field) => Ok(humantime::parse_duration(&field.text().await?)?),
61            None => Err(ParseError::expected_input()),
62        }
63    }
64}
65
66impl ToJSON for Duration {
67    fn to_json(&self) -> Option<Value> {
68        Some(Value::String(humantime::format_duration(*self).to_string()))
69    }
70}
71
72impl ToHeader for Duration {
73    fn to_header(&self) -> Option<HeaderValue> {
74        HeaderValue::from_str(&humantime::format_duration(*self).to_string()).ok()
75    }
76}