Compare commits
No commits in common. "cf7216939b9dab5d29689a6188e054a963c2e37d" and "50bca2ae8676c3162677460a9eb935dc3a6334e5" have entirely different histories.
cf7216939b
...
50bca2ae86
|
@ -1,2 +1 @@
|
||||||
/target
|
/target
|
||||||
Cargo.lock
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "nslice"
|
||||||
|
version = "0.1.0"
|
|
@ -1,15 +1,10 @@
|
||||||
[package]
|
[package]
|
||||||
name = "nslice"
|
name = "nslice"
|
||||||
version = "0.2.0"
|
version = "0.1.0"
|
||||||
authors = ["Leonora Tindall <nora@nora.codes>"]
|
authors = ["Leonora Tindall <nora@nora.codes>"]
|
||||||
edition = "2021"
|
edition = "2018"
|
||||||
description = "Structures for interpreting slices of variable length as arrays"
|
description = "Structures for interpreting slices of variable length as arrays"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
keywords = ["memory", "slice", "array"]
|
keywords = ["memory", "slice", "array"]
|
||||||
categories = ["data-structures"]
|
categories = ["data-structures"]
|
||||||
repository = "https://git.nora.codes/nora/nslice"
|
repository = "https://git.nora.codes/nora/nslice"
|
||||||
|
|
||||||
|
|
||||||
[features]
|
|
||||||
nightly = []
|
|
||||||
default = ["nightly"]
|
|
25
README.md
25
README.md
|
@ -1,25 +0,0 @@
|
||||||
# nslice
|
|
||||||
|
|
||||||
Structures for interpreting slices of variable length as arrays.
|
|
||||||
|
|
||||||
`nslice` provides `MinSlice` and `ExactSlice` for representing slices known to have
|
|
||||||
either exactly or at least some compile-time-known number of values.
|
|
||||||
|
|
||||||
This is useful when dealing with a slice whose length you expect to be exactly
|
|
||||||
or at least some particular length;
|
|
||||||
rather than making runtime checks on each access,
|
|
||||||
you can check the length once and access values freely with no copying.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
# use nslice::MinSlice;
|
|
||||||
|
|
||||||
let slice = &[1, 2, 3, 4, 5, 6];
|
|
||||||
let minslice: &MinSlice<_, 3> = MinSlice::from_slice(slice).unwrap();
|
|
||||||
assert_eq!(minslice.tail.len(), 3);
|
|
||||||
assert_eq!(minslice.head[0], 1);
|
|
||||||
assert_eq!(minslice.tail[2], 6);
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This project is licensed MIT.
|
|
133
src/lib.rs
133
src/lib.rs
|
@ -1,4 +1,15 @@
|
||||||
#![doc=include_str!("../README.md")]
|
//! Structures for interpreting slices of variable length as arrays.
|
||||||
|
//!
|
||||||
|
//! `nslice` provides `MinSlice` and `ExactSlice` for representing slices known to have
|
||||||
|
//! either exactly or at least some compile-time-known number of values.
|
||||||
|
//! ```
|
||||||
|
//! use nslice::MinSlice;
|
||||||
|
//! let slice = &[1, 2, 3, 4, 5, 6];
|
||||||
|
//! let minslice: &MinSlice<_, 3> = MinSlice::from_slice(slice).unwrap();
|
||||||
|
//! assert_eq!(minslice.tail.len(), 3);
|
||||||
|
//! assert_eq!(minslice.head[0], 1);
|
||||||
|
//! assert_eq!(minslice.tail[2], 6);
|
||||||
|
//! ```
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
/// A reference to a region of memory which is known to contain `N` or more elements
|
/// A reference to a region of memory which is known to contain `N` or more elements
|
||||||
|
@ -8,16 +19,6 @@ use std::slice;
|
||||||
/// `MinSlice` is merely a way of reinterpreting an existing slice
|
/// `MinSlice` is merely a way of reinterpreting an existing slice
|
||||||
/// (`&[T]` or `&mut [T]`), and it is exactly the same size as a slice:
|
/// (`&[T]` or `&mut [T]`), and it is exactly the same size as a slice:
|
||||||
/// one pointer and one `usize`.
|
/// one pointer and one `usize`.
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use nslice::MinSlice;
|
|
||||||
/// let slice: &[u8] = b"Hello, world";
|
|
||||||
/// let minslice = MinSlice::<u8, 12>::from_slice(slice).unwrap();
|
|
||||||
/// let value: u8 = minslice.head[6];
|
|
||||||
/// assert_eq!(value, b' ')
|
|
||||||
/// ```
|
|
||||||
pub struct MinSlice<T, const N: usize> {
|
pub struct MinSlice<T, const N: usize> {
|
||||||
/// The bounded region of memory. Exactly `N` `T`s.
|
/// The bounded region of memory. Exactly `N` `T`s.
|
||||||
pub head: [T; N],
|
pub head: [T; N],
|
||||||
|
@ -46,7 +47,7 @@ impl<T, const N: usize> MinSlice<T, N> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce a `&mut MinSlice` from a mutable slice of `T`s.
|
/// Produce a `&mut MinSlice` from a mutable slice of `T`s.
|
||||||
/// Returns `None` if there are not enough elements in `slice`.
|
/// Returns `None` if there are not enough elements in `slice`.
|
||||||
pub fn from_mut(slice: &mut [T]) -> Option<&mut MinSlice<T, N>> {
|
pub fn from_mut(slice: &mut [T]) -> Option<&mut MinSlice<T, N>> {
|
||||||
|
@ -56,70 +57,6 @@ impl<T, const N: usize> MinSlice<T, N> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, const N: usize> MinSlice<T, N> {
|
|
||||||
/// Returns a slice over the memory referred to by the `MinSlice`.
|
|
||||||
/// Its length is guaranteed to be no less than `N`.
|
|
||||||
pub fn as_slice(&self) -> &[T] {
|
|
||||||
unsafe { slice::from_raw_parts(self.head.as_ptr(), N + self.tail.len()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a mutable slice over the memory referred to by the `MinSlice`.
|
|
||||||
/// Its length is guaranteed to be no less than `N`.
|
|
||||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
|
||||||
unsafe { slice::from_raw_parts_mut(self.head.as_mut_ptr(), N + self.tail.len()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resize the `MinSlice`, returning a new `Some(&MinSlice<T, M>)`
|
|
||||||
/// if there are at least `M` `T`s in `self`.
|
|
||||||
pub fn resize<const M: usize>(&self) -> Option<&MinSlice<T, M>> {
|
|
||||||
MinSlice::<T, M>::from_slice(self.as_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resize the `MinSlice`, returning a new `Some(&mut MinSlice<T, M>)`
|
|
||||||
/// if there are at least `M` `T`s in `self`.
|
|
||||||
pub fn resize_mut<const M: usize>(&mut self) -> Option<&mut MinSlice<T, M>> {
|
|
||||||
MinSlice::<T, M>::from_mut(self.as_mut_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extend the `MinSlice`, returning a new `Some(&MinSlice<T, N + I>)`
|
|
||||||
/// if there are at least `I` `T`s in `tail`.
|
|
||||||
#[cfg(feature = "nightly")]
|
|
||||||
pub fn extend_by<const I: usize>(&self) -> Option<&MinSlice<T, {N + I}>> {
|
|
||||||
MinSlice::<T, {N + I}>::from_slice(self.as_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extend the `MinSlice`, returning a new `Some(&mut MinSlice<T, N + I>)`
|
|
||||||
/// if there are at least `I` `T`s in `tail`.
|
|
||||||
#[cfg(feature = "nightly")]
|
|
||||||
pub fn extend_by_mut<const I: usize>(&mut self) -> Option<&mut MinSlice<T, {N + I}>> {
|
|
||||||
MinSlice::<T, {N + I}>::from_mut(self.as_mut_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a reference to a value from the `MinSlice` by index.
|
|
||||||
///
|
|
||||||
/// Return `Some(&T)` for the `T` at index `i` if `i < (N + self.tail.len)`,
|
|
||||||
/// or `None` otherwise.
|
|
||||||
pub fn get(&self, i: usize) -> Option<&T> {
|
|
||||||
if i < N {
|
|
||||||
Some(&self.head[i])
|
|
||||||
} else {
|
|
||||||
self.tail.get(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a mutable reference to a value from the `MinSlice` by index.
|
|
||||||
///
|
|
||||||
/// Return `Some(&mut T)` for the `T` at index `i` if `i < (N + self.tail.len)`,
|
|
||||||
/// or `None` otherwise.
|
|
||||||
pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
|
|
||||||
if i < N {
|
|
||||||
Some(&mut self.head[i])
|
|
||||||
} else {
|
|
||||||
self.tail.get_mut(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Produce a `&MinSlice` from a slice of `T`s without checking its length.
|
/// Produce a `&MinSlice` from a slice of `T`s without checking its length.
|
||||||
///
|
///
|
||||||
|
@ -175,26 +112,14 @@ impl<T, const N: usize> ExactSlice<T, N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a slice over the memory referred to by the `ExactSlice`.
|
|
||||||
/// Its length is guaranteed to be exactly `N`.
|
|
||||||
pub fn as_slice(&self) -> &[T] {
|
|
||||||
unsafe { slice::from_raw_parts(self.head.as_ptr(), N) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a mutable slice over the memory referred to by the `ExactSlice`.
|
|
||||||
/// Its length is guaranteed to be exactly `N`.
|
|
||||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
|
||||||
unsafe { slice::from_raw_parts_mut(self.head.as_mut_ptr(), N) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Produce a `&MinSlice` from this `&ExactSlice`. Its `tail` will be empty.
|
/// Produce a `&MinSlice` from this `&ExactSlice`. Its `tail` will be empty.
|
||||||
pub fn as_min_slice(&self) -> &MinSlice<T, N> {
|
pub fn as_min_slice(&self) -> Option<&MinSlice<T, N>> {
|
||||||
unsafe { MinSlice::from_slice_unchecked(&self.head[..]) }
|
MinSlice::from_slice(&self.head[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce a `&mut MinSlice` from this `&min ExactSlice`. Its `tail` will be empty.
|
/// Produce a `&mut MinSlice` from this `&min ExactSlice`. Its `tail` will be empty.
|
||||||
pub fn as_mut_min_slice(&mut self) -> &mut MinSlice<T, N> {
|
pub fn as_mut_min_slice(&mut self) -> Option<&mut MinSlice<T, N>> {
|
||||||
unsafe { MinSlice::from_mut_unchecked(&mut self.head[..]) }
|
MinSlice::from_mut(&mut self.head[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce an `&ExactSlice` from a slice of `T`s without checking its length.
|
/// Produce an `&ExactSlice` from a slice of `T`s without checking its length.
|
||||||
|
@ -218,30 +143,6 @@ impl<T, const N: usize> ExactSlice<T, N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, const N: usize> Into<&'a MinSlice<T, N>> for &'a ExactSlice<T, N> {
|
|
||||||
fn into(self) -> &'a MinSlice<T, N> {
|
|
||||||
self.as_min_slice()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T, const N: usize> Into<&'a mut MinSlice<T, N>> for &'a mut ExactSlice<T, N> {
|
|
||||||
fn into(self) -> &'a mut MinSlice<T, N> {
|
|
||||||
self.as_mut_min_slice()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T, const N: usize> Into<&'a ExactSlice<T, N>> for &'a MinSlice<T, N> {
|
|
||||||
fn into(self) -> &'a ExactSlice<T, N> {
|
|
||||||
unsafe { ExactSlice::from_slice_unchecked(&self.head[..]) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T, const N: usize> Into<&'a mut ExactSlice<T, N>> for &'a mut MinSlice<T, N> {
|
|
||||||
fn into(self) -> &'a mut ExactSlice<T, N> {
|
|
||||||
unsafe { ExactSlice::from_mut_unchecked(&mut self.head[..]) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn basic_min_success() {
|
fn basic_min_success() {
|
||||||
let slice = &[1, 2, 3, 4, 5, 6];
|
let slice = &[1, 2, 3, 4, 5, 6];
|
||||||
|
|
Loading…
Reference in New Issue