Skip to content

Commit

Permalink
Replace serenity::json::prelude with public wrapper functions (sere…
Browse files Browse the repository at this point in the history
…nity-rs#2569)

To avoid future breakage, we shouldn't re-export functions from dependency
libraries in case a function signature changes, which would pass on breaking
changes to Serenity's users. Providing wrapper functions solves this issue.

Note: changed `from_str` to take `&str` instead of `String`, and simply clone
it for the `simd_json` case. This means the more common `serde_json` use case
no longer requires ownership (or an extra clone before passing the string in).
  • Loading branch information
mkrasnitski authored and arqunis committed Oct 24, 2023
1 parent ae8c0e0 commit 7386be6
Show file tree
Hide file tree
Showing 24 changed files with 205 additions and 168 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ secrecy = { version = "0.8.0", features = ["serde"] }
arrayvec = { version = "0.7.3", features = ["serde"] }
# Optional dependencies
fxhash = { version = "0.2.1", optional = true }
simd-json = { version = "0.10", optional = true }
simd-json = { version = "0.12", optional = true }
uwl = { version = "0.6.0", optional = true }
levenshtein = { version = "1.0.5", optional = true }
chrono = { version = "0.4.22", default-features = false, features = ["clock", "serde"], optional = true }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ the HTTP functions.
instead of `rustls_backend`.
- **tokio_task_builder**: Enables tokio's `tracing` feature and uses `tokio::task::Builder` to spawn tasks with names if `RUSTFLAGS="--cfg tokio_unstable"` is set.
- **unstable_discord_api**: Enables features of the Discord API that do not have a stable interface. The features might not have official documentation or are subject to change.
- **simd_json**: Enables SIMD accelerated JSON parsing and rendering for API calls, use with `RUSTFLAGS="-C target-cpu=native"`
- **simd_json**: Enables SIMD accelerated JSON parsing and rendering for API calls, if supported on the target CPU architecture.
- **temp_cache**: Enables temporary caching in functions that retrieve data via the HTTP API.
- **chrono**: Uses the `chrono` crate to represent timestamps. If disabled, the `time` crate is used instead.
- **interactions_endpoint**: Enables tools related to Discord's Interactions Endpoint URL feature
Expand Down
1 change: 0 additions & 1 deletion examples/e19_interactions_endpoint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ edition = "2018"
[dependencies]
serenity = { path = "../../", default-features = false, features = ["builder", "interactions_endpoint"] }
tiny_http = "0.12.0"
serde_json = "1.0"
5 changes: 3 additions & 2 deletions examples/e19_interactions_endpoint/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use serenity::builder::*;
use serenity::interactions_endpoint::Verifier;
use serenity::json;
use serenity::model::application::*;

type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
Expand Down Expand Up @@ -36,7 +37,7 @@ fn handle_request(
}

// Build Discord response
let response = match serde_json::from_slice::<Interaction>(body)? {
let response = match json::from_slice::<Interaction>(body)? {
// Discord rejects the interaction endpoints URL if pings are not acknowledged
Interaction::Ping(_) => CreateInteractionResponse::Pong,
Interaction::Command(interaction) => handle_command(interaction),
Expand All @@ -45,7 +46,7 @@ fn handle_request(

// Send the Discord response back via HTTP
request.respond(
tiny_http::Response::from_data(serde_json::to_vec(&response)?)
tiny_http::Response::from_data(json::to_vec(&response)?)
.with_header("Content-Type: application/json".parse::<tiny_http::Header>().unwrap()),
)?;

Expand Down
10 changes: 5 additions & 5 deletions src/builder/create_components.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use serde::Serialize;

use crate::json::json;
use crate::json::{self, json};
use crate::model::prelude::*;

/// A builder for creating a components action row in a message.
Expand All @@ -19,12 +19,12 @@ impl serde::Serialize for CreateActionRow {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::Error as _;

serde_json::json!({
json!({
"type": 1,
"components": match self {
Self::Buttons(x) => serde_json::to_value(x).map_err(S::Error::custom)?,
Self::SelectMenu(x) => serde_json::to_value(vec![x]).map_err(S::Error::custom)?,
Self::InputText(x) => serde_json::to_value(vec![x]).map_err(S::Error::custom)?,
Self::Buttons(x) => json::to_value(x).map_err(S::Error::custom)?,
Self::SelectMenu(x) => json::to_value(vec![x]).map_err(S::Error::custom)?,
Self::InputText(x) => json::to_value(vec![x]).map_err(S::Error::custom)?,
}
})
.serialize(serializer)
Expand Down
17 changes: 9 additions & 8 deletions src/builder/create_interaction_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::constants;
#[cfg(feature = "http")]
use crate::http::CacheHttp;
use crate::internal::prelude::*;
use crate::json::{self, json};
use crate::model::prelude::*;

/// [Discord docs](https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-response-object).
Expand Down Expand Up @@ -57,7 +58,7 @@ impl serde::Serialize for CreateInteractionResponse {
use serde::ser::Error as _;

#[allow(clippy::match_same_arms)] // hurts readability
serde_json::json!({
json!({
"type": match self {
Self::Pong { .. } => 1,
Self::Message { .. } => 4,
Expand All @@ -68,13 +69,13 @@ impl serde::Serialize for CreateInteractionResponse {
Self::Modal { .. } => 9,
},
"data": match self {
Self::Pong => serde_json::Value::Null,
Self::Message(x) => serde_json::to_value(x).map_err(S::Error::custom)?,
Self::Defer(x) => serde_json::to_value(x).map_err(S::Error::custom)?,
Self::Acknowledge => serde_json::Value::Null,
Self::UpdateMessage(x) => serde_json::to_value(x).map_err(S::Error::custom)?,
Self::Autocomplete(x) => serde_json::to_value(x).map_err(S::Error::custom)?,
Self::Modal(x) => serde_json::to_value(x).map_err(S::Error::custom)?,
Self::Pong => json::NULL,
Self::Message(x) => json::to_value(x).map_err(S::Error::custom)?,
Self::Defer(x) => json::to_value(x).map_err(S::Error::custom)?,
Self::Acknowledge => json::NULL,
Self::UpdateMessage(x) => json::to_value(x).map_err(S::Error::custom)?,
Self::Autocomplete(x) => json::to_value(x).map_err(S::Error::custom)?,
Self::Modal(x) => json::to_value(x).map_err(S::Error::custom)?,
}
})
.serialize(serializer)
Expand Down
2 changes: 1 addition & 1 deletion src/cache/cache_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use super::Cache;
/// Some(old_user)
/// },
/// Entry::Vacant(entry) => {
/// // We can convert a [`serde_json::Value`] to a User for test
/// // We can convert a [`json::Value`] to a User for test
/// // purposes.
/// let user = from_value::<User>(json!({
/// "id": self.user_id,
Expand Down
17 changes: 3 additions & 14 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::io::Error as IoError;

#[cfg(feature = "http")]
use reqwest::{header::InvalidHeaderValue, Error as ReqwestError};
use serde_json::Error as JsonError;
#[cfg(feature = "gateway")]
use tokio_tungstenite::tungstenite::error::Error as TungsteniteError;
use tracing::instrument;
Expand All @@ -16,6 +15,7 @@ use crate::gateway::GatewayError;
#[cfg(feature = "http")]
use crate::http::HttpError;
use crate::internal::prelude::*;
use crate::json::JsonError;
use crate::model::ModelError;

/// The common result type between most library functions.
Expand All @@ -38,11 +38,9 @@ pub enum Error {
Format(FormatError),
/// An [`std::io`] error.
Io(IoError),
/// An error from the [`serde_json`] crate.
#[cfg_attr(not(feature = "simd_json"), doc = "An error from the [`serde_json`] crate.")]
#[cfg_attr(feature = "simd_json", doc = "An error from the [`simd_json`] crate.")]
Json(JsonError),
#[cfg(feature = "simd_json")]
/// An error from the `simd_json` crate.
SimdJson(simd_json::Error),
/// An error from the [`model`] module.
///
/// [`model`]: crate::model
Expand Down Expand Up @@ -90,13 +88,6 @@ pub enum Error {
Tungstenite(TungsteniteError),
}

#[cfg(feature = "simd_json")]
impl From<simd_json::Error> for Error {
fn from(e: simd_json::Error) -> Self {
Error::SimdJson(e)
}
}

impl From<FormatError> for Error {
fn from(e: FormatError) -> Error {
Error::Format(e)
Expand Down Expand Up @@ -167,8 +158,6 @@ impl fmt::Display for Error {
Self::Json(inner) => fmt::Display::fmt(&inner, f),
Self::Model(inner) => fmt::Display::fmt(&inner, f),
Self::Url(msg) => f.write_str(msg),
#[cfg(feature = "simd_json")]
Error::SimdJson(inner) => fmt::Display::fmt(&inner, f),
#[cfg(feature = "client")]
Self::Client(inner) => fmt::Display::fmt(&inner, f),
#[cfg(feature = "gateway")]
Expand Down
4 changes: 2 additions & 2 deletions src/gateway/ws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,14 @@ impl WsClient {
why
})?;

from_str(decompressed).map_err(|why| {
from_str(&decompressed).map_err(|why| {
warn!("Err deserializing bytes: {why:?}");
debug!("Failing bytes: {bytes:?}");

why
})?
},
Message::Text(payload) => from_str(payload.clone()).map_err(|why| {
Message::Text(payload) => from_str(&payload).map_err(|why| {
warn!("Err deserializing text: {why:?}; text: {payload}");

why
Expand Down
20 changes: 9 additions & 11 deletions src/http/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use super::{
use crate::builder::CreateAttachment;
use crate::constants;
use crate::internal::prelude::*;
use crate::json::prelude::*;
use crate::json::*;
use crate::model::application::{Command, CommandPermissions};
use crate::model::guild::automod::Rule;
use crate::model::prelude::*;
Expand Down Expand Up @@ -2142,7 +2142,7 @@ impl Http {
///
/// ```rust,no_run
/// use serenity::http::Http;
/// use serenity::json::{json, prelude::*};
/// use serenity::json::json;
/// use serenity::model::prelude::*;
///
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
Expand Down Expand Up @@ -2195,7 +2195,7 @@ impl Http {
///
/// ```rust,no_run
/// use serenity::http::Http;
/// use serenity::json::{json, prelude::*};
/// use serenity::json::json;
/// use serenity::model::prelude::*;
///
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
Expand Down Expand Up @@ -2293,17 +2293,16 @@ impl Http {
///
/// ```rust,no_run
/// use serenity::http::Http;
/// use serenity::json::prelude::*;
/// use serenity::json::json;
/// use serenity::model::prelude::*;
///
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
/// # let http: Http = unimplemented!();
/// let id = WebhookId::new(245037420704169985);
/// let token = "ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV";
/// let value = json!({"name": "new name"});
/// let map = value.as_object().unwrap();
/// let map = json!({"name": "new name"});
///
/// let edited = http.edit_webhook_with_token(id, token, map, None).await?;
/// let edited = http.edit_webhook_with_token(id, token, &map, None).await?;
/// # Ok(())
/// # }
/// ```
Expand Down Expand Up @@ -2364,18 +2363,17 @@ impl Http {
///
/// ```rust,no_run
/// use serenity::http::Http;
/// use serenity::json::prelude::*;
/// use serenity::json::json;
/// use serenity::model::prelude::*;
///
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
/// # let http: Http = unimplemented!();
/// let id = WebhookId::new(245037420704169985);
/// let token = "ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV";
/// let value = json!({"content": "test"});
/// let map = value.as_object().unwrap();
/// let map = json!({"content": "test"});
/// let files = vec![];
///
/// let message = http.execute_webhook(id, None, token, true, files, map).await?;
/// let message = http.execute_webhook(id, None, token, true, files, &map).await?;
/// # Ok(())
/// # }
/// ```
Expand Down
2 changes: 1 addition & 1 deletion src/http/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde::de::{Deserialize, Deserializer, Error as _};
use url::ParseError as UrlError;

use crate::internal::prelude::*;
use crate::json::decode_resp;
use crate::json::*;

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[non_exhaustive]
Expand Down
3 changes: 0 additions & 3 deletions src/internal/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
pub use std::result::Result as StdResult;

#[cfg(feature = "simd_json")]
pub use simd_json::{Mutable, Value as ValueTrait, ValueAccess};

#[cfg(feature = "client")]
pub use crate::client::ClientError;
pub use crate::error::{Error, Result};
Expand Down
Loading

0 comments on commit 7386be6

Please sign in to comment.