Skip to main content

kynos_openapi/model/
callback.rs

1//! The Callback Object.
2
3use std::fmt;
4
5use serde::{
6    Deserialize, Deserializer, Serialize, Serializer,
7    de::{MapAccess, Visitor},
8    ser::SerializeMap,
9};
10
11use crate::{
12    Map,
13    model::{extensions::Extensions, paths::item::PathItem, reference::RefOr},
14};
15
16/// Out-of-band requests the API makes as part of an operation.
17///
18/// Keys are runtime expressions identifying the URL to call, such as
19/// `{$request.body#/callbackUrl}`. Each maps to the operations the API will
20/// perform against that URL.
21///
22/// Extensions sit beside those keys, so this is not a bare map — see
23/// [`Paths`](crate::Paths), which has the same shape for the same reason.
24#[derive(Clone, Debug, Default, PartialEq)]
25pub struct Callback {
26    /// The Path Items, keyed by runtime expression.
27    pub items: Map<RefOr<PathItem>>,
28
29    /// Specification extensions.
30    pub extensions: Extensions,
31}
32
33impl Callback {
34    /// Creates an empty callback map.
35    #[must_use]
36    pub fn new() -> Self {
37        Self::default()
38    }
39
40    /// Declares the operations performed against the URL named by `expression`.
41    #[must_use]
42    pub fn with(mut self, expression: impl Into<String>, path_item: PathItem) -> Self {
43        self.items.insert(expression.into(), RefOr::Item(path_item));
44        self
45    }
46
47    /// Returns `true` when nothing at all is declared.
48    #[must_use]
49    pub fn is_empty(&self) -> bool {
50        self.items.is_empty() && self.extensions.is_empty()
51    }
52}
53
54impl Serialize for Callback {
55    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
56        let mut map = serializer.serialize_map(Some(self.items.len() + self.extensions.0.len()))?;
57        for (expression, item) in &self.items {
58            map.serialize_entry(expression, item)?;
59        }
60        for (key, value) in &self.extensions.0 {
61            map.serialize_entry(key, value)?;
62        }
63        map.end()
64    }
65}
66
67impl<'de> Deserialize<'de> for Callback {
68    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
69        struct CallbackVisitor;
70
71        impl<'de> Visitor<'de> for CallbackVisitor {
72            type Value = Callback;
73
74            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75                f.write_str("a map of runtime expressions to path items")
76            }
77
78            fn visit_map<A: MapAccess<'de>>(self, mut access: A) -> Result<Callback, A::Error> {
79                let mut callback = Callback::new();
80                while let Some(key) = access.next_key::<String>()? {
81                    if key.starts_with(crate::model::extensions::EXTENSION_PREFIX) {
82                        callback.extensions.0.insert(key, access.next_value()?);
83                    } else {
84                        callback.items.insert(key, access.next_value()?);
85                    }
86                }
87                Ok(callback)
88            }
89        }
90
91        deserializer.deserialize_map(CallbackVisitor)
92    }
93}