Skip to content

Commit

Permalink
Update to small-fixed-array v0.2 (serenity-rs#2711)
Browse files Browse the repository at this point in the history
`small-fixed-array` v0.2 removes implicit truncation and makes all
truncations explicit.

I also changed FixedString initialization from literals to use
`from_str_trunc` to take advantage of SSO if possible.
  • Loading branch information
GnomedDev committed Apr 1, 2024
1 parent 656cf3b commit 3eaf191
Show file tree
Hide file tree
Showing 21 changed files with 94 additions and 80 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ base64 = { version = "0.22.0" }
secrecy = { version = "0.8.0", features = ["serde"] }
arrayvec = { version = "0.7.4", features = ["serde"] }
serde_cow = { version = "0.1.0" }
small-fixed-array = { version = "0.1.1", features = ["serde", "log_using_tracing"] }
small-fixed-array = { version = "0.2", features = ["serde"] }
bool_to_bitflags = { version = "0.1.0" }
nonmax = { version = "0.5.5", features = ["serde"] }
# Optional dependencies
Expand Down
12 changes: 9 additions & 3 deletions src/cache/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,9 @@ impl CacheUpdate for ThreadCreateEvent {
// This is a rare enough occurence to realloc.
let mut threads = std::mem::take(&mut g.threads).into_vec();
threads.push(self.thread.clone());
g.threads = threads.into();

g.threads = FixedArray::try_from(threads.into_boxed_slice())
.expect("A guild should not have 4 billion threads");

None
}
Expand All @@ -529,7 +531,9 @@ impl CacheUpdate for ThreadUpdateEvent {
// This is a rare enough occurence to realloc.
let mut threads = std::mem::take(&mut g.threads).into_vec();
threads.push(self.thread.clone());
g.threads = threads.into();

g.threads = FixedArray::try_from(threads.into_boxed_slice())
.expect("A guild should not have 4 billion threads");

None
}
Expand All @@ -547,7 +551,9 @@ impl CacheUpdate for ThreadDeleteEvent {
g.threads.iter().position(|e| e.id == thread_id).map(|i| {
let mut threads = std::mem::take(&mut g.threads).into_vec();
let thread = threads.remove(i);
g.threads = threads.into();

g.threads = FixedArray::try_from(threads.into_boxed_slice())
.expect("A guild should not have 4 billion threads");

thread
})
Expand Down
14 changes: 7 additions & 7 deletions src/gateway/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl ActivityData {
#[must_use]
pub fn playing(name: impl Into<String>) -> Self {
Self {
name: name.into().into(),
name: name.into().trunc_into(),
kind: ActivityType::Playing,
state: None,
url: None,
Expand All @@ -103,7 +103,7 @@ impl ActivityData {
#[cfg(feature = "http")]
pub fn streaming(name: impl Into<String>, url: impl IntoUrl) -> Result<Self> {
Ok(Self {
name: name.into().into(),
name: name.into().trunc_into(),
kind: ActivityType::Streaming,
state: None,
url: Some(url.into_url()?),
Expand All @@ -114,7 +114,7 @@ impl ActivityData {
#[must_use]
pub fn listening(name: impl Into<String>) -> Self {
Self {
name: name.into().into(),
name: name.into().trunc_into(),
kind: ActivityType::Listening,
state: None,
url: None,
Expand All @@ -125,7 +125,7 @@ impl ActivityData {
#[must_use]
pub fn watching(name: impl Into<String>) -> Self {
Self {
name: name.into().into(),
name: name.into().trunc_into(),
kind: ActivityType::Watching,
state: None,
url: None,
Expand All @@ -136,7 +136,7 @@ impl ActivityData {
#[must_use]
pub fn competing(name: impl Into<String>) -> Self {
Self {
name: name.into().into(),
name: name.into().trunc_into(),
kind: ActivityType::Competing,
state: None,
url: None,
Expand All @@ -149,9 +149,9 @@ impl ActivityData {
Self {
// discord seems to require a name for custom activities
// even though it's not displayed
name: "~".to_string().into(),
name: FixedString::from_str_trunc("~"),
kind: ActivityType::Custom,
state: Some(state.into().into()),
state: Some(state.into().trunc_into()),
url: None,
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/http/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,23 @@ pub struct DiscordJsonSingleError {
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub struct ErrorResponse {
pub method: Method,
pub status_code: StatusCode,
pub url: FixedString<u16>,
pub method: Method,
pub error: DiscordJsonError,
}

impl ErrorResponse {
// We need a freestanding from-function since we cannot implement an async From-trait.
pub async fn from_response(r: Response, method: Method) -> Self {
ErrorResponse {
status_code: r.status(),
url: r.url().to_string().into(),
method,
status_code: r.status(),
url: FixedString::from_str_trunc(r.url().as_str()),
error: decode_resp(r).await.unwrap_or_else(|e| DiscordJsonError {
code: -1,
errors: FixedArray::empty(),
message: format!("[Serenity] Could not decode json when receiving error response from discord:, {e}").into(),
message: format!("[Serenity] Could not decode json when receiving error response from discord:, {e}").trunc_into(),
}),
}
}
Expand Down Expand Up @@ -197,7 +197,7 @@ pub fn deserialize_errors<'de, D: Deserializer<'de>>(
let mut path = Vec::new();
loop_errors(map, &mut errors, &mut path).map_err(D::Error::custom)?;

Ok(errors.into())
Ok(errors.trunc_into())
}

fn make_error(
Expand Down Expand Up @@ -253,8 +253,8 @@ mod test {
async fn test_error_response_into() {
let error = DiscordJsonError {
code: 43121215,
message: String::from("This is a Ferris error").into(),
errors: FixedArray::empty(),
message: FixedString::from_str_trunc("This is a Ferris error"),
};

let mut builder = Builder::new();
Expand All @@ -268,7 +268,7 @@ mod test {

let known = ErrorResponse {
status_code: reqwest::StatusCode::from_u16(403).unwrap(),
url: String::from("https://ferris.crab/").into(),
url: FixedString::from_str_trunc("https://ferris.crab/"),
method: Method::POST,
error,
};
Expand Down
2 changes: 1 addition & 1 deletion src/internal/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
pub use std::result::Result as StdResult;

pub use small_fixed_array::{FixedArray, FixedString};
pub use small_fixed_array::{FixedArray, FixedString, TruncatingInto};

pub use crate::error::{Error, Result};
pub use crate::json::{JsonMap, Value};
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,4 @@ pub mod all {
}

// Re-exports of crates used internally which are already publically exposed.
pub use nonmax;
pub use {nonmax, small_fixed_array};
34 changes: 17 additions & 17 deletions src/model/application/command_interaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,10 +339,10 @@ impl CommandData {
for opt in opts {
let value = match &opt.value {
CommandDataOptionValue::SubCommand(opts) => {
ResolvedValue::SubCommand(resolve_options(opts, resolved).into())
ResolvedValue::SubCommand(resolve_options(opts, resolved).trunc_into())
},
CommandDataOptionValue::SubCommandGroup(opts) => {
ResolvedValue::SubCommandGroup(resolve_options(opts, resolved).into())
ResolvedValue::SubCommandGroup(resolve_options(opts, resolved).trunc_into())
},
CommandDataOptionValue::Autocomplete {
kind,
Expand Down Expand Up @@ -566,13 +566,13 @@ fn option_from_raw(raw: RawCommandDataOption) -> Result<CommandDataOption> {
let options =
raw.options.ok_or_else::<JsonError, _>(|| DeError::missing_field("options"))?;
let options = options.into_iter().map(option_from_raw).collect::<Result<_>>()?;
CommandDataOptionValue::SubCommand(options)
CommandDataOptionValue::SubCommand(FixedArray::from_vec_trunc(options))
},
CommandOptionType::SubCommandGroup => {
let options =
raw.options.ok_or_else::<JsonError, _>(|| DeError::missing_field("options"))?;
let options = options.into_iter().map(option_from_raw).collect::<Result<_>>()?;
CommandDataOptionValue::SubCommandGroup(options)
CommandDataOptionValue::SubCommandGroup(FixedArray::from_vec_trunc(options))
},
CommandOptionType::Attachment => CommandDataOptionValue::Attachment(value!()),
CommandOptionType::Channel => CommandDataOptionValue::Channel(value!()),
Expand Down Expand Up @@ -811,19 +811,19 @@ mod tests {
#[test]
fn nested_options() {
let value = CommandDataOption {
name: "subcommand_group".to_string().into(),
name: FixedString::from_str_trunc("subcommand_group"),
value: CommandDataOptionValue::SubCommandGroup(
vec![CommandDataOption {
name: "subcommand".to_string().into(),
name: FixedString::from_str_trunc("subcommand"),
value: CommandDataOptionValue::SubCommand(
vec![CommandDataOption {
name: "channel".to_string().into(),
name: FixedString::from_str_trunc("channel"),
value: CommandDataOptionValue::Channel(ChannelId::new(3)),
}]
.into(),
.trunc_into(),
),
}]
.into(),
.trunc_into(),
),
};

Expand All @@ -845,30 +845,30 @@ mod tests {
fn mixed_options() {
let value = vec![
CommandDataOption {
name: "boolean".to_string().into(),
name: FixedString::from_str_trunc("boolean"),
value: CommandDataOptionValue::Boolean(true),
},
CommandDataOption {
name: "integer".to_string().into(),
name: FixedString::from_str_trunc("integer"),
value: CommandDataOptionValue::Integer(1),
},
CommandDataOption {
name: "number".to_string().into(),
name: FixedString::from_str_trunc("number"),
value: CommandDataOptionValue::Number(2.0),
},
CommandDataOption {
name: "string".to_string().into(),
value: CommandDataOptionValue::String("foobar".to_string().into()),
name: FixedString::from_str_trunc("string"),
value: CommandDataOptionValue::String(FixedString::from_str_trunc("foobar")),
},
CommandDataOption {
name: "empty_subcommand".to_string().into(),
name: FixedString::from_str_trunc("empty_subcommand"),
value: CommandDataOptionValue::SubCommand(FixedArray::default()),
},
CommandDataOption {
name: "autocomplete".to_string().into(),
name: FixedString::from_str_trunc("autocomplete"),
value: CommandDataOptionValue::Autocomplete {
kind: CommandOptionType::Integer,
value: "not an integer".to_string().into(),
value: FixedString::from_str_trunc("not an integer"),
},
},
];
Expand Down
6 changes: 3 additions & 3 deletions src/model/application/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,10 @@ mod tests {
let mut button = Button {
kind: ComponentType::Button,
data: ButtonKind::NonLink {
custom_id: "hello".to_string().into(),
custom_id: FixedString::from_str_trunc("hello"),
style: ButtonStyle::Danger,
},
label: Some("a".to_string().into()),
label: Some(FixedString::from_str_trunc("a")),
emoji: None,
disabled: false,
};
Expand All @@ -317,7 +317,7 @@ mod tests {
);

button.data = ButtonKind::Link {
url: "https://google.com".to_string().into(),
url: FixedString::from_str_trunc("https://google.com"),
};
assert_json(
&button,
Expand Down
2 changes: 1 addition & 1 deletion src/model/channel/embed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl EmbedField {
T: Into<String>,
U: Into<String>,
{
Self::_new(name.into().into(), value.into().into(), inline)
Self::_new(name.into().trunc_into(), value.into().trunc_into(), inline)
}

pub(crate) const fn _new(
Expand Down
11 changes: 6 additions & 5 deletions src/model/channel/reaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ impl From<char> for ReactionType {
/// # fn main() {}
/// ```
fn from(ch: char) -> ReactionType {
ReactionType::Unicode(ch.to_string().into())
ReactionType::Unicode(ch.to_string().trunc_into())
}
}

Expand Down Expand Up @@ -436,7 +436,7 @@ impl TryFrom<String> for ReactionType {
}

if !emoji_string.starts_with('<') {
return Ok(ReactionType::Unicode(emoji_string.into()));
return Ok(ReactionType::Unicode(emoji_string.trunc_into()));
}
ReactionType::try_from(&emoji_string[..])
}
Expand Down Expand Up @@ -470,13 +470,14 @@ impl<'a> TryFrom<&'a str> for ReactionType {
/// ```rust
/// use serenity::model::channel::ReactionType;
/// use serenity::model::id::EmojiId;
/// use serenity::small_fixed_array::FixedString;
///
/// let emoji_string = "<:customemoji:600404340292059257>";
/// let reaction = ReactionType::try_from(emoji_string).unwrap();
/// let reaction2 = ReactionType::Custom {
/// animated: false,
/// id: EmojiId::new(600404340292059257),
/// name: Some("customemoji".to_string().into()),
/// name: Some(FixedString::from_str_trunc("customemoji")),
/// };
///
/// assert_eq!(reaction, reaction2);
Expand All @@ -490,7 +491,7 @@ impl<'a> TryFrom<&'a str> for ReactionType {
}

if !emoji_str.starts_with('<') {
return Ok(ReactionType::Unicode(emoji_str.to_string().into()));
return Ok(ReactionType::Unicode(emoji_str.to_string().trunc_into()));
}

if !emoji_str.ends_with('>') {
Expand All @@ -502,7 +503,7 @@ impl<'a> TryFrom<&'a str> for ReactionType {
let mut split_iter = emoji_str.split(':');

let animated = split_iter.next().ok_or(ReactionConversionError)? == "a";
let name = Some(split_iter.next().ok_or(ReactionConversionError)?.to_string().into());
let name = Some(split_iter.next().ok_or(ReactionConversionError)?.to_string().trunc_into());
let id = split_iter.next().and_then(|s| s.parse().ok()).ok_or(ReactionConversionError)?;

Ok(ReactionType::Custom {
Expand Down
2 changes: 1 addition & 1 deletion src/model/guild/audit_log/change.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ mod tests {
fn entity_type_variant() {
let value = Change::Type {
old: Some(EntityType::Int(123)),
new: Some(EntityType::Str("discord".to_string().into())),
new: Some(EntityType::Str(FixedString::from_str_trunc("discord"))),
};
assert_json(&value, json!({"key": "type", "old_value": 123, "new_value": "discord"}));
}
Expand Down
4 changes: 2 additions & 2 deletions src/model/guild/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2623,9 +2623,9 @@ mod test {

fn gen_member() -> Member {
Member {
nick: Some("aaaa".to_string().into()),
nick: Some(FixedString::from_str_trunc("aaaa")),
user: User {
name: "test".to_string().into(),
name: FixedString::from_str_trunc("test"),
discriminator: NonZeroU16::new(1432),
..User::default()
},
Expand Down
4 changes: 2 additions & 2 deletions src/model/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ impl fmt::Display for EmojiIdentifier {
#[derive(Debug)]
#[cfg(all(feature = "model", feature = "utils"))]
pub struct EmojiIdentifierParseError {
parsed_string: FixedString,
parsed_string: String,
}

#[cfg(all(feature = "model", feature = "utils"))]
Expand All @@ -224,7 +224,7 @@ impl FromStr for EmojiIdentifier {

fn from_str(s: &str) -> StdResult<Self, Self::Err> {
utils::parse_emoji(s).ok_or_else(|| EmojiIdentifierParseError {
parsed_string: s.to_owned().into(),
parsed_string: s.to_owned(),
})
}
}
Expand Down
Loading

0 comments on commit 3eaf191

Please sign in to comment.