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