Skip to content

Commit

Permalink
Add support for bitvec/bitset 0.8
Browse files Browse the repository at this point in the history
  • Loading branch information
avl committed Aug 20, 2024
1 parent 6acafbb commit 8cb263d
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 11 deletions.
27 changes: 22 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions savefile-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ nightly=["savefile/nightly"]
savefile = { path = "../savefile", features = ["size_sanity_checks", "encryption", "compression","bit-set","bit-vec","rustc-hash","serde_derive", "quickcheck"]}
savefile-derive = { path = "../savefile-derive", version = "=0.17.7" }
savefile-abi = { path = "../savefile-abi" }
bit-vec = "0.6"
bit-vec = "0.8"
arrayvec="0.7"
smallvec="*"
indexmap = { version = "1.9"}
Expand All @@ -24,7 +24,7 @@ parking_lot="0.12"
serde="*"
serde_derive="*"
bincode="1.2.1"
bit-set="0.5"
bit-set="0.8"
rustc-hash="1.1"
quickcheck="1.0"
quickcheck_macros ="1.0"
Expand Down
9 changes: 6 additions & 3 deletions savefile/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ license = "MIT/Apache-2.0"
edition = "2021"

[features]
default = ["indexmap", "arrayvec", "smallvec", "bit-vec", "parking_lot","bit-set"]
bit-set = ["dep:bit-set","bit-vec"]
serde_derive = ["dep:serde_derive","serde"]
default = ["indexmap", "arrayvec", "smallvec", "bit-vec", "parking_lot","bit-set", "bit-set08", "bit-vec08"]
bit-set = ["dep:bit-set", "bit-vec"]
bit-set08 = ["dep:bit-set08", "bit-vec08"]
serde_derive = ["dep:serde_derive", "serde"]

# Enable this to reduce risk of crashing on corrupt input. Provides sanity checks for sizes of objects.
# This is mostly to be able to run fuzzers against the deserializers without them being guaranteed to easily find out-of-memory crashes.
Expand All @@ -48,6 +49,7 @@ derive = ["dep:savefile-derive"]

[dependencies]
bit-vec = { version = "0.6", optional = true}
bit-vec08 = { package="bit-vec", version = "0.8", optional = true}
arrayvec = { version = "0.7", optional = true}
smallvec = { version = "1.11", optional = true}
indexmap = { version = "1.9", optional = true}
Expand All @@ -56,6 +58,7 @@ ring = {version = "0.16.9", optional = true}
rand = { version = "0.8", optional = true}
bzip2 = {version = "0.4.4", optional = true}
bit-set = {version = "0.5", optional = true}
bit-set08 = {package="bit-set", version = "0.8", optional = true}
rustc-hash = {version = "1.1", optional = true}
memoffset = "0.9"
byteorder = "1.4"
Expand Down
189 changes: 188 additions & 1 deletion savefile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,8 @@ pub trait Packed {
}

/// This just exists to make sure that no one can actually implement the ReprC-trait placeholder.
/// If you somehow end up here, what you really want is to find instances of ReprC and change them
/// to Packed.
#[doc(hidden)]
#[deprecated(since = "0.17", note = "The 'ReprC' trait has been renamed to 'Packed'.")]
pub struct DeliberatelyUnimplementable {
Expand Down Expand Up @@ -5327,7 +5329,7 @@ impl<T: Deserialize, R: Deserialize> Deserialize for Result<T, R> {
}
}

#[cfg(feature = "bit-vec")]
#[cfg(any(feature = "bit-vec", feature="bit-vec08"))]
#[cfg(target_endian = "big")]
compile_error!("savefile bit-vec feature does not support big-endian machines");

Expand Down Expand Up @@ -5497,6 +5499,180 @@ impl Deserialize for bit_set::BitSet<u32> {
}
}





#[cfg(feature = "bit-vec08")]
impl WithSchema for bit_vec08::BitVec {
fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
Schema::Struct(SchemaStruct {
dbg_name: "BitVec".to_string(),
size: None,
alignment: None,
fields: vec![
Field {
name: "num_bits".to_string(),
value: Box::new(usize::schema(version, context)),
offset: None,
},
Field {
name: "num_bytes".to_string(),
value: Box::new(usize::schema(version, context)),
offset: None,
},
Field {
name: "buffer".to_string(),
value: Box::new(Schema::Vector(
Box::new(u8::schema(version, context)),
VecOrStringLayout::Unknown,
)),
offset: None,
},
],
})
}
}

#[cfg(feature = "bit-vec08")]
impl Introspect for bit_vec08::BitVec {
fn introspect_value(&self) -> String {
let mut ret = String::new();
for i in 0..self.len() {
if self[i] {
ret.push('1');
} else {
ret.push('0');
}
}
ret
}

fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
None
}
}

#[cfg(feature = "bit-vec08")]
impl Serialize for bit_vec08::BitVec<u32> {
fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
let l = self.len();
serializer.write_usize(l)?;
let storage = self.storage();
let rawbytes_ptr = storage.as_ptr() as *const u8;
let rawbytes: &[u8] = unsafe { std::slice::from_raw_parts(rawbytes_ptr, 4 * storage.len()) };
serializer.write_usize(rawbytes.len() | (1 << 63))?;
serializer.write_bytes(rawbytes)?;
Ok(())
}
}

#[cfg(feature = "bit-vec08")]
impl Packed for bit_vec08::BitVec<u32> {}

#[cfg(feature = "bit-vec08")]
impl Deserialize for bit_vec08::BitVec<u32> {
fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
let numbits = deserializer.read_usize()?;
let mut numbytes = deserializer.read_usize()?;
if numbytes & (1 << 63) != 0 {
//New format
numbytes &= !(1 << 63);
let mut ret = bit_vec08::BitVec::with_capacity(numbytes * 8);
unsafe {
let num_words = numbytes / 4;
let storage = ret.storage_mut();
storage.resize(num_words, 0);
let storage_ptr = storage.as_ptr() as *mut u8;
let storage_bytes: &mut [u8] = std::slice::from_raw_parts_mut(storage_ptr, 4 * num_words);
deserializer.read_bytes_to_buf(storage_bytes)?;
ret.set_len(numbits);
}
Ok(ret)
} else {
let bytes = deserializer.read_bytes(numbytes)?;
let mut ret = bit_vec08::BitVec::from_bytes(&bytes);
ret.truncate(numbits);
Ok(ret)
}
}
}

#[cfg(feature = "bit-set")]
impl WithSchema for bit_set08::BitSet {
fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
Schema::Struct(SchemaStruct {
dbg_name: "BitSet".to_string(),
size: None,
alignment: None,
fields: vec![
Field {
name: "num_bits".to_string(),
value: Box::new(usize::schema(version, context)),
offset: None,
},
Field {
name: "num_bytes".to_string(),
value: Box::new(usize::schema(version, context)),
offset: None,
},
Field {
name: "buffer".to_string(),
value: Box::new(Schema::Vector(
Box::new(u8::schema(version, context)),
VecOrStringLayout::Unknown,
)),
offset: None,
},
],
})
}
}

#[cfg(feature = "bit-set08")]
impl Introspect for bit_set08::BitSet {
fn introspect_value(&self) -> String {
let mut ret = String::new();
for i in 0..self.len() {
if self.contains(i) {
use std::fmt::Write;
if !ret.is_empty() {
ret += " ";
}
write!(&mut ret, "{}", i).unwrap();
}
}
ret
}

fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
None
}
}

#[cfg(feature = "bit-set08")]
impl Packed for bit_set08::BitSet<u32> {}

#[cfg(feature = "bit-set08")]
impl Serialize for bit_set08::BitSet<u32> {
fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
let bitset = self.get_ref();
bitset.serialize(serializer)
}
}

#[cfg(feature = "bit-set")]
impl Deserialize for bit_set08::BitSet<u32> {
fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
let bit_vec: bit_vec08::BitVec = bit_vec08::BitVec::deserialize(deserializer)?;
Ok(bit_set08::BitSet::from_bit_vec(bit_vec))
}
}





impl<T: Introspect> Introspect for BinaryHeap<T> {
fn introspect_value(&self) -> String {
"BinaryHeap".to_string()
Expand Down Expand Up @@ -7535,6 +7711,17 @@ impl Serialize for SystemTime {
Ok(())
}
}

impl Introspect for std::time::Instant {
fn introspect_value(&self) -> String {
format!("{:?}", self)
}
fn introspect_child<'a>(&'a self, _index: usize) -> Option<Box<dyn IntrospectItem<'a> + 'a>> {
None
}
}


fn u128_duration_nanos(nanos: u128) -> Duration {
if nanos > u64::MAX as u128 {
Duration::from_nanos((nanos % 1_000_000_000) as u64) + Duration::from_secs((nanos/1_000_000_000) as u64)
Expand Down

0 comments on commit 8cb263d

Please sign in to comment.