ruma_client_api/profile/
profile_field_serde.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize, Serializer, de, ser::SerializeMap};
4
5use super::{CustomProfileFieldValue, ProfileFieldName, ProfileFieldValue};
6
7/// Helper type to deserialize any type that implements [`StaticProfileField`].
8#[cfg(feature = "client")]
9pub(super) struct StaticProfileFieldVisitor<F: super::StaticProfileField>(
10    pub(super) std::marker::PhantomData<F>,
11);
12
13#[cfg(feature = "client")]
14impl<'de, F: super::StaticProfileField> de::Visitor<'de> for StaticProfileFieldVisitor<F> {
15    type Value = Option<F::Value>;
16
17    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
18        write!(formatter, "a map with optional key `{}` and value", F::NAME)
19    }
20
21    fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
22    where
23        V: de::MapAccess<'de>,
24    {
25        use std::borrow::Cow;
26
27        let mut found = false;
28
29        while let Some(key) = map.next_key::<Cow<'_, str>>()? {
30            if key == F::NAME {
31                found = true;
32                break;
33            }
34        }
35
36        if !found {
37            return Ok(None);
38        }
39
40        Ok(Some(map.next_value()?))
41    }
42}
43
44impl Serialize for CustomProfileFieldValue {
45    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
46    where
47        S: Serializer,
48    {
49        let mut map = serializer.serialize_map(Some(1))?;
50        map.serialize_entry(&self.field, &self.value)?;
51        map.end()
52    }
53}
54
55/// Helper type to deserialize [`ProfileFieldValue`].
56///
57/// If the inner value is set, this will try to deserialize a map entry using this key, otherwise
58/// this will deserialize the first key-value pair encountered.
59pub(super) struct ProfileFieldValueVisitor(pub(super) Option<ProfileFieldName>);
60
61impl<'de> de::Visitor<'de> for ProfileFieldValueVisitor {
62    type Value = Option<ProfileFieldValue>;
63
64    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
65        formatter.write_str("enum ProfileFieldValue")
66    }
67
68    fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
69    where
70        V: de::MapAccess<'de>,
71    {
72        let field = if let Some(field) = self.0 {
73            let mut found = false;
74
75            while let Some(key) = map.next_key::<ProfileFieldName>()? {
76                if key == field {
77                    found = true;
78                    break;
79                }
80            }
81
82            if !found {
83                return Ok(None);
84            }
85
86            field
87        } else {
88            let Some(field) = map.next_key()? else {
89                return Ok(None);
90            };
91
92            field
93        };
94
95        Ok(Some(match field {
96            ProfileFieldName::AvatarUrl => ProfileFieldValue::AvatarUrl(map.next_value()?),
97            ProfileFieldName::DisplayName => ProfileFieldValue::DisplayName(map.next_value()?),
98            ProfileFieldName::TimeZone => ProfileFieldValue::TimeZone(map.next_value()?),
99            ProfileFieldName::_Custom(field) => {
100                ProfileFieldValue::_Custom(CustomProfileFieldValue {
101                    field: field.0.into(),
102                    value: map.next_value()?,
103                })
104            }
105        }))
106    }
107}
108
109pub(super) fn deserialize_profile_field_value_option<'de, D>(
110    deserializer: D,
111) -> Result<Option<ProfileFieldValue>, D::Error>
112where
113    D: de::Deserializer<'de>,
114{
115    deserializer.deserialize_map(ProfileFieldValueVisitor(None))
116}
117
118impl<'de> Deserialize<'de> for ProfileFieldValue {
119    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
120    where
121        D: de::Deserializer<'de>,
122    {
123        deserialize_profile_field_value_option(deserializer)?
124            .ok_or_else(|| de::Error::invalid_length(0, &"at least one key-value pair"))
125    }
126}