Skip to content

Commit

Permalink
Replace serenity::json::prelude with wrapper functions
Browse files Browse the repository at this point in the history
  • Loading branch information
mkrasnitski committed Oct 16, 2023
1 parent ba7988b commit 3d19a75
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 91 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.11", 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
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
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
2 changes: 1 addition & 1 deletion 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
202 changes: 120 additions & 82 deletions src/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,47 @@ use std::collections::HashMap;
use std::hash::{BuildHasher, Hash};

use serde::de::DeserializeOwned;
use serde::ser::Serialize;
#[cfg(test)]
use serde::Deserialize;
use serde::Serialize;

use crate::Result;

#[cfg(not(feature = "simd-json"))]
pub type Value = serde_json::Value;
#[cfg(feature = "simd-json")]
pub type Value = simd_json::OwnedValue;

#[cfg(not(feature = "simd-json"))]
pub use serde_json::json;
#[cfg(not(feature = "simd-json"))]
pub use serde_json::Error as JsonError;
#[cfg(feature = "simd-json")]
pub use simd_json::json;
#[cfg(feature = "simd-json")]
pub use simd_json::Error as JsonError;

#[cfg(not(feature = "simd-json"))]
pub type JsonMap = serde_json::Map<String, Value>;
#[cfg(feature = "simd-json")]
pub type JsonMap = simd_json::owned::Object;

#[cfg(not(feature = "simd-json"))]
pub const NULL: Value = Value::Null;
#[cfg(feature = "simd-json")]
pub const NULL: Value = Value::Static(simd_json::StaticNode::Null);
#[cfg(not(feature = "simd_json"))]
mod export {
pub type Value = serde_json::Value;
pub type JsonMap = serde_json::Map<String, Value>;
pub const NULL: Value = Value::Null;

pub use serde_json::{json, Error as JsonError};
}

#[cfg(feature = "simd_json")]
mod export {
pub type Value = simd_json::OwnedValue;
pub type JsonMap = simd_json::owned::Object;
pub const NULL: Value = Value::Static(simd_json::StaticNode::Null);

pub use simd_json::{
json,
Builder,
Error as JsonError,
Mutable,
StaticNode,
Value as ValueTrait,
ValueAccess,
};
}

pub use export::*;

#[cfg(feature = "http")]
pub(crate) async fn decode_resp<T: serde::de::DeserializeOwned>(
resp: reqwest::Response,
) -> Result<T> {
#[cfg(not(feature = "simd-json"))]
#[cfg(not(feature = "simd_json"))]
let result = serde_json::from_slice(&resp.bytes().await?)?;
#[cfg(feature = "simd-json")]
#[cfg(feature = "simd_json")]
let result = simd_json::from_slice(&mut resp.bytes().await?.to_vec())?;
Ok(result)
}
Expand All @@ -53,52 +59,115 @@ where
map.into_iter().map(|(k, v)| (k.to_string(), v)).collect()
}

/// Deserialize an instance of type `T` from a string of JSON text.
#[cfg_attr(not(feature = "simd_json"), allow(unused_mut))]
#[allow(clippy::missing_errors_doc)] // It's obvious
pub fn to_string<T>(v: &T) -> Result<String>
pub fn from_str<T>(s: &str) -> Result<T>
where
T: Serialize,
T: DeserializeOwned,
{
#[cfg(not(feature = "simd-json"))]
let result = serde_json::to_string(v)?;
#[cfg(feature = "simd-json")]
let result = simd_json::to_string(v)?;
#[cfg(not(feature = "simd_json"))]
let result = serde_json::from_str(s)?;
#[cfg(feature = "simd_json")]
let result = simd_json::from_slice(&mut s.as_bytes().to_vec())?;
Ok(result)
}

#[cfg_attr(not(feature = "simd-json"), allow(unused_mut))]
#[allow(clippy::missing_errors_doc)] // It's obvious
pub fn from_str<T>(mut s: String) -> Result<T>
/// Deserialize an instance of type `T` from bytes of JSON text.
pub fn from_slice<T>(v: &[u8]) -> Result<T>
where
T: DeserializeOwned,
{
#[cfg(not(feature = "simd-json"))]
let result = serde_json::from_str(&s)?;
#[cfg(feature = "simd-json")]
// SAFETY: `simd_json::from_str` mutates the underlying string such that it might not be valid
// UTF-8 afterward. However, we own `s`, so it gets thrown away after it's used here.
let result = unsafe { simd_json::from_str(&mut s)? };
#[cfg(not(feature = "simd_json"))]
let result = serde_json::from_slice(v)?;
#[cfg(feature = "simd_json")]
// We clone here to obtain a mutable reference to the clone, since we don't have a mutable ref
// to the original.
let result = simd_json::from_slice(&mut v.to_vec())?;
Ok(result)
}

pub(crate) fn from_value<T>(v: Value) -> Result<T>
/// Interpret a [`Value`] as an instance of type `T`.
pub fn from_value<T>(value: Value) -> Result<T>
where
T: DeserializeOwned,
{
#[cfg(not(feature = "simd-json"))]
let result = serde_json::from_value(v)?;
#[cfg(feature = "simd-json")]
let result = simd_json::serde::from_owned_value(v)?;
#[cfg(not(feature = "simd_json"))]
let result = serde_json::from_value(value)?;
#[cfg(feature = "simd_json")]
let result = simd_json::serde::from_owned_value(value)?;
Ok(result)
}

#[cfg(test)]
pub(crate) fn to_value<T>(value: T) -> Result<Value>
/// Deserialize an instance of type `T` from bytes of JSON text.
pub fn from_reader<R, T>(rdr: R) -> Result<T>
where
R: std::io::Read,
T: DeserializeOwned,
{
#[cfg(not(feature = "simd_json"))]
let result = serde_json::from_reader(rdr)?;
#[cfg(feature = "simd_json")]
let result = simd_json::from_reader(rdr)?;
Ok(result)
}

/// Serialize the given data structure as a String of JSON.
pub fn to_string<T>(value: &T) -> Result<String>
where
T: ?Sized + Serialize,
{
#[cfg(not(feature = "simd_json"))]
let result = serde_json::to_string(value)?;
#[cfg(feature = "simd_json")]
let result = simd_json::to_string(value)?;
Ok(result)
}

/// Serialize the given data structure as a pretty-printed String of JSON.
pub fn to_string_pretty<T>(value: &T) -> Result<String>
where
T: ?Sized + Serialize,
{
#[cfg(not(feature = "simd_json"))]
let result = serde_json::to_string_pretty(value)?;
#[cfg(feature = "simd_json")]
let result = simd_json::to_string_pretty(value)?;
Ok(result)
}

/// Serialize the given data structure as a JSON byte vector.
pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
where
T: ?Sized + Serialize,
{
#[cfg(not(feature = "simd_json"))]
let result = serde_json::to_vec(value)?;
#[cfg(feature = "simd_json")]
let result = simd_json::to_vec(value)?;
Ok(result)
}

/// Serialize the given data structure as a pretty-printed JSON byte vector.
pub fn to_vec_pretty<T>(value: &T) -> Result<Vec<u8>>
where
T: ?Sized + Serialize,
{
#[cfg(not(feature = "simd_json"))]
let result = serde_json::to_vec_pretty(value)?;
#[cfg(feature = "simd_json")]
let result = simd_json::to_vec_pretty(value)?;
Ok(result)
}

/// Convert a `T` into a [`Value`] which is an enum that can represent any valid JSON data.
pub fn to_value<T>(value: T) -> Result<Value>
where
T: Serialize,
{
#[cfg(not(feature = "simd-json"))]
#[cfg(not(feature = "simd_json"))]
let result = serde_json::to_value(value)?;
#[cfg(feature = "simd-json")]
#[cfg(feature = "simd_json")]
let result = simd_json::serde::to_owned_value(value)?;
Ok(result)
}
Expand All @@ -107,7 +176,7 @@ where
#[track_caller]
pub(crate) fn assert_json<T>(data: &T, json: crate::json::Value)
where
T: serde::Serialize + for<'de> serde::Deserialize<'de> + PartialEq + std::fmt::Debug,
T: Serialize + for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug,
{
// test serialization
let serialized = to_value(data).unwrap();
Expand All @@ -123,34 +192,3 @@ where
"JSON->data deserialization failed\nexpected: {data:?}\n got: {deserialized:?}"
);
}

pub mod prelude {
#[cfg(not(feature = "simd-json"))]
pub use serde_json::{
from_reader,
from_slice,
from_str,
from_value,
to_string,
to_string_pretty,
to_value,
to_vec,
to_vec_pretty,
};
#[cfg(feature = "simd-json")]
pub use simd_json::{
from_reader,
from_slice,
from_str,
serde::from_owned_value as from_value,
serde::to_owned_value as to_value,
to_string,
to_string_pretty,
to_vec,
to_vec_pretty,
};
#[cfg(feature = "simd-json")]
pub use simd_json::{Builder, Mutable, StaticNode, Value as ValueTrait, ValueAccess};

pub use super::*;
}
2 changes: 1 addition & 1 deletion src/model/channel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub use self::private_channel::*;
pub use self::reaction::*;
#[cfg(feature = "model")]
use crate::http::CacheHttp;
use crate::json::prelude::*;
use crate::json::*;
use crate::model::prelude::*;
use crate::model::utils::is_false;
use crate::model::Timestamp;
Expand Down
2 changes: 1 addition & 1 deletion src/model/guild/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ use crate::gateway::ShardMessenger;
#[cfg(feature = "model")]
use crate::http::{CacheHttp, Http, UserPagination};
#[cfg(feature = "model")]
use crate::json::prelude::json;
use crate::json::json;
#[cfg(feature = "model")]
use crate::model::application::{Command, CommandPermissions};
#[cfg(feature = "model")]
Expand Down

0 comments on commit 3d19a75

Please sign in to comment.