mirror of
https://github.com/rust-embedded/heapless.git
synced 2025-09-27 12:30:35 +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`
|
||||
|
||||
## [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
|
||||
|
||||
### Fixed
|
||||
@ -421,7 +434,9 @@ architecture.
|
||||
|
||||
- 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.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
|
||||
|
@ -12,7 +12,7 @@ keywords = ["static", "no-heap"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
name = "heapless"
|
||||
repository = "https://github.com/japaric/heapless"
|
||||
version = "0.7.7"
|
||||
version = "0.7.9"
|
||||
|
||||
[features]
|
||||
default = ["cas"]
|
||||
@ -24,6 +24,7 @@ x86-sync-pool = []
|
||||
__trybuild = []
|
||||
# Enable larger MPMC sizes.
|
||||
mpmc_large = []
|
||||
# This flag has no version guarantee, the `defmt` dependency can be updated in a patch release
|
||||
defmt-impl = ["defmt"]
|
||||
|
||||
[target.'cfg(any(target_arch = "x86_64", target_arch = "x86"))'.dev-dependencies]
|
||||
@ -55,9 +56,5 @@ optional = true
|
||||
version = "0.1"
|
||||
|
||||
[dependencies.defmt]
|
||||
version = "0.2.1"
|
||||
version = ">=0.2.0,<0.4"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies.defmt]
|
||||
version = "0.2.1"
|
||||
features = ["unstable-test"]
|
||||
|
@ -9,6 +9,7 @@
|
||||
// n)` in-place heapsort.
|
||||
|
||||
use core::{
|
||||
cmp::Ordering,
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
mem::{self, ManuallyDrop},
|
||||
@ -16,7 +17,6 @@ use core::{
|
||||
ptr, slice,
|
||||
};
|
||||
|
||||
use crate::sealed::binary_heap::Kind;
|
||||
use crate::vec::Vec;
|
||||
|
||||
/// Min-heap
|
||||
@ -25,6 +25,32 @@ pub enum Min {}
|
||||
/// Max-heap
|
||||
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.
|
||||
///
|
||||
/// This can be either a min-heap or a max-heap.
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::{
|
||||
sealed::binary_heap::Kind as BinaryHeapKind, BinaryHeap, IndexMap, IndexSet, LinearMap, String,
|
||||
Vec,
|
||||
binary_heap::Kind as BinaryHeapKind, BinaryHeap, IndexMap, IndexSet, LinearMap, String, Vec,
|
||||
};
|
||||
use core::{fmt, marker::PhantomData};
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
#[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> {
|
||||
/// Creates an empty `IndexMap`.
|
||||
pub const fn new() -> Self {
|
||||
// Const assert
|
||||
crate::sealed::greater_than_1::<N>();
|
||||
crate::sealed::power_of_two::<N>();
|
||||
|
||||
IndexMap {
|
||||
build_hasher: BuildHasherDefault::new(),
|
||||
core: CoreMap::new(),
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::indexmap::{self, IndexMap};
|
||||
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
|
||||
/// default FNV hasher.
|
||||
@ -74,22 +74,13 @@ pub type FnvIndexSet<T, const N: usize> = IndexSet<T, BuildHasherDefault<FnvHash
|
||||
/// println!("{}", book);
|
||||
/// }
|
||||
/// ```
|
||||
pub struct IndexSet<T, S, const N: usize>
|
||||
where
|
||||
T: Eq + Hash,
|
||||
{
|
||||
pub struct IndexSet<T, S, const N: usize> {
|
||||
map: IndexMap<T, (), S, N>,
|
||||
}
|
||||
|
||||
impl<T, S, const N: usize> IndexSet<T, BuildHasherDefault<S>, N>
|
||||
where
|
||||
T: Eq + Hash,
|
||||
S: Default + Hasher,
|
||||
{
|
||||
impl<T, S, const N: usize> IndexSet<T, BuildHasherDefault<S>, N> {
|
||||
/// Creates an empty `IndexSet`
|
||||
pub fn new() -> Self {
|
||||
assert!(N.is_power_of_two());
|
||||
|
||||
pub const fn new() -> Self {
|
||||
IndexSet {
|
||||
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(path_statements)]
|
||||
pub(crate) const fn smaller_than<const N: usize, const MAX: usize>() {
|
||||
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(path_statements)]
|
||||
pub(crate) const fn greater_than_0<const N: usize>() {
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::{
|
||||
sealed::binary_heap::Kind as BinaryHeapKind, BinaryHeap, IndexMap, IndexSet, LinearMap, String,
|
||||
Vec,
|
||||
binary_heap::Kind as BinaryHeapKind, BinaryHeap, IndexMap, IndexSet, LinearMap, String, Vec,
|
||||
};
|
||||
use hash32::{BuildHasher, Hash};
|
||||
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
|
||||
|
@ -25,7 +25,7 @@
|
||||
//!
|
||||
//! [`BinaryHeap`]: `crate::binary_heap::BinaryHeap`
|
||||
|
||||
use crate::sealed::sorted_linked_list::Kind as LLKind;
|
||||
use core::cmp::Ordering;
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::MaybeUninit;
|
||||
@ -50,6 +50,32 @@ pub struct Min;
|
||||
/// Marker for Max sorted [`SortedLinkedList`].
|
||||
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`].
|
||||
pub struct Node<T, Idx> {
|
||||
val: MaybeUninit<T>,
|
||||
@ -57,14 +83,14 @@ pub struct Node<T, Idx> {
|
||||
}
|
||||
|
||||
/// The linked list.
|
||||
pub struct SortedLinkedList<T, Idx, Kind, const N: usize>
|
||||
pub struct SortedLinkedList<T, Idx, K, const N: usize>
|
||||
where
|
||||
Idx: SortedLinkedListIndex,
|
||||
{
|
||||
list: [Node<T, Idx>; N],
|
||||
head: Idx,
|
||||
free: Idx,
|
||||
_kind: PhantomData<Kind>,
|
||||
_kind: PhantomData<K>,
|
||||
}
|
||||
|
||||
// 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 {
|
||||
val: MaybeUninit::uninit(),
|
||||
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!(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
|
||||
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
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
Kind: LLKind,
|
||||
K: Kind,
|
||||
{
|
||||
/// Pushes a value onto the list without checking if the list is full.
|
||||
///
|
||||
@ -230,7 +256,7 @@ where
|
||||
if self
|
||||
.read_data_in_node_at(head)
|
||||
.cmp(self.read_data_in_node_at(new))
|
||||
!= Kind::ordering()
|
||||
!= K::ordering()
|
||||
{
|
||||
self.node_at_mut(new).next = self.head;
|
||||
self.head = Idx::new_unchecked(new);
|
||||
@ -242,7 +268,7 @@ where
|
||||
if self
|
||||
.read_data_in_node_at(next)
|
||||
.cmp(self.read_data_in_node_at(new))
|
||||
!= Kind::ordering()
|
||||
!= K::ordering()
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -307,7 +333,7 @@ where
|
||||
/// assert_eq!(iter.next(), Some(&1));
|
||||
/// assert_eq!(iter.next(), None);
|
||||
/// ```
|
||||
pub fn iter(&self) -> Iter<'_, T, Idx, Kind, N> {
|
||||
pub fn iter(&self) -> Iter<'_, T, Idx, K, N> {
|
||||
Iter {
|
||||
list: self,
|
||||
index: self.head,
|
||||
@ -336,7 +362,7 @@ where
|
||||
/// assert_eq!(ll.pop(), Ok(1));
|
||||
/// 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
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
@ -486,21 +512,21 @@ where
|
||||
}
|
||||
|
||||
/// 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
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
Kind: LLKind,
|
||||
K: Kind,
|
||||
{
|
||||
list: &'a SortedLinkedList<T, Idx, Kind, N>,
|
||||
list: &'a SortedLinkedList<T, Idx, K, N>,
|
||||
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
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
Kind: LLKind,
|
||||
K: Kind,
|
||||
{
|
||||
type Item = &'a T;
|
||||
|
||||
@ -515,24 +541,24 @@ where
|
||||
}
|
||||
|
||||
/// 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
|
||||
T: Ord,
|
||||
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,
|
||||
prev_index: Idx,
|
||||
index: Idx,
|
||||
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
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
Kind: LLKind,
|
||||
K: Kind,
|
||||
{
|
||||
fn pop_internal(&mut self) -> T {
|
||||
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
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
Kind: LLKind,
|
||||
K: Kind,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
// 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
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
Kind: LLKind,
|
||||
K: Kind,
|
||||
{
|
||||
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
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
Kind: LLKind,
|
||||
K: Kind,
|
||||
{
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.maybe_changed = true;
|
||||
@ -659,11 +685,11 @@ where
|
||||
}
|
||||
|
||||
// /// 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
|
||||
// T: Ord + core::fmt::Debug,
|
||||
// Idx: SortedLinkedListIndex,
|
||||
// Kind: LLKind,
|
||||
// K: Kind,
|
||||
// {
|
||||
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// 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
|
||||
T: Ord + core::fmt::Debug,
|
||||
Idx: SortedLinkedListIndex,
|
||||
Kind: LLKind,
|
||||
K: Kind,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
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
|
||||
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;
|
||||
|
||||
/// 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)
|
||||
pub const fn new() -> Self {
|
||||
// Const assert N > 0
|
||||
crate::sealed::greater_than_0::<N>();
|
||||
// Const assert N >= 0
|
||||
crate::sealed::greater_than_eq_0::<N>();
|
||||
|
||||
Self {
|
||||
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> {
|
||||
fn extend<I>(&mut self, iter: I)
|
||||
where
|
||||
@ -1222,4 +1233,29 @@ mod tests {
|
||||
assert!(!v.ends_with(b"ba"));
|
||||
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