poem_ext/
static_string.rs

1/// Construct an OpenApi type that always evaluates to a static string that is
2/// set at compile time.
3///
4/// #### Example
5/// ```
6/// use poem_ext::static_string;
7/// use poem_openapi::{types::ToJSON, Object};
8///
9/// static_string!(NotFoundError, "not found");
10///
11/// #[derive(Debug, Object)]
12/// struct NotFoundDetails {
13///     error: NotFoundError,
14///     foobar: i32,
15/// }
16///
17/// let response = NotFoundDetails {
18///     error: Default::default(),
19///     foobar: 42,
20/// };
21/// assert_eq!(
22///     response.to_json_string(),
23///     r#"{"error":"not found","foobar":42}"#
24/// );
25/// ```
26#[macro_export]
27macro_rules! static_string {
28    ($vis:vis $name:ident, $str:expr) => {
29        #[derive(::std::fmt::Debug)]
30        $vis struct $name;
31
32        impl ::std::default::Default for $name {
33            fn default() -> Self {
34                Self
35            }
36        }
37
38        impl ::poem_openapi::types::Type for $name {
39            const IS_REQUIRED: bool = true;
40
41            type RawValueType = &'static str;
42
43            type RawElementValueType = &'static str;
44
45            fn name() -> ::std::borrow::Cow<'static, str> {
46                ::std::stringify!($name).into()
47            }
48
49            fn schema_ref() -> ::poem_openapi::registry::MetaSchemaRef {
50                ::poem_openapi::registry::MetaSchemaRef::Inline(Box::new(
51                    ::poem_openapi::registry::MetaSchema {
52                        ty: "string",
53                        read_only: true,
54                        default: ::std::option::Option::Some($str.into()),
55                        ..::poem_openapi::registry::MetaSchema::ANY
56                    },
57                ))
58            }
59
60            fn as_raw_value(&self) -> ::std::option::Option<&Self::RawValueType> {
61                ::std::option::Option::Some(&$str)
62            }
63
64            fn raw_element_iter<'a>(
65                &'a self,
66            ) -> ::std::boxed::Box<dyn ::std::iter::Iterator<Item = &'a Self::RawElementValueType> + 'a> {
67                ::std::boxed::Box::new(self.as_raw_value().into_iter())
68            }
69        }
70
71        impl ::poem_openapi::types::ParseFromJSON for $name {
72            fn parse_from_json(
73                _value: ::std::option::Option<::poem_openapi::__private::serde_json::Value>,
74            ) -> ::poem_openapi::types::ParseResult<Self> {
75                ::std::panic!("Cannot parse static string")
76            }
77        }
78
79        impl ::poem_openapi::types::ToJSON for $name {
80            fn to_json(&self) -> ::std::option::Option<poem_openapi::__private::serde_json::Value> {
81                ::std::option::Option::Some(::poem_openapi::__private::serde_json::Value::String(
82                    $str.into(),
83                ))
84            }
85        }
86    };
87}