Skip to content

Commit

Permalink
add as_contiguous to Slice (#39)
Browse files Browse the repository at this point in the history
* add as_contiguous to slice

* relax as_contiguous returned lifetime
  • Loading branch information
vxpm authored Nov 23, 2023
1 parent fd5bf7b commit a9f31ff
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,25 @@ impl<'a, T: 'a> Slice<'a, T> {
len: end - start,
}
}

/// Tries to treat this SegVec [`Slice`] as a contiguous [`slice`]. This only
/// succeeds if all the elements of this [`Slice`] are in the same segment.
pub fn as_contiguous(&self) -> Option<&'a [T]> {
let (start_segment, start_offset) = self.inner.segment_and_offset(self.start);

if self.len == 0 {
// this could just return Some(&[]), but the address of the slice
// would be dangling - not sure if this matters much...
let segment = unsafe { self.inner.segment_unchecked(start_segment) };
return Some(&segment[start_offset..start_offset]);
}

let (end_segment, end_offset) = self.inner.segment_and_offset(self.start + self.len - 1);
(start_segment == end_segment).then(|| {
let segment = unsafe { self.inner.segment_unchecked(start_segment) };
&segment[start_offset..end_offset + 1]
})
}
}

impl<'a, T: 'a> Index<usize> for Slice<'a, T> {
Expand Down
33 changes: 33 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -768,3 +768,36 @@ fn test_not_thin_segments_feature() {
let _: detail::Segment<()> = Vec::new();
}

#[test]
fn test_slice_as_contiguous() {
let mut sv: SegVec<i32, Linear<4>> = SegVec::with_capacity(4);

// first segment
sv.push(0);
sv.push(1);
sv.push(2);
sv.push(3);

// second segment
sv.push(4);
sv.push(5);
sv.push(6);
sv.push(7);

assert_eq!(sv.slice(2..2).as_contiguous(), Some([].as_slice()));

assert_eq!(
sv.slice(0..4).as_contiguous(),
Some([0, 1, 2, 3].as_slice())
);
assert_eq!(sv.slice(1..3).as_contiguous(), Some([1, 2].as_slice()));

assert!(sv.slice(0..5).as_contiguous().is_none());
assert!(sv.slice(3..8).as_contiguous().is_none());

assert_eq!(
sv.slice(4..8).as_contiguous(),
Some([4, 5, 6, 7].as_slice())
);
assert_eq!(sv.slice(5..7).as_contiguous(), Some([5, 6].as_slice()));
}

0 comments on commit a9f31ff

Please sign in to comment.