openapiv3/
util.rs

1use std::hash::Hash;
2use std::marker::PhantomData;
3
4use indexmap::IndexMap;
5use serde::{
6    de::{IgnoredAny, Visitor},
7    Deserialize, Deserializer,
8};
9
10#[allow(clippy::trivially_copy_pass_by_ref)] // needs to match signature for use in serde attribute
11#[inline]
12pub const fn is_false(v: &bool) -> bool {
13    !(*v)
14}
15
16pub(crate) fn deserialize_extensions<'de, D>(
17    deserializer: D,
18) -> Result<IndexMap<String, serde_json::Value>, D::Error>
19where
20    D: Deserializer<'de>,
21{
22    deserializer.deserialize_map(PredicateVisitor(
23        |key: &String| key.starts_with("x-"),
24        PhantomData,
25    ))
26}
27
28/// Used to deserialize IndexMap<K, V> that are flattened within other structs.
29/// This only adds keys that satisfy the given predicate.
30pub(crate) struct PredicateVisitor<F, K, V>(pub F, pub PhantomData<(K, V)>);
31
32impl<'de, F, K, V> Visitor<'de> for PredicateVisitor<F, K, V>
33where
34    F: Fn(&K) -> bool,
35    K: Deserialize<'de> + Eq + Hash,
36    V: Deserialize<'de>,
37{
38    type Value = IndexMap<K, V>;
39
40    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
41        formatter.write_str("a map whose fields obey a predicate")
42    }
43
44    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
45    where
46        A: serde::de::MapAccess<'de>,
47    {
48        let mut ret = Self::Value::default();
49
50        loop {
51            match map.next_key::<K>() {
52                Err(_) => (),
53                Ok(None) => break,
54                Ok(Some(key)) if self.0(&key) => {
55                    let _ = ret.insert(key, map.next_value()?);
56                }
57                Ok(Some(_)) => {
58                    let _ = map.next_value::<IgnoredAny>()?;
59                }
60            }
61        }
62
63        Ok(ret)
64    }
65}