mirror of
https://github.com/rust-embedded/heapless.git
synced 2025-09-30 05:50:29 +00:00
Merge branch 'master' into feature/historybuf_ordered_iterator
This commit is contained in:
commit
4d0a160638
28
.github/workflows/changelog.yml
vendored
Normal file
28
.github/workflows/changelog.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Check that the changelog is updated for all changes.
|
||||||
|
#
|
||||||
|
# This is only run for PRs.
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
# opened, reopened, synchronize are the default types for pull_request.
|
||||||
|
# labeled, unlabeled ensure this check is also run if a label is added or removed.
|
||||||
|
types: [opened, reopened, labeled, unlabeled, synchronize]
|
||||||
|
|
||||||
|
name: Changelog
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
changelog:
|
||||||
|
name: Changelog
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Check that changelog updated
|
||||||
|
uses: dangoslen/changelog-enforcer@v3
|
||||||
|
with:
|
||||||
|
changeLogPath: CHANGELOG.md
|
||||||
|
skipLabels: 'needs-changelog, skip-changelog'
|
||||||
|
missingUpdateErrorMessage: 'Please add a changelog entry in the CHANGELOG.md file.'
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
17
CHANGELOG.md
17
CHANGELOG.md
@ -11,6 +11,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
- Added `OldestOrdered` iterator for `HistoryBuffer`
|
- Added `OldestOrdered` iterator for `HistoryBuffer`
|
||||||
|
|
||||||
|
## [v0.7.9] - 2021-12-16
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix `IndexMap` and `IndexSet` bounds
|
||||||
|
- Make `IndexSet::new()` a `const fn`
|
||||||
|
|
||||||
|
## [v0.7.8] - 2021-11-11
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- A span of `defmt` versions is now supported (`0.2` and `0.3`)
|
||||||
|
|
||||||
## [v0.7.7] - 2021-09-22
|
## [v0.7.7] - 2021-09-22
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
@ -421,7 +434,9 @@ architecture.
|
|||||||
|
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|
||||||
[Unreleased]: https://github.com/japaric/heapless/compare/v0.7.7...HEAD
|
[Unreleased]: https://github.com/japaric/heapless/compare/v0.7.9...HEAD
|
||||||
|
[v0.7.9]: https://github.com/japaric/heapless/compare/v0.7.8...v0.7.9
|
||||||
|
[v0.7.8]: https://github.com/japaric/heapless/compare/v0.7.7...v0.7.8
|
||||||
[v0.7.7]: https://github.com/japaric/heapless/compare/v0.7.6...v0.7.7
|
[v0.7.7]: https://github.com/japaric/heapless/compare/v0.7.6...v0.7.7
|
||||||
[v0.7.6]: https://github.com/japaric/heapless/compare/v0.7.5...v0.7.6
|
[v0.7.6]: https://github.com/japaric/heapless/compare/v0.7.5...v0.7.6
|
||||||
[v0.7.5]: https://github.com/japaric/heapless/compare/v0.7.4...v0.7.5
|
[v0.7.5]: https://github.com/japaric/heapless/compare/v0.7.4...v0.7.5
|
||||||
|
@ -12,7 +12,7 @@ keywords = ["static", "no-heap"]
|
|||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
name = "heapless"
|
name = "heapless"
|
||||||
repository = "https://github.com/japaric/heapless"
|
repository = "https://github.com/japaric/heapless"
|
||||||
version = "0.7.7"
|
version = "0.7.9"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["cas"]
|
default = ["cas"]
|
||||||
@ -24,6 +24,7 @@ x86-sync-pool = []
|
|||||||
__trybuild = []
|
__trybuild = []
|
||||||
# Enable larger MPMC sizes.
|
# Enable larger MPMC sizes.
|
||||||
mpmc_large = []
|
mpmc_large = []
|
||||||
|
# This flag has no version guarantee, the `defmt` dependency can be updated in a patch release
|
||||||
defmt-impl = ["defmt"]
|
defmt-impl = ["defmt"]
|
||||||
|
|
||||||
[target.'cfg(any(target_arch = "x86_64", target_arch = "x86"))'.dev-dependencies]
|
[target.'cfg(any(target_arch = "x86_64", target_arch = "x86"))'.dev-dependencies]
|
||||||
@ -55,9 +56,5 @@ optional = true
|
|||||||
version = "0.1"
|
version = "0.1"
|
||||||
|
|
||||||
[dependencies.defmt]
|
[dependencies.defmt]
|
||||||
version = "0.2.1"
|
version = ">=0.2.0,<0.4"
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dev-dependencies.defmt]
|
|
||||||
version = "0.2.1"
|
|
||||||
features = ["unstable-test"]
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
// n)` in-place heapsort.
|
// n)` in-place heapsort.
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
|
cmp::Ordering,
|
||||||
fmt,
|
fmt,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
mem::{self, ManuallyDrop},
|
mem::{self, ManuallyDrop},
|
||||||
@ -16,7 +17,6 @@ use core::{
|
|||||||
ptr, slice,
|
ptr, slice,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::sealed::binary_heap::Kind;
|
|
||||||
use crate::vec::Vec;
|
use crate::vec::Vec;
|
||||||
|
|
||||||
/// Min-heap
|
/// Min-heap
|
||||||
@ -25,6 +25,32 @@ pub enum Min {}
|
|||||||
/// Max-heap
|
/// Max-heap
|
||||||
pub enum Max {}
|
pub enum Max {}
|
||||||
|
|
||||||
|
/// The binary heap kind: min-heap or max-heap
|
||||||
|
pub trait Kind: private::Sealed {
|
||||||
|
#[doc(hidden)]
|
||||||
|
fn ordering() -> Ordering;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Kind for Min {
|
||||||
|
fn ordering() -> Ordering {
|
||||||
|
Ordering::Less
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Kind for Max {
|
||||||
|
fn ordering() -> Ordering {
|
||||||
|
Ordering::Greater
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sealed traits
|
||||||
|
mod private {
|
||||||
|
pub trait Sealed {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl private::Sealed for Max {}
|
||||||
|
impl private::Sealed for Min {}
|
||||||
|
|
||||||
/// A priority queue implemented with a binary heap.
|
/// A priority queue implemented with a binary heap.
|
||||||
///
|
///
|
||||||
/// This can be either a min-heap or a max-heap.
|
/// This can be either a min-heap or a max-heap.
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
sealed::binary_heap::Kind as BinaryHeapKind, BinaryHeap, IndexMap, IndexSet, LinearMap, String,
|
binary_heap::Kind as BinaryHeapKind, BinaryHeap, IndexMap, IndexSet, LinearMap, String, Vec,
|
||||||
Vec,
|
|
||||||
};
|
};
|
||||||
use core::{fmt, marker::PhantomData};
|
use core::{fmt, marker::PhantomData};
|
||||||
use hash32::{BuildHasherDefault, Hash, Hasher};
|
use hash32::{BuildHasherDefault, Hash, Hasher};
|
||||||
|
33
src/defmt.rs
33
src/defmt.rs
@ -21,36 +21,3 @@ where
|
|||||||
defmt::write!(fmt, "{=str}", self.as_str());
|
defmt::write!(fmt, "{=str}", self.as_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::Vec;
|
|
||||||
use defmt::Format;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
/// Tests encoding Vec with defmt, asserting these types may be serialized
|
|
||||||
/// Note: the exact wire format is NOT checked since its an unstable implementation detail of an external crate.
|
|
||||||
/// based on https://github.com/knurling-rs/defmt/blob/697a8e807bd766a80ada2d57514a9da1232dbc9a/tests/encode.rs#L523
|
|
||||||
fn test_defmt_format_vec() {
|
|
||||||
let val: Vec<_, 8> = Vec::from_slice(b"abc").unwrap();
|
|
||||||
|
|
||||||
let mut f = defmt::InternalFormatter::new();
|
|
||||||
let g = defmt::Formatter { inner: &mut f };
|
|
||||||
val.format(g);
|
|
||||||
f.finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tests encoding String with defmt, asserting these types may be serialized
|
|
||||||
/// Note: the exact wire format is NOT checked since its an unstable implementation detail of an external crate.
|
|
||||||
/// based loosely on https://github.com/knurling-rs/defmt/blob/main/tests/encode.rs#L483
|
|
||||||
#[test]
|
|
||||||
fn test_defmt_format_str() {
|
|
||||||
let mut val: crate::String<32> = crate::String::new();
|
|
||||||
val.push_str("foo").unwrap();
|
|
||||||
|
|
||||||
let mut f = defmt::InternalFormatter::new();
|
|
||||||
let g = defmt::Formatter { inner: &mut f };
|
|
||||||
val.format(g);
|
|
||||||
f.finalize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -368,6 +368,10 @@ pub struct IndexMap<K, V, S, const N: usize> {
|
|||||||
impl<K, V, S, const N: usize> IndexMap<K, V, BuildHasherDefault<S>, N> {
|
impl<K, V, S, const N: usize> IndexMap<K, V, BuildHasherDefault<S>, N> {
|
||||||
/// Creates an empty `IndexMap`.
|
/// Creates an empty `IndexMap`.
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
|
// Const assert
|
||||||
|
crate::sealed::greater_than_1::<N>();
|
||||||
|
crate::sealed::power_of_two::<N>();
|
||||||
|
|
||||||
IndexMap {
|
IndexMap {
|
||||||
build_hasher: BuildHasherDefault::new(),
|
build_hasher: BuildHasherDefault::new(),
|
||||||
core: CoreMap::new(),
|
core: CoreMap::new(),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::indexmap::{self, IndexMap};
|
use crate::indexmap::{self, IndexMap};
|
||||||
use core::{borrow::Borrow, fmt, iter::FromIterator};
|
use core::{borrow::Borrow, fmt, iter::FromIterator};
|
||||||
use hash32::{BuildHasher, BuildHasherDefault, FnvHasher, Hash, Hasher};
|
use hash32::{BuildHasher, BuildHasherDefault, FnvHasher, Hash};
|
||||||
|
|
||||||
/// A [`heapless::IndexSet`](./struct.IndexSet.html) using the
|
/// A [`heapless::IndexSet`](./struct.IndexSet.html) using the
|
||||||
/// default FNV hasher.
|
/// default FNV hasher.
|
||||||
@ -74,22 +74,13 @@ pub type FnvIndexSet<T, const N: usize> = IndexSet<T, BuildHasherDefault<FnvHash
|
|||||||
/// println!("{}", book);
|
/// println!("{}", book);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct IndexSet<T, S, const N: usize>
|
pub struct IndexSet<T, S, const N: usize> {
|
||||||
where
|
|
||||||
T: Eq + Hash,
|
|
||||||
{
|
|
||||||
map: IndexMap<T, (), S, N>,
|
map: IndexMap<T, (), S, N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, S, const N: usize> IndexSet<T, BuildHasherDefault<S>, N>
|
impl<T, S, const N: usize> IndexSet<T, BuildHasherDefault<S>, N> {
|
||||||
where
|
|
||||||
T: Eq + Hash,
|
|
||||||
S: Default + Hasher,
|
|
||||||
{
|
|
||||||
/// Creates an empty `IndexSet`
|
/// Creates an empty `IndexSet`
|
||||||
pub fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
assert!(N.is_power_of_two());
|
|
||||||
|
|
||||||
IndexSet {
|
IndexSet {
|
||||||
map: IndexMap::new(),
|
map: IndexMap::new(),
|
||||||
}
|
}
|
||||||
|
@ -1,57 +1,15 @@
|
|||||||
/// Sealed traits and implementations for `binary_heap`
|
|
||||||
pub mod binary_heap {
|
|
||||||
use crate::binary_heap::{Max, Min};
|
|
||||||
use core::cmp::Ordering;
|
|
||||||
|
|
||||||
/// The binary heap kind: min-heap or max-heap
|
|
||||||
pub unsafe trait Kind {
|
|
||||||
#[doc(hidden)]
|
|
||||||
fn ordering() -> Ordering;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Kind for Min {
|
|
||||||
fn ordering() -> Ordering {
|
|
||||||
Ordering::Less
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Kind for Max {
|
|
||||||
fn ordering() -> Ordering {
|
|
||||||
Ordering::Greater
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sealed traits and implementations for `LinkedList`
|
|
||||||
pub mod sorted_linked_list {
|
|
||||||
use crate::sorted_linked_list::{Max, Min};
|
|
||||||
use core::cmp::Ordering;
|
|
||||||
|
|
||||||
/// The linked list kind: min-list or max-list
|
|
||||||
pub unsafe trait Kind {
|
|
||||||
#[doc(hidden)]
|
|
||||||
fn ordering() -> Ordering;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Kind for Min {
|
|
||||||
fn ordering() -> Ordering {
|
|
||||||
Ordering::Less
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Kind for Max {
|
|
||||||
fn ordering() -> Ordering {
|
|
||||||
Ordering::Greater
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(path_statements)]
|
#[allow(path_statements)]
|
||||||
pub(crate) const fn smaller_than<const N: usize, const MAX: usize>() {
|
pub(crate) const fn smaller_than<const N: usize, const MAX: usize>() {
|
||||||
Assert::<N, MAX>::LESS;
|
Assert::<N, MAX>::LESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[allow(path_statements)]
|
||||||
|
pub(crate) const fn greater_than_eq_0<const N: usize>() {
|
||||||
|
Assert::<N, 0>::GREATER_EQ;
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(path_statements)]
|
#[allow(path_statements)]
|
||||||
pub(crate) const fn greater_than_0<const N: usize>() {
|
pub(crate) const fn greater_than_0<const N: usize>() {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
sealed::binary_heap::Kind as BinaryHeapKind, BinaryHeap, IndexMap, IndexSet, LinearMap, String,
|
binary_heap::Kind as BinaryHeapKind, BinaryHeap, IndexMap, IndexSet, LinearMap, String, Vec,
|
||||||
Vec,
|
|
||||||
};
|
};
|
||||||
use hash32::{BuildHasher, Hash};
|
use hash32::{BuildHasher, Hash};
|
||||||
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
|
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
//!
|
//!
|
||||||
//! [`BinaryHeap`]: `crate::binary_heap::BinaryHeap`
|
//! [`BinaryHeap`]: `crate::binary_heap::BinaryHeap`
|
||||||
|
|
||||||
use crate::sealed::sorted_linked_list::Kind as LLKind;
|
use core::cmp::Ordering;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
@ -50,6 +50,32 @@ pub struct Min;
|
|||||||
/// Marker for Max sorted [`SortedLinkedList`].
|
/// Marker for Max sorted [`SortedLinkedList`].
|
||||||
pub struct Max;
|
pub struct Max;
|
||||||
|
|
||||||
|
/// The linked list kind: min-list or max-list
|
||||||
|
pub trait Kind: private::Sealed {
|
||||||
|
#[doc(hidden)]
|
||||||
|
fn ordering() -> Ordering;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Kind for Min {
|
||||||
|
fn ordering() -> Ordering {
|
||||||
|
Ordering::Less
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Kind for Max {
|
||||||
|
fn ordering() -> Ordering {
|
||||||
|
Ordering::Greater
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sealed traits
|
||||||
|
mod private {
|
||||||
|
pub trait Sealed {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl private::Sealed for Max {}
|
||||||
|
impl private::Sealed for Min {}
|
||||||
|
|
||||||
/// A node in the [`SortedLinkedList`].
|
/// A node in the [`SortedLinkedList`].
|
||||||
pub struct Node<T, Idx> {
|
pub struct Node<T, Idx> {
|
||||||
val: MaybeUninit<T>,
|
val: MaybeUninit<T>,
|
||||||
@ -57,14 +83,14 @@ pub struct Node<T, Idx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The linked list.
|
/// The linked list.
|
||||||
pub struct SortedLinkedList<T, Idx, Kind, const N: usize>
|
pub struct SortedLinkedList<T, Idx, K, const N: usize>
|
||||||
where
|
where
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
{
|
{
|
||||||
list: [Node<T, Idx>; N],
|
list: [Node<T, Idx>; N],
|
||||||
head: Idx,
|
head: Idx,
|
||||||
free: Idx,
|
free: Idx,
|
||||||
_kind: PhantomData<Kind>,
|
_kind: PhantomData<K>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal macro for generating indexes for the linkedlist and const new for the linked list
|
// Internal macro for generating indexes for the linkedlist and const new for the linked list
|
||||||
@ -115,7 +141,7 @@ macro_rules! impl_index_and_const_new {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Kind, const N: usize> SortedLinkedList<T, $name, Kind, N> {
|
impl<T, K, const N: usize> SortedLinkedList<T, $name, K, N> {
|
||||||
const UNINIT: Node<T, $name> = Node {
|
const UNINIT: Node<T, $name> = Node {
|
||||||
val: MaybeUninit::uninit(),
|
val: MaybeUninit::uninit(),
|
||||||
next: $name::none(),
|
next: $name::none(),
|
||||||
@ -156,7 +182,7 @@ impl_index_and_const_new!(LinkedIndexU8, u8, new_u8, 254); // val is 2^8 - 2 (on
|
|||||||
impl_index_and_const_new!(LinkedIndexU16, u16, new_u16, 65_534); // val is 2^16 - 2
|
impl_index_and_const_new!(LinkedIndexU16, u16, new_u16, 65_534); // val is 2^16 - 2
|
||||||
impl_index_and_const_new!(LinkedIndexUsize, usize, new_usize, 4_294_967_294); // val is 2^32 - 2
|
impl_index_and_const_new!(LinkedIndexUsize, usize, new_usize, 4_294_967_294); // val is 2^32 - 2
|
||||||
|
|
||||||
impl<T, Idx, Kind, const N: usize> SortedLinkedList<T, Idx, Kind, N>
|
impl<T, Idx, K, const N: usize> SortedLinkedList<T, Idx, K, N>
|
||||||
where
|
where
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
{
|
{
|
||||||
@ -205,11 +231,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Idx, Kind, const N: usize> SortedLinkedList<T, Idx, Kind, N>
|
impl<T, Idx, K, const N: usize> SortedLinkedList<T, Idx, K, N>
|
||||||
where
|
where
|
||||||
T: Ord,
|
T: Ord,
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
Kind: LLKind,
|
K: Kind,
|
||||||
{
|
{
|
||||||
/// Pushes a value onto the list without checking if the list is full.
|
/// Pushes a value onto the list without checking if the list is full.
|
||||||
///
|
///
|
||||||
@ -230,7 +256,7 @@ where
|
|||||||
if self
|
if self
|
||||||
.read_data_in_node_at(head)
|
.read_data_in_node_at(head)
|
||||||
.cmp(self.read_data_in_node_at(new))
|
.cmp(self.read_data_in_node_at(new))
|
||||||
!= Kind::ordering()
|
!= K::ordering()
|
||||||
{
|
{
|
||||||
self.node_at_mut(new).next = self.head;
|
self.node_at_mut(new).next = self.head;
|
||||||
self.head = Idx::new_unchecked(new);
|
self.head = Idx::new_unchecked(new);
|
||||||
@ -242,7 +268,7 @@ where
|
|||||||
if self
|
if self
|
||||||
.read_data_in_node_at(next)
|
.read_data_in_node_at(next)
|
||||||
.cmp(self.read_data_in_node_at(new))
|
.cmp(self.read_data_in_node_at(new))
|
||||||
!= Kind::ordering()
|
!= K::ordering()
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -307,7 +333,7 @@ where
|
|||||||
/// assert_eq!(iter.next(), Some(&1));
|
/// assert_eq!(iter.next(), Some(&1));
|
||||||
/// assert_eq!(iter.next(), None);
|
/// assert_eq!(iter.next(), None);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn iter(&self) -> Iter<'_, T, Idx, Kind, N> {
|
pub fn iter(&self) -> Iter<'_, T, Idx, K, N> {
|
||||||
Iter {
|
Iter {
|
||||||
list: self,
|
list: self,
|
||||||
index: self.head,
|
index: self.head,
|
||||||
@ -336,7 +362,7 @@ where
|
|||||||
/// assert_eq!(ll.pop(), Ok(1));
|
/// assert_eq!(ll.pop(), Ok(1));
|
||||||
/// assert_eq!(ll.pop(), Err(()));
|
/// assert_eq!(ll.pop(), Err(()));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn find_mut<F>(&mut self, mut f: F) -> Option<FindMut<'_, T, Idx, Kind, N>>
|
pub fn find_mut<F>(&mut self, mut f: F) -> Option<FindMut<'_, T, Idx, K, N>>
|
||||||
where
|
where
|
||||||
F: FnMut(&T) -> bool,
|
F: FnMut(&T) -> bool,
|
||||||
{
|
{
|
||||||
@ -486,21 +512,21 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Iterator for the linked list.
|
/// Iterator for the linked list.
|
||||||
pub struct Iter<'a, T, Idx, Kind, const N: usize>
|
pub struct Iter<'a, T, Idx, K, const N: usize>
|
||||||
where
|
where
|
||||||
T: Ord,
|
T: Ord,
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
Kind: LLKind,
|
K: Kind,
|
||||||
{
|
{
|
||||||
list: &'a SortedLinkedList<T, Idx, Kind, N>,
|
list: &'a SortedLinkedList<T, Idx, K, N>,
|
||||||
index: Idx,
|
index: Idx,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, Idx, Kind, const N: usize> Iterator for Iter<'a, T, Idx, Kind, N>
|
impl<'a, T, Idx, K, const N: usize> Iterator for Iter<'a, T, Idx, K, N>
|
||||||
where
|
where
|
||||||
T: Ord,
|
T: Ord,
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
Kind: LLKind,
|
K: Kind,
|
||||||
{
|
{
|
||||||
type Item = &'a T;
|
type Item = &'a T;
|
||||||
|
|
||||||
@ -515,24 +541,24 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Comes from [`SortedLinkedList::find_mut`].
|
/// Comes from [`SortedLinkedList::find_mut`].
|
||||||
pub struct FindMut<'a, T, Idx, Kind, const N: usize>
|
pub struct FindMut<'a, T, Idx, K, const N: usize>
|
||||||
where
|
where
|
||||||
T: Ord,
|
T: Ord,
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
Kind: LLKind,
|
K: Kind,
|
||||||
{
|
{
|
||||||
list: &'a mut SortedLinkedList<T, Idx, Kind, N>,
|
list: &'a mut SortedLinkedList<T, Idx, K, N>,
|
||||||
is_head: bool,
|
is_head: bool,
|
||||||
prev_index: Idx,
|
prev_index: Idx,
|
||||||
index: Idx,
|
index: Idx,
|
||||||
maybe_changed: bool,
|
maybe_changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, Idx, Kind, const N: usize> FindMut<'a, T, Idx, Kind, N>
|
impl<'a, T, Idx, K, const N: usize> FindMut<'a, T, Idx, K, N>
|
||||||
where
|
where
|
||||||
T: Ord,
|
T: Ord,
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
Kind: LLKind,
|
K: Kind,
|
||||||
{
|
{
|
||||||
fn pop_internal(&mut self) -> T {
|
fn pop_internal(&mut self) -> T {
|
||||||
if self.is_head {
|
if self.is_head {
|
||||||
@ -616,11 +642,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Idx, Kind, const N: usize> Drop for FindMut<'_, T, Idx, Kind, N>
|
impl<T, Idx, K, const N: usize> Drop for FindMut<'_, T, Idx, K, N>
|
||||||
where
|
where
|
||||||
T: Ord,
|
T: Ord,
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
Kind: LLKind,
|
K: Kind,
|
||||||
{
|
{
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Only resort the list if the element has changed
|
// Only resort the list if the element has changed
|
||||||
@ -631,11 +657,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Idx, Kind, const N: usize> Deref for FindMut<'_, T, Idx, Kind, N>
|
impl<T, Idx, K, const N: usize> Deref for FindMut<'_, T, Idx, K, N>
|
||||||
where
|
where
|
||||||
T: Ord,
|
T: Ord,
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
Kind: LLKind,
|
K: Kind,
|
||||||
{
|
{
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
@ -645,11 +671,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Idx, Kind, const N: usize> DerefMut for FindMut<'_, T, Idx, Kind, N>
|
impl<T, Idx, K, const N: usize> DerefMut for FindMut<'_, T, Idx, K, N>
|
||||||
where
|
where
|
||||||
T: Ord,
|
T: Ord,
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
Kind: LLKind,
|
K: Kind,
|
||||||
{
|
{
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
self.maybe_changed = true;
|
self.maybe_changed = true;
|
||||||
@ -659,11 +685,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// /// Useful for debug during development.
|
// /// Useful for debug during development.
|
||||||
// impl<T, Idx, Kind, const N: usize> fmt::Debug for FindMut<'_, T, Idx, Kind, N>
|
// impl<T, Idx, K, const N: usize> fmt::Debug for FindMut<'_, T, Idx, K, N>
|
||||||
// where
|
// where
|
||||||
// T: Ord + core::fmt::Debug,
|
// T: Ord + core::fmt::Debug,
|
||||||
// Idx: SortedLinkedListIndex,
|
// Idx: SortedLinkedListIndex,
|
||||||
// Kind: LLKind,
|
// K: Kind,
|
||||||
// {
|
// {
|
||||||
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
// f.debug_struct("FindMut")
|
// f.debug_struct("FindMut")
|
||||||
@ -683,18 +709,18 @@ where
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
impl<T, Idx, Kind, const N: usize> fmt::Debug for SortedLinkedList<T, Idx, Kind, N>
|
impl<T, Idx, K, const N: usize> fmt::Debug for SortedLinkedList<T, Idx, K, N>
|
||||||
where
|
where
|
||||||
T: Ord + core::fmt::Debug,
|
T: Ord + core::fmt::Debug,
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
Kind: LLKind,
|
K: Kind,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_list().entries(self.iter()).finish()
|
f.debug_list().entries(self.iter()).finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Idx, Kind, const N: usize> Drop for SortedLinkedList<T, Idx, Kind, N>
|
impl<T, Idx, K, const N: usize> Drop for SortedLinkedList<T, Idx, K, N>
|
||||||
where
|
where
|
||||||
Idx: SortedLinkedListIndex,
|
Idx: SortedLinkedListIndex,
|
||||||
{
|
{
|
||||||
|
42
src/vec.rs
42
src/vec.rs
@ -1,4 +1,7 @@
|
|||||||
use core::{cmp::Ordering, fmt, hash, iter::FromIterator, mem::MaybeUninit, ops, ptr, slice};
|
use core::{
|
||||||
|
cmp::Ordering, convert::TryFrom, fmt, hash, iter::FromIterator, mem::MaybeUninit, ops, ptr,
|
||||||
|
slice,
|
||||||
|
};
|
||||||
use hash32;
|
use hash32;
|
||||||
|
|
||||||
/// A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html)
|
/// A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html)
|
||||||
@ -53,8 +56,8 @@ impl<T, const N: usize> Vec<T, N> {
|
|||||||
/// ```
|
/// ```
|
||||||
/// `Vec` `const` constructor; wrap the returned value in [`Vec`](../struct.Vec.html)
|
/// `Vec` `const` constructor; wrap the returned value in [`Vec`](../struct.Vec.html)
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
// Const assert N > 0
|
// Const assert N >= 0
|
||||||
crate::sealed::greater_than_0::<N>();
|
crate::sealed::greater_than_eq_0::<N>();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
buffer: [Self::INIT; N],
|
buffer: [Self::INIT; N],
|
||||||
@ -569,6 +572,14 @@ impl<T, const N: usize> Drop for Vec<T, N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec<T, N> {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
|
||||||
|
Vec::from_slice(slice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, const N: usize> Extend<T> for Vec<T, N> {
|
impl<T, const N: usize> Extend<T> for Vec<T, N> {
|
||||||
fn extend<I>(&mut self, iter: I)
|
fn extend<I>(&mut self, iter: I)
|
||||||
where
|
where
|
||||||
@ -1222,4 +1233,29 @@ mod tests {
|
|||||||
assert!(!v.ends_with(b"ba"));
|
assert!(!v.ends_with(b"ba"));
|
||||||
assert!(!v.ends_with(b"a"));
|
assert!(!v.ends_with(b"a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn zero_capacity() {
|
||||||
|
let mut v: Vec<u8, 0> = Vec::new();
|
||||||
|
// Validate capacity
|
||||||
|
assert_eq!(v.capacity(), 0);
|
||||||
|
|
||||||
|
// Make sure there is no capacity
|
||||||
|
assert!(v.push(1).is_err());
|
||||||
|
|
||||||
|
// Validate length
|
||||||
|
assert_eq!(v.len(), 0);
|
||||||
|
|
||||||
|
// Validate pop
|
||||||
|
assert_eq!(v.pop(), None);
|
||||||
|
|
||||||
|
// Validate slice
|
||||||
|
assert_eq!(v.as_slice(), &[]);
|
||||||
|
|
||||||
|
// Validate empty
|
||||||
|
assert!(v.is_empty());
|
||||||
|
|
||||||
|
// Validate full
|
||||||
|
assert!(v.is_full());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user