diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 4254c4d..628ec96 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -22,6 +22,11 @@ jobs:
run: cargo test --no-default-features --verbose
- name: Run tests for serde
run: cargo test --features serde --verbose
+ - run: cargo test --no-default-features --features serde_no_std
+ - run: cargo test --features borsh
+ - run: cargo test --features miniserde
+ - run: cargo test --features nanoserde
+ - run: cargo test --features nanoserde --no-default-features
miri:
name: "Miri"
@@ -62,7 +67,27 @@ jobs:
- run: cargo build
- run: cargo test
- run: cargo test --no-default-features
+ - run: cargo test --no-default-features --features serde_no_std
- run: cargo test --features serde
+ - run: cargo test --features miniserde
+
+ msrv-borsh:
+ name: Rust ${{matrix.rust}}
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ rust: [1.67.0, 1.68.0]
+ timeout-minutes: 45
+ steps:
+ - uses: actions/checkout@v4
+ - uses: dtolnay/rust-toolchain@master
+ with:
+ toolchain: ${{matrix.rust}}
+ - run: cargo test
+ - run: cargo test --features borsh
+ - run: cargo test --features nanoserde
+ - run: cargo test --features nanoserde --no-default-features
clippy:
runs-on: ubuntu-latest
diff --git a/Cargo.toml b/Cargo.toml
index b7bdd17..05fbd36 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,10 @@ edition = "2021"
rust-version = "1.63"
[dependencies]
-serde = { version = "1.0", features = ["derive"], optional = true }
+borsh = { version = "1.5", default-features = false, features = ["derive"], optional = true }
+serde = { version = "1.0", default-features = false, features = ["derive"], optional = true }
+miniserde = { version = "0.1", optional = true }
+nanoserde = { version = "0.1", optional = true }
[dependencies.bit-vec]
version = "0.8.0"
@@ -26,4 +29,15 @@ serde_json = "1.0"
[features]
default = ["std"]
std = ["bit-vec/std"]
+
+borsh = ["dep:borsh", "bit-vec/borsh"]
serde = ["dep:serde", "bit-vec/serde"]
+miniserde = ["dep:miniserde", "bit-vec/miniserde"]
+nanoserde = ["dep:nanoserde", "bit-vec/nanoserde"]
+
+serde_std = ["std", "serde/std"]
+serde_no_std = ["serde/alloc"]
+borsh_std = ["borsh/std"]
+
+[package.metadata.docs.rs]
+features = ["borsh", "serde", "miniserde", "nanoserde"]
diff --git a/README.md b/README.md
index 3fa4e26..d7e96a9 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,8 @@
[![Documentation][docs.rs badge]][docs.rs link]
![Rust CI][github ci badge]
![rustc 1.63+]
+![borsh: rustc 1.67+]
+![nanoserde: rustc 1.67+]
[![Dependency Status][deps.rs status]][deps.rs link]
@@ -23,6 +25,8 @@
[docs.rs link]: https://docs.rs/bit-set/0.8.0/bit_set/
[github ci badge]: https://github.com/contain-rs/bit-set/workflows/Rust/badge.svg?branch=master
[rustc 1.63+]: https://img.shields.io/badge/rustc-1.63%2B-blue.svg
+[borsh: rustc 1.67+]: https://img.shields.io/badge/borsh:%20rustc-1.67%2B-blue.svg
+[nanoserde: rustc 1.67+]: https://img.shields.io/badge/nanoserde:%20rustc-1.67%2B-blue.svg
[deps.rs status]: https://deps.rs/crate/bit-set/0.8.0/status.svg
[deps.rs link]: https://deps.rs/crate/bit-set/0.8.0
[shields.io download count]: https://img.shields.io/crates/d/bit-set.svg
@@ -57,6 +61,25 @@ If you want to use bit-set in a program that has `#![no_std]`, just drop default
bit-set = { version = "0.8", default-features = false }
```
+If you want to use serde with the alloc crate instead of std, just use the `serde_no_std` feature:
+
+```toml
+[dependencies]
+bit-set = { version = "0.8", default-features = false, features = ["serde", "serde_no_std"] }
+```
+
+If you want [borsh-rs](https://github.com/near/borsh-rs) support, include it like this:
+
+```toml
+[dependencies]
+bit-set = { version = "0.8", features = ["borsh"] }
+```
+
+Other available serialization libraries can be enabled with the
+[`miniserde`](https://github.com/dtolnay/miniserde) and
+[`nanoserde`](https://github.com/not-fl3/nanoserde) features.
+
+
### Description
diff --git a/src/lib.rs b/src/lib.rs
index 5bdf9a8..899b9dd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -64,6 +64,13 @@ use core::fmt;
use core::hash;
use core::iter::{self, Chain, Enumerate, FromIterator, Repeat, Skip, Take};
+#[cfg(feature = "nanoserde")]
+extern crate alloc;
+#[cfg(feature = "nanoserde")]
+use alloc::vec::Vec;
+#[cfg(feature = "nanoserde")]
+use nanoserde::{DeBin, DeJson, DeRon, SerBin, SerJson, SerRon};
+
type MatchWords<'a, B> = Chain>, Skip>>>>;
/// Computes how many blocks are needed to store that many bits
@@ -116,6 +123,18 @@ fn match_words<'a, 'b, B: BitBlock>(
}
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
+#[cfg_attr(
+ feature = "borsh",
+ derive(borsh::BorshDeserialize, borsh::BorshSerialize)
+)]
+#[cfg_attr(
+ feature = "miniserde",
+ derive(miniserde::Deserialize, miniserde::Serialize)
+)]
+#[cfg_attr(
+ feature = "nanoserde",
+ derive(DeBin, DeJson, DeRon, SerBin, SerJson, SerRon)
+)]
pub struct BitSet {
bit_vec: BitVec,
}
@@ -1599,20 +1618,20 @@ mod tests {
s.truncate(5 * 8);
assert_eq!(s, BitSet::from_bytes(&bytes[..5]));
- assert_eq!(s.len(), 5 * 8);
+ assert_eq!(s.count(), 5 * 8);
s.truncate(4 * 8);
assert_eq!(s, BitSet::from_bytes(&bytes[..4]));
- assert_eq!(s.len(), 4 * 8);
+ assert_eq!(s.count(), 4 * 8);
// Truncating to a size > s.len() should be a noop
s.truncate(5 * 8);
assert_eq!(s, BitSet::from_bytes(&bytes[..4]));
- assert_eq!(s.len(), 4 * 8);
+ assert_eq!(s.count(), 4 * 8);
s.truncate(8);
assert_eq!(s, BitSet::from_bytes(&bytes[..1]));
- assert_eq!(s.len(), 8);
+ assert_eq!(s.count(), 8);
s.truncate(0);
assert_eq!(s, BitSet::from_bytes(&[]));
- assert_eq!(s.len(), 0);
+ assert_eq!(s.count(), 0);
}
#[cfg(feature = "serde")]
@@ -1630,6 +1649,53 @@ mod tests {
assert_eq!(bset, unserialized);
}
+ #[cfg(feature = "miniserde")]
+ #[test]
+ fn test_miniserde_serialization() {
+ let bset: BitSet = BitSet::new();
+ let serialized = miniserde::json::to_string(&bset);
+ let unserialized: BitSet = miniserde::json::from_str(&serialized[..]).unwrap();
+ assert_eq!(bset, unserialized);
+
+ let elems: Vec = vec![11, 42, 100, 101];
+ let bset: BitSet = elems.iter().map(|n| *n).collect();
+ let serialized = miniserde::json::to_string(&bset);
+ let unserialized = miniserde::json::from_str(&serialized[..]).unwrap();
+ assert_eq!(bset, unserialized);
+ }
+
+ #[cfg(feature = "nanoserde")]
+ #[test]
+ fn test_nanoserde_json_serialization() {
+ use nanoserde::{DeJson, SerJson};
+
+ let bset: BitSet = BitSet::new();
+ let serialized = bset.serialize_json();
+ let unserialized: BitSet = BitSet::deserialize_json(&serialized[..]).unwrap();
+ assert_eq!(bset, unserialized);
+
+ let elems: Vec = vec![11, 42, 100, 101];
+ let bset: BitSet = elems.iter().map(|n| *n).collect();
+ let serialized = bset.serialize_json();
+ let unserialized = BitSet::deserialize_json(&serialized[..]).unwrap();
+ assert_eq!(bset, unserialized);
+ }
+
+ #[cfg(feature = "borsh")]
+ #[test]
+ fn test_borsh_serialization() {
+ let bset: BitSet = BitSet::new();
+ let serialized = borsh::to_vec(&bset).unwrap();
+ let unserialized: BitSet = borsh::from_slice(&serialized[..]).unwrap();
+ assert_eq!(bset, unserialized);
+
+ let elems: Vec = vec![11, 42, 100, 101];
+ let bset: BitSet = elems.iter().map(|n| *n).collect();
+ let serialized = borsh::to_vec(&bset).unwrap();
+ let unserialized = borsh::from_slice(&serialized[..]).unwrap();
+ assert_eq!(bset, unserialized);
+ }
+
/*
#[test]
fn test_bit_set_append() {