diff --git a/Cargo.lock b/Cargo.lock index abfac8f..18a194d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,7 @@ dependencies = [ "bincode", "bitcode_derive", "bytemuck", + "compact_str", "flate2", "glam", "lz4_flex", @@ -68,6 +69,15 @@ version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +[[package]] +name = "castaway" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" +dependencies = [ + "rustversion", +] + [[package]] name = "cc" version = "1.2.51" @@ -86,6 +96,20 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "compact_str" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "static_assertions", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -152,6 +176,12 @@ dependencies = [ "rand", ] +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + [[package]] name = "jobserver" version = "0.1.34" @@ -290,6 +320,18 @@ dependencies = [ "num-traits", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + [[package]] name = "serde" version = "1.0.228" @@ -332,6 +374,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "syn" version = "2.0.114" diff --git a/Cargo.toml b/Cargo.toml index 46cc43e..7299ce1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ exclude = ["fuzz/"] arrayvec = { version = "0.7", default-features = false, optional = true } bitcode_derive = { version = "=0.6.9", path = "./bitcode_derive", optional = true } bytemuck = { version = "1.14", features = [ "min_const_generics", "must_cast" ] } +compact_str = { version = "0.9.0", optional = true } glam = { version = ">=0.21", default-features = false, optional = true } rust_decimal = { version = "1.36", default-features = false, optional = true } serde = { version = "1.0", default-features = false, features = [ "alloc" ], optional = true } diff --git a/src/ext/compact_str.rs b/src/ext/compact_str.rs new file mode 100644 index 0000000..0bdc874 --- /dev/null +++ b/src/ext/compact_str.rs @@ -0,0 +1,62 @@ +use crate::coder::{Decoder, Encoder}; +use crate::derive::{Decode, Encode}; +use crate::str::{StrDecoder, StrEncoder}; +use compact_str::CompactString; + +impl Encoder for StrEncoder { + #[inline(always)] + fn encode(&mut self, t: &CompactString) { + self.encode(t.as_str()) + } +} + +impl Encode for CompactString { + type Encoder = StrEncoder; +} + +impl<'a> Decoder<'a, CompactString> for StrDecoder<'a> { + #[inline(always)] + fn decode(&mut self) -> CompactString { + let s: &str = self.decode(); + s.into() + } +} + +impl<'a> Decode<'a> for CompactString { + type Decoder = StrDecoder<'a>; +} + +#[cfg(test)] +mod tests { + use crate::{decode, encode}; + use alloc::vec::Vec; + use compact_str::CompactString; + + #[test] + fn compact_string() { + let mut v = CompactString::default(); + v.push('0'); + v.push('1'); + let b = encode(&v); + assert_eq!(decode::(&b).unwrap(), v); + } + + #[test] + fn compact_string_long() { + // CompactString inlines up to 23 bytes on 64-bit platforms; the English alphabet exceeds that at 26 bytes. + let v = CompactString::new("abcdefghijklmnopqrstuvwxyz"); + let b = encode(&v); + assert_eq!(decode::(&b).unwrap(), v); + } + + #[test] + fn compact_string_vec() { + let v = vec![ + CompactString::new("01"), + CompactString::new("abcdefghijklmnopqrstuvwxyz"), + ]; + let b = encode(&v); + let v2 = decode::>(&b).unwrap(); + assert_eq!(v, v2); + } +} diff --git a/src/ext/mod.rs b/src/ext/mod.rs index 869e0b8..6c7ce92 100644 --- a/src/ext/mod.rs +++ b/src/ext/mod.rs @@ -1,5 +1,7 @@ #[cfg(feature = "arrayvec")] mod arrayvec; +#[cfg(feature = "compact_str")] +mod compact_str; #[cfg(feature = "glam")] #[rustfmt::skip] // Makes impl_struct! calls way longer. mod glam;