From 1768216c04fa358bdf37bba401c1c0d9f0fa3b31 Mon Sep 17 00:00:00 2001 From: kirk Date: Tue, 11 Jul 2023 21:51:23 -0500 Subject: [PATCH] put macros and traits of each type behind individual feature flags --- .github/workflows/rust.yml | 52 ++++++++++++++++++++++++++++++++++++++ Cargo.toml | 10 +++++--- README.md | 14 ++++++++++ derive/Cargo.toml | 5 +++- derive/src/lib.rs | 15 +++++++++-- derive/src/parse.rs | 3 +++ derive/src/shared.rs | 8 ++++++ src/lib.rs | 12 +++++++-- tests/bin.rs | 2 +- tests/json.rs | 1 + tests/parse.rs | 1 + tests/ron.rs | 1 + tests/ser_de.rs | 40 +++++++++++++++++++++-------- tests/toml.rs | 2 ++ 14 files changed, 146 insertions(+), 20 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 219bc89..fe1da43 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -56,6 +56,58 @@ jobs: command: build args: --all-targets --target=${{ matrix.config.target }} + features: + name: Test Individual Features + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + feature: [ + "binary", + "json", + "ron", + "toml", + ] + + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: x86_64-unknown-linux-gnu + override: true + + - uses: actions-rs/cargo@v1 + with: + command: test + args: --no-default-features --features ${{ matrix.feature }} + + no_std_features: + name: Test Individual Features NoStd + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + feature: [ + "binary", + "json", + "ron", + "toml", + ] + + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + target: x86_64-unknown-linux-gnu + override: true + + - uses: actions-rs/cargo@v1 + with: + command: test + args: --no-default-features --features "no_std, ${{ matrix.feature }}" + test: name: Test runs-on: ${{ matrix.config.os }} diff --git a/Cargo.toml b/Cargo.toml index ef705bf..31233b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nanoserde" -version = "0.1.37" +version = "0.2.0" authors = ["makepad ", "Fedor "] license = "MIT OR Apache-2.0" description = """ @@ -22,9 +22,13 @@ edition = "2018" repository = "https://github.com/not-fl3/nanoserde" [features] -default = [] +default = ["json", "binary", "ron", "toml"] +json = ["dep:nanoserde-derive", "nanoserde-derive/json"] +binary = ["dep:nanoserde-derive", "nanoserde-derive/binary"] +ron = ["dep:nanoserde-derive", "nanoserde-derive/ron"] +toml = [] no_std = ["dep:hashbrown"] [dependencies] hashbrown = { version = "0.12.3", optional = true } -nanoserde-derive = { path = "derive", version = "=0.1.22" } +nanoserde-derive = { path = "derive", version = "=0.2.0", optional = true } diff --git a/README.md b/README.md index 0cd16f2..c67121f 100644 --- a/README.md +++ b/README.md @@ -52,3 +52,17 @@ For more examples take a look at [tests](/tests) | container attribute: `#[nserde(proxy = "")]` | yes | yes | no | no | | container attribute: `#[nserde(transparent)]` | yes | no | no | no | +## Crate features: + +All features are enabled by default. To enable only specific formats, import nanoserde using +```toml +nanoserde = { version = "*", default-features = false, features = [] } +``` +in your `Cargo.toml` and add one or more of the following crate features: + +| Format | Feature Name | +| ----------| -------------- | +| Binary | `binary` | +| JSON | `json` | +| RON | `ron` | +| TOML | `toml` | diff --git a/derive/Cargo.toml b/derive/Cargo.toml index c52647d..30ea539 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nanoserde-derive" -version = "0.1.22" +version = "0.2.0" authors = ["Makepad ", "Fedor "] edition = "2018" description = "Fork of makepad-tinyserde derive without any external dependencies" @@ -11,6 +11,9 @@ proc-macro = true [features] default = [] +json = [] +binary = [] +ron = [] no_std = ["dep:hashbrown"] [dependencies] diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 4e8b620..c8a5e79 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -6,18 +6,24 @@ extern crate proc_macro; #[macro_use] mod shared; +#[cfg(feature = "binary")] mod serde_bin; +#[cfg(feature = "binary")] use crate::serde_bin::*; +#[cfg(feature = "ron")] mod serde_ron; +#[cfg(feature = "ron")] use crate::serde_ron::*; +#[cfg(feature = "json")] mod serde_json; +#[cfg(feature = "json")] +use crate::serde_json::*; mod parse; -use crate::serde_json::*; - +#[cfg(feature = "binary")] #[proc_macro_derive(SerBin, attributes(nserde))] pub fn derive_ser_bin(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse::parse_data(input); @@ -37,6 +43,7 @@ pub fn derive_ser_bin(input: proc_macro::TokenStream) -> proc_macro::TokenStream ts } +#[cfg(feature = "binary")] #[proc_macro_derive(DeBin, attributes(nserde))] pub fn derive_de_bin(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse::parse_data(input); @@ -57,6 +64,7 @@ pub fn derive_de_bin(input: proc_macro::TokenStream) -> proc_macro::TokenStream ts } +#[cfg(feature = "ron")] #[proc_macro_derive(SerRon, attributes(nserde))] pub fn derive_ser_ron(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse::parse_data(input); @@ -76,6 +84,7 @@ pub fn derive_ser_ron(input: proc_macro::TokenStream) -> proc_macro::TokenStream ts } +#[cfg(feature = "ron")] #[proc_macro_derive(DeRon, attributes(nserde))] pub fn derive_de_ron(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse::parse_data(input); @@ -95,6 +104,7 @@ pub fn derive_de_ron(input: proc_macro::TokenStream) -> proc_macro::TokenStream ts } +#[cfg(feature = "json")] #[proc_macro_derive(SerJson, attributes(nserde))] pub fn derive_ser_json(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse::parse_data(input); @@ -114,6 +124,7 @@ pub fn derive_ser_json(input: proc_macro::TokenStream) -> proc_macro::TokenStrea ts } +#[cfg(feature = "json")] #[proc_macro_derive(DeJson, attributes(nserde))] pub fn derive_de_json(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse::parse_data(input); diff --git a/derive/src/parse.rs b/derive/src/parse.rs index 2ac4ee1..1122733 100644 --- a/derive/src/parse.rs +++ b/derive/src/parse.rs @@ -195,10 +195,12 @@ impl Generic { } } + #[cfg(any(feature = "binary", feature = "json"))] pub fn ident_only(&self) -> String { format!("{}{}", self.lifetime_prefix(), self.full()) } + #[cfg(any(feature = "binary", feature = "json"))] pub fn full_with_const(&self, extra_bounds: &[&str], bounds: bool) -> String { let bounds = match (bounds, &self) { (true, Generic::Lifetime { .. }) => self.get_bounds().join(" + "), @@ -412,6 +414,7 @@ impl Category { } impl Type { + #[cfg(any(feature = "ron", feature = "json"))] pub fn base(&self) -> String { let mut base = match &self.ref_type { Some(inner) => match inner { diff --git a/derive/src/shared.rs b/derive/src/shared.rs index aa4948e..110f814 100644 --- a/derive/src/shared.rs +++ b/derive/src/shared.rs @@ -1,5 +1,6 @@ use alloc::string::String; +#[cfg(any(feature = "binary", feature = "json"))] use crate::parse::{Enum, Struct}; macro_rules! l { @@ -22,6 +23,7 @@ pub fn attrs_proxy(attributes: &[crate::parse::Attribute]) -> Option { }) } +#[cfg(any(feature = "ron", feature = "json"))] pub fn attrs_rename(attributes: &[crate::parse::Attribute]) -> Option { attributes.iter().find_map(|attr| { if attr.tokens.len() == 2 && attr.tokens[0] == "rename" { @@ -32,6 +34,7 @@ pub fn attrs_rename(attributes: &[crate::parse::Attribute]) -> Option { }) } +#[cfg(any(feature = "ron", feature = "json"))] pub fn attrs_default(attributes: &[crate::parse::Attribute]) -> Option> { attributes.iter().find_map(|attr| { if attr.tokens.len() == 1 && attr.tokens[0] == "default" { @@ -44,6 +47,7 @@ pub fn attrs_default(attributes: &[crate::parse::Attribute]) -> Option Option { attributes.iter().find_map(|attr| { if attr.tokens.len() == 2 && attr.tokens[0] == "default_with" { @@ -54,18 +58,21 @@ pub fn attrs_default_with(attributes: &[crate::parse::Attribute]) -> Option bool { attributes .iter() .any(|attr| attr.tokens.len() == 1 && attr.tokens[0] == "transparent") } +#[cfg(feature = "json")] pub fn attrs_skip(attributes: &[crate::parse::Attribute]) -> bool { attributes .iter() .any(|attr| attr.tokens.len() == 1 && attr.tokens[0] == "skip") } +#[cfg(any(feature = "binary", feature = "json"))] pub(crate) fn struct_bounds_strings(struct_: &Struct, bound_name: &str) -> (String, String) { let generics: &Vec<_> = &struct_.generics; @@ -90,6 +97,7 @@ pub(crate) fn struct_bounds_strings(struct_: &Struct, bound_name: &str) -> (Stri return (generic_w_bounds, generic_no_bounds); } +#[cfg(any(feature = "binary", feature = "json"))] pub(crate) fn enum_bounds_strings(enum_: &Enum, bound_name: &str) -> (String, String) { let generics: &Vec<_> = &enum_.generics; diff --git a/src/lib.rs b/src/lib.rs index 3a65515..8384509 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,8 +7,6 @@ //! //! Data serialization library with zero dependencies. No more syn/proc_macro2/quote in the build tree! //! -//! `nanoserde` also almost do not use any generics, so build size is not going to be bloated with monomorphizated code. -//! //! The main difference with "serde" and the reason why "nanoserde" is possible: there is no intermediate data model //! For each serialisation datatype there is a special macro. //! @@ -20,20 +18,30 @@ #![cfg_attr(feature = "no_std", no_std)] // Possibly stable in 1.65. // See: https://github.com/rust-lang/rust/pull/99917 +// and https://github.com/rust-lang/rust/issues/103765 #![cfg_attr(feature = "no_std", feature(error_in_core))] extern crate alloc; +#[cfg(any(feature = "binary", feature = "json", feature = "ron"))] pub use nanoserde_derive::*; +#[cfg(feature = "binary")] mod serde_bin; +#[cfg(feature = "binary")] pub use crate::serde_bin::*; +#[cfg(feature = "ron")] mod serde_ron; +#[cfg(feature = "ron")] pub use crate::serde_ron::*; +#[cfg(feature = "json")] mod serde_json; +#[cfg(feature = "json")] pub use crate::serde_json::*; +#[cfg(feature = "toml")] mod toml; +#[cfg(feature = "toml")] pub use crate::toml::*; diff --git a/tests/bin.rs b/tests/bin.rs index 355c020..27be065 100644 --- a/tests/bin.rs +++ b/tests/bin.rs @@ -1,3 +1,4 @@ +#![cfg(feature = "binary")] use std::{ array, collections::{BTreeSet, LinkedList}, @@ -6,7 +7,6 @@ use std::{ #[cfg(feature = "no_std")] use hashbrown::{HashMap, HashSet}; - #[cfg(not(feature = "no_std"))] use std::collections::{HashMap, HashSet}; diff --git a/tests/json.rs b/tests/json.rs index 21e3e45..5275b6f 100644 --- a/tests/json.rs +++ b/tests/json.rs @@ -1,3 +1,4 @@ +#![cfg(feature = "json")] use nanoserde::{DeJson, SerJson}; use std::{ diff --git a/tests/parse.rs b/tests/parse.rs index 1f75dc9..76b3808 100644 --- a/tests/parse.rs +++ b/tests/parse.rs @@ -1,3 +1,4 @@ +#![cfg(all(feature = "binary", feature = "json", feature = "ron"))] use nanoserde::{DeBin, DeJson, DeRon, SerBin, SerJson, SerRon}; // https://github.com/not-fl3/nanoserde/issues/83 diff --git a/tests/ron.rs b/tests/ron.rs index 728e768..856a978 100644 --- a/tests/ron.rs +++ b/tests/ron.rs @@ -1,3 +1,4 @@ +#![cfg(feature = "ron")] use nanoserde::{DeRon, SerRon}; use std::{ diff --git a/tests/ser_de.rs b/tests/ser_de.rs index eca1293..4c37964 100644 --- a/tests/ser_de.rs +++ b/tests/ser_de.rs @@ -1,4 +1,10 @@ -use nanoserde::{DeBin, DeJson, DeRon, SerBin, SerJson, SerRon}; +#![cfg(any(feature = "binary", feature = "json", feature = "ron"))] +#[cfg(feature = "binary")] +use nanoserde::{DeBin, SerBin}; +#[cfg(feature = "json")] +use nanoserde::{DeJson, SerJson}; +#[cfg(feature = "ron")] +use nanoserde::{DeRon, SerRon}; #[cfg(feature = "no_std")] use hashbrown::HashMap; @@ -8,7 +14,10 @@ use std::collections::HashMap; #[test] fn ser_de() { - #[derive(DeBin, SerBin, DeJson, SerJson, DeRon, SerRon, PartialEq, Debug)] + #[derive(PartialEq, Debug)] + #[cfg_attr(feature = "binary", derive(DeBin, SerBin))] + #[cfg_attr(feature = "json", derive(DeJson, SerJson))] + #[cfg_attr(feature = "ron", derive(DeRon, SerRon))] pub struct Test { pub a: i32, pub b: f32, @@ -32,15 +41,24 @@ fn ser_de() { g: (), }; - let bytes = SerBin::serialize_bin(&test); - let test_deserialized = DeBin::deserialize_bin(&bytes).unwrap(); - assert_eq!(test, test_deserialized); + #[cfg(feature = "binary")] + { + let bytes = SerBin::serialize_bin(&test); + let test_deserialized = DeBin::deserialize_bin(&bytes).unwrap(); + assert_eq!(test, test_deserialized); + } - let bytes = SerJson::serialize_json(&test); - let test_deserialized = DeJson::deserialize_json(&bytes).unwrap(); - assert_eq!(test, test_deserialized); + #[cfg(feature = "json")] + { + let bytes = SerJson::serialize_json(&test); + let test_deserialized = DeJson::deserialize_json(&bytes).unwrap(); + assert_eq!(test, test_deserialized); + } - let bytes = SerRon::serialize_ron(&test); - let test_deserialized = DeRon::deserialize_ron(&bytes).unwrap(); - assert_eq!(test, test_deserialized); + #[cfg(feature = "ron")] + { + let bytes = SerRon::serialize_ron(&test); + let test_deserialized = DeRon::deserialize_ron(&bytes).unwrap(); + assert_eq!(test, test_deserialized); + } } diff --git a/tests/toml.rs b/tests/toml.rs index 4b1c821..c7c3c39 100644 --- a/tests/toml.rs +++ b/tests/toml.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "toml")] + #[cfg(feature = "no_std")] use hashbrown::HashMap; #[cfg(not(feature = "no_std"))]