diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 592f26a..de7c917 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - rust: [nightly, beta, stable, 1.37.0] + rust: [nightly, beta, stable, 1.42.0] steps: - uses: actions/checkout@v2 - uses: dtolnay/rust-toolchain@master diff --git a/Cargo.toml b/Cargo.toml index e8e62cc..a5947f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,8 @@ rustc-serialize = { version = "0.3", optional = true } serde = { version = "1.0", features = ["derive"], optional = true } serde-bench = { version = "0.0.7", optional = true } serde_json = { version = "1.0", optional = true } -simd-json = { version = "0.1", optional = true} +simd-json = { version = "0.3", optional = true } +simd-json-derive = { version = "0.1", optional = true } time = "0.1" [features] @@ -22,7 +23,7 @@ all-libs = ["lib-serde", "lib-json-rust", "lib-rustc-serialize", "lib-simd-json" all-files = ["file-canada", "file-citm-catalog", "file-twitter"] performance = ["parse-dom", "stringify-dom", "parse-struct", "stringify-struct"] lib-serde = ["serde", "serde_json"] -lib-simd-json = ["serde", "simd-json"] +lib-simd-json = ["serde", "simd-json", "simd-json-derive"] lib-json-rust = ["json"] lib-rustc-serialize = ["rustc-serialize"] file-canada = [] diff --git a/src/canada.rs b/src/canada.rs index 70d84f3..4375c07 100644 --- a/src/canada.rs +++ b/src/canada.rs @@ -7,6 +7,7 @@ pub type Canada = FeatureCollection; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(deny_unknown_fields))] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct FeatureCollection { #[cfg_attr(feature = "serde", serde(rename = "type"))] pub obj_type: ObjType, @@ -15,6 +16,7 @@ pub struct FeatureCollection { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(deny_unknown_fields))] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Feature { #[cfg_attr(feature = "serde", serde(rename = "type"))] pub obj_type: ObjType, @@ -24,6 +26,7 @@ pub struct Feature { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(deny_unknown_fields))] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Geometry { #[cfg_attr(feature = "serde", serde(rename = "type"))] pub obj_type: ObjType, diff --git a/src/color.rs b/src/color.rs index ffcf22e..14d9a5b 100644 --- a/src/color.rs +++ b/src/color.rs @@ -58,6 +58,17 @@ impl Serialize for Color { } } +#[cfg(feature = "lib-simd-json")] +impl simd_json_derive::Serialize for Color { + fn json_write(&self, writer: &mut W) -> std::io::Result<()> + where + W: std::io::Write, + { + let mut buf = MaybeUninit::uninit(); + self.as_str(&mut buf).json_write(writer) + } +} + #[cfg(feature = "serde")] impl<'de> Deserialize<'de> for Color { fn deserialize(deserializer: D) -> Result diff --git a/src/copy/citm_catalog.rs b/src/copy/citm_catalog.rs index 84af11c..a707163 100644 --- a/src/copy/citm_catalog.rs +++ b/src/copy/citm_catalog.rs @@ -11,6 +11,7 @@ use crate::prim_str::PrimStr; feature = "serde", serde(deny_unknown_fields, rename_all = "camelCase") )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct CitmCatalog { pub area_names: Map, pub audience_sub_category_names: Map, @@ -33,6 +34,7 @@ pub type IdStr = PrimStr; feature = "serde", serde(deny_unknown_fields, rename_all = "camelCase") )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Event { pub description: (), pub id: Id, @@ -49,6 +51,7 @@ pub struct Event { feature = "serde", serde(deny_unknown_fields, rename_all = "camelCase") )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Performance { pub event_id: Id, pub id: Id, @@ -66,6 +69,7 @@ pub struct Performance { feature = "serde", serde(deny_unknown_fields, rename_all = "camelCase") )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Price { pub amount: u32, pub audience_sub_category_id: Id, @@ -77,6 +81,7 @@ pub struct Price { feature = "serde", serde(deny_unknown_fields, rename_all = "camelCase") )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct SeatCategory { pub areas: Vec, pub seat_category_id: Id, @@ -87,6 +92,7 @@ pub struct SeatCategory { feature = "serde", serde(deny_unknown_fields, rename_all = "camelCase") )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Area { pub area_id: Id, pub block_ids: empty::Array, diff --git a/src/copy/twitter.rs b/src/copy/twitter.rs index 7a63c51..7003d1d 100644 --- a/src/copy/twitter.rs +++ b/src/copy/twitter.rs @@ -11,6 +11,7 @@ use crate::prim_str::PrimStr; feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Twitter { pub statuses: Vec, pub search_metadata: SearchMetadata, @@ -27,6 +28,7 @@ pub type ShortIdStr = PrimStr; feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Status { pub metadata: Metadata, pub created_at: String, @@ -61,6 +63,7 @@ pub struct Status { feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Metadata { pub result_type: ResultType, pub iso_language_code: LanguageCode, @@ -72,6 +75,7 @@ pub struct Metadata { feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct User { pub id: ShortId, pub id_str: ShortIdStr, @@ -121,6 +125,7 @@ pub struct User { feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct UserEntities { pub url: Option, pub description: UserEntitiesDescription, @@ -132,6 +137,7 @@ pub struct UserEntities { feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct UserUrl { pub urls: Vec, } @@ -142,6 +148,7 @@ pub struct UserUrl { feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Url { pub url: String, pub expanded_url: String, @@ -155,6 +162,7 @@ pub struct Url { feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct UserEntitiesDescription { pub urls: Vec, } @@ -165,6 +173,7 @@ pub struct UserEntitiesDescription { feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct StatusEntities { pub hashtags: Vec, pub symbols: empty::Array, @@ -179,6 +188,7 @@ pub struct StatusEntities { feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Hashtag { pub text: String, pub indices: Indices, @@ -190,6 +200,7 @@ pub struct Hashtag { feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct UserMention { pub screen_name: String, pub name: String, @@ -200,6 +211,7 @@ pub struct UserMention { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(deny_unknown_fields))] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Media { pub id: LongId, pub id_str: LongIdStr, @@ -222,6 +234,7 @@ pub struct Media { feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Sizes { pub medium: Size, pub small: Size, @@ -235,6 +248,7 @@ pub struct Sizes { feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct Size { pub w: u16, pub h: u16, @@ -249,6 +263,7 @@ pub type Indices = (u8, u8); feature = "lib-rustc-serialize", derive(RustcEncodable, RustcDecodable) )] +#[cfg_attr(feature = "lib-simd-json", derive(simd_json_derive::Serialize))] pub struct SearchMetadata { pub completed_in: f32, pub max_id: LongId, diff --git a/src/empty.rs b/src/empty.rs index 59ed200..8df4241 100644 --- a/src/empty.rs +++ b/src/empty.rs @@ -45,6 +45,16 @@ impl<'de> Deserialize<'de> for Array { } } +#[cfg(feature = "lib-simd-json")] +impl simd_json_derive::Serialize for Array { + fn json_write(&self, writer: &mut W) -> std::io::Result<()> + where + W: std::io::Write, + { + writer.write_all(b"[]") + } +} + #[cfg(feature = "lib-rustc-serialize")] impl Encodable for Array { fn encode(&self, s: &mut S) -> Result<(), S::Error> diff --git a/src/enums.rs b/src/enums.rs index 856b738..cc47bea 100644 --- a/src/enums.rs +++ b/src/enums.rs @@ -6,7 +6,7 @@ macro_rules! enum_str { $($variant,)* } - #[cfg(any(feature = "serde", feature = "lib-rustc-serialize"))] + #[cfg(any(feature = "lib-simd-json", feature = "lib-serde", feature = "lib-rustc-serialize"))] impl $name { fn as_str(self) -> &'static str { match self { @@ -52,6 +52,15 @@ macro_rules! enum_str { } } + #[cfg(feature = "lib-simd-json")] + impl ::simd_json_derive::Serialize for $name { + fn json_write(&self, writer: &mut W) -> std::io::Result<()> + where W: std::io::Write + { + self.as_str().json_write(writer) + } + } + #[cfg(feature = "lib-rustc-serialize")] impl ::rustc_serialize::Encodable for $name { fn encode(&self, s: &mut S) -> Result<(), S::Error> diff --git a/src/main.rs b/src/main.rs index fb88596..a6d2f85 100644 --- a/src/main.rs +++ b/src/main.rs @@ -129,6 +129,7 @@ macro_rules! bench_file_simd_json { path: $path:expr, structure: $structure:ty, } => { + let num_trials = num_trials().unwrap_or(256); print!("{:22}", $path); @@ -160,6 +161,7 @@ macro_rules! bench_file_simd_json { #[cfg(feature = "stringify-dom")] { + use simd_json::prelude::*; let len = contents.len(); let mut data = contents.clone(); let dom = simd_json_parse_dom(&mut data).unwrap(); @@ -190,6 +192,22 @@ macro_rules! bench_file_simd_json { io::stdout().flush().unwrap(); } + #[cfg(feature = "stringify-struct")] + { + use simd_json_derive::Serialize; + let len = contents.len(); + let mut data = contents.clone(); + let parsed: $structure = simd_json_parse_struct(&mut data).unwrap(); + let dur = timer::bench_with_buf(num_trials, len, |out| { + parsed.json_write(out).unwrap(); + }); + let mut serialized = Vec::new(); + parsed.json_write(&mut serialized).unwrap(); + + print!("{:6} MB/s", throughput(dur, serialized.len())); + io::stdout().flush().unwrap(); + } + println!(); } } diff --git a/src/prim_str.rs b/src/prim_str.rs index 6d34daf..d0c6ea2 100644 --- a/src/prim_str.rs +++ b/src/prim_str.rs @@ -65,6 +65,19 @@ where } } +#[cfg(feature = "lib-simd-json")] +impl simd_json_derive::Serialize for PrimStr +where + T: Copy + Ord + Display + FromStr, +{ + fn json_write(&self, writer: &mut W) -> std::io::Result<()> + where + W: std::io::Write, + { + write!(writer, "{}", self.0) + } +} + #[cfg(feature = "lib-rustc-serialize")] impl Encodable for PrimStr where