Skip to content

Commit

Permalink
Make EditRole::icon and EditRole::unicode_emoji nullable in addit…
Browse files Browse the repository at this point in the history
…ion to undefined (serenity-rs#2539)

All `EditRole` fields are skipped when they are `None`. This does not work for `EditRole::icon` and `EditRole::unicode_emoji` because the field being `undefined` is different from the field being `null` at the API: if the field is `undefined` it will be kept unchanged, and if it is `null` it will be cleared.

With a double `Option` it is possible to distinguish `undefined` from `null` from a set value. This is the [canonical](serde-rs/serde#984 (comment)) solution using serde (the example shows de-serialization but it works the same in reverse).

Then, `None` is "keep field unchanged", `Some(None)` is "clear this field" and `Some(Some(value)` is "set this field to this value"

# Breaking changes

- `EditRole::unicode_emoji()` takes a `Option<String>` instead of `impl Into<String>`.
- `EditRole::icon()` takes a `Option<&CreateAttachment>` instead of `&CreateAttachment`
  • Loading branch information
Sergiovan authored and mkrasnitski committed Oct 24, 2023
1 parent 1622542 commit f79afd0
Showing 1 changed file with 10 additions and 9 deletions.
19 changes: 10 additions & 9 deletions src/builder/edit_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ pub struct EditRole<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
hoist: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
icon: Option<String>,
icon: Option<Option<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
unicode_emoji: Option<String>,
unicode_emoji: Option<Option<String>>,

#[serde(skip_serializing_if = "Option::is_none")]
mentionable: Option<bool>,

Expand All @@ -83,7 +84,7 @@ impl<'a> EditRole<'a> {
permissions: Some(role.permissions.bits()),
position: Some(role.position),
colour: Some(role.colour),
unicode_emoji: role.unicode_emoji.clone(),
unicode_emoji: role.unicode_emoji.as_ref().map(|v| Some(v.clone())),
audit_log_reason: None,
// TODO: Do we want to download role.icon?
icon: None,
Expand Down Expand Up @@ -129,16 +130,16 @@ impl<'a> EditRole<'a> {
}

/// Set the role icon to a unicode emoji.
pub fn unicode_emoji(mut self, unicode_emoji: impl Into<String>) -> Self {
self.unicode_emoji = Some(unicode_emoji.into());
self.icon = None;
pub fn unicode_emoji(mut self, unicode_emoji: Option<String>) -> Self {
self.unicode_emoji = Some(unicode_emoji);
self.icon = Some(None);
self
}

/// Set the role icon to a custom image.
pub fn icon(mut self, icon: &CreateAttachment) -> Self {
self.icon = Some(icon.to_base64());
self.unicode_emoji = None;
pub fn icon(mut self, icon: Option<&CreateAttachment>) -> Self {
self.icon = Some(icon.map(CreateAttachment::to_base64));
self.unicode_emoji = Some(None);
self
}

Expand Down

0 comments on commit f79afd0

Please sign in to comment.