Skip to main content

ruma_common/profile/
user_profile_update.rs

1//! An update to the profile information for a user.
2
3use std::collections::BTreeMap;
4
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use serde_json::Value as JsonValue;
7
8use super::{ProfileFieldName, ProfileFieldValue, StaticProfileField};
9
10/// An update to a user's profile.
11#[derive(Clone, Debug)]
12#[non_exhaustive]
13pub enum UserProfileUpdate {
14    /// The user's profile has been updated with the included changes.
15    Updated(UserProfileChanges),
16
17    /// This user no longer needs to be tracked as they have left all shared rooms.
18    Dropped,
19}
20
21impl<'d> Deserialize<'d> for UserProfileUpdate {
22    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
23    where
24        D: Deserializer<'d>,
25    {
26        Option::<UserProfileChanges>::deserialize(deserializer).map(|value| match value {
27            Some(changes) => Self::Updated(changes),
28            None => Self::Dropped,
29        })
30    }
31}
32
33impl Serialize for UserProfileUpdate {
34    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
35    where
36        S: Serializer,
37    {
38        match self {
39            Self::Updated(changes) => serializer.serialize_some(changes),
40            Self::Dropped => serializer.serialize_none(),
41        }
42    }
43}
44
45/// A collection of changes to be applied to a user's profile.
46///
47/// This type is not supposed to be used directly, but applied to an existing
48/// [`UserProfile`](super::UserProfile). If a profile doesn't exist, the changes should be applied
49/// to an empty one.
50#[derive(Clone, Debug, Default, Serialize, Deserialize)]
51#[non_exhaustive]
52pub struct UserProfileChanges {
53    /// Fields that have been newly set, or updated.
54    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
55    pub updated: BTreeMap<ProfileFieldName, JsonValue>,
56
57    /// Fields that have been removed from the profile.
58    #[serde(default, skip_serializing_if = "Vec::is_empty")]
59    pub removed: Vec<ProfileFieldName>,
60}
61
62impl UserProfileChanges {
63    /// Creates a new empty `UserProfileUpdate`.
64    pub fn new() -> Self {
65        Self::default()
66    }
67
68    /// Returns the updated value of the given [`StaticProfileField`].
69    ///
70    /// Returns `Ok(Some(_))` if an update to the field is included and the value was deserialized
71    /// successfully, `Ok(None)` if the field update is not included, or an error if deserialization
72    /// of the value failed.
73    pub fn get_updated_static<F: StaticProfileField>(
74        &self,
75    ) -> Result<Option<F::Value>, serde_json::Error> {
76        self.updated
77            .get(&ProfileFieldName::from(F::NAME))
78            .map(|value| serde_json::from_value(value.clone()))
79            .transpose()
80    }
81
82    /// Inserts an update for the supplied profile field value.
83    pub fn insert_updated_value(&mut self, value: ProfileFieldValue) {
84        self.updated.insert(value.field_name(), value.value().into_owned());
85    }
86}