Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ cachegrind*
callgrind*
dhat*
massif*

fuzz/coverage/
8 changes: 7 additions & 1 deletion fuzz/fuzz_targets/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,18 @@ fn prop_identity(inline_array: &InlineArray) -> bool {
let buf: &[u8] = inline_array.as_ref();
assert_eq!(buf.as_ptr() as usize % 8, 0);

let ptr = iv2.into_raw();
let ptr = iv2.clone().into_raw();
let rt = unsafe { InlineArray::from_raw(ptr) };
assert_eq!(&rt, inline_array);

if inline_array.is_empty() {
assert_eq!(inline_array, &inline_array::EMPTY);
} else {
iv2.make_mut()[0] = iv2[0].wrapping_add(1);
if iv2 == inline_array {
println!("Mutating clone shouldn't mutate origin");
return false;
}
}

true
Expand Down
40 changes: 34 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ impl Clone for InlineArray {
loop {
let current = rc.load(Ordering::Relaxed);
if current == u8::MAX {
return InlineArray::from(self.deref());
let body: &[u8] = self.as_ref();
return InlineArray::from(body);
}

let cas_res = rc.compare_exchange_weak(
Expand All @@ -157,7 +158,8 @@ impl Clone for InlineArray {
loop {
let current = rc.load(Ordering::Relaxed);
if current == u16::MAX {
return InlineArray::from(self.deref());
let body: &[u8] = self.as_ref();
return InlineArray::from(body);
}

let cas_res = rc.compare_exchange_weak(
Expand Down Expand Up @@ -301,7 +303,7 @@ impl Default for InlineArray {

impl Hash for InlineArray {
fn hash<H: Hasher>(&self, state: &mut H) {
self.deref().hash(state);
self.as_ref().hash(state)
}
}

Expand Down Expand Up @@ -443,7 +445,7 @@ impl InlineArray {
/// This function returns a mutable reference to the inner
/// byte array. If there are more than 1 atomic references
/// to the inner array, the array is copied into a new
/// `InlineVec` and a reference to that is returned. This
/// `InlineArray` and a reference to that is returned. This
/// functions similarly in spirit to [`std::sync::Arc::make_mut`].
pub fn make_mut(&mut self) -> &mut [u8] {
match self.kind() {
Expand All @@ -453,7 +455,8 @@ impl InlineArray {
}
Kind::SmallRemote => {
if self.deref_small_trailer().rc.load(Ordering::Acquire) != 1 {
*self = InlineArray::from(self.deref())
let body: &[u8] = self.as_ref();
*self = InlineArray::from(body)
}
unsafe {
let len = self.deref_small_trailer().len();
Expand All @@ -464,7 +467,8 @@ impl InlineArray {
}
Kind::BigRemote => {
if self.deref_big_header().rc.load(Ordering::Acquire) != 1 {
*self = InlineArray::from(self.deref())
let body: &[u8] = self.as_ref();
*self = InlineArray::from(body)
}
unsafe {
let data_ptr = self.remote_ptr().add(size_of::<BigRemoteHeader>());
Expand Down Expand Up @@ -662,6 +666,8 @@ impl fmt::Debug for InlineArray {
#[cfg(test)]
mod tests {

use crate::{INLINE_CUTOFF, SMALL_REMOTE_CUTOFF};

use super::InlineArray;

#[test]
Expand Down Expand Up @@ -700,6 +706,20 @@ mod tests {
assert_eq!(initial, iv.make_mut());
}

#[test]
fn mutate_clone() {
for len in [
INLINE_CUTOFF - 1,
SMALL_REMOTE_CUTOFF - 1,
SMALL_REMOTE_CUTOFF + 1,
] {
let origin = InlineArray::from(vec![0_u8; len]);
let mut target = origin.clone();
target.make_mut()[0] = 1;
assert_ne!(origin, target);
}
}

fn prop_identity(inline_array: &InlineArray) -> bool {
let mut iv2 = inline_array.clone();

Expand All @@ -721,6 +741,14 @@ mod tests {
let buf: &[u8] = inline_array.as_ref();
assert_eq!(buf.as_ptr() as usize % 8, 0);

if !inline_array.is_empty() {
iv2.make_mut()[0] = iv2[0].wrapping_add(1);
if iv2 == inline_array {
println!("Mutating clone shouldn't mutate origin");
return false;
}
}

true
}

Expand Down