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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

- Added `SortedLinearMap`, a fixed-capacity map that keeps entries sorted by key and performs lookups via binary search (analogous to `BTreeMap` as `LinearMap` is to `HashMap`). Includes `first_key_value`/`last_key_value`, `pop_first`/`pop_last`, `range`/`range_mut`, `entry`, `retain`, serde, and zeroize support.

## [v0.9.3] 2025-04-15

- Fixed unsoundness in `Deque::clear`, `HistoryBuf::clear` and `IndexMap::clear` in the context
Expand Down
43 changes: 42 additions & 1 deletion src/de.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
binary_heap::Kind as BinaryHeapKind, len_type::LenType, BinaryHeap, Deque, HistoryBuf,
IndexMap, IndexSet, LinearMap, String, Vec,
IndexMap, IndexSet, LinearMap, SortedLinearMap, String, Vec,
};
use core::{
fmt,
Expand Down Expand Up @@ -297,6 +297,47 @@ where
}
}

impl<'de, K, V, const N: usize> Deserialize<'de> for SortedLinearMap<K, V, N>
where
K: Ord + Deserialize<'de>,
V: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct ValueVisitor<'de, K, V, const N: usize>(PhantomData<(&'de (), K, V)>);

impl<'de, K, V, const N: usize> de::Visitor<'de> for ValueVisitor<'de, K, V, N>
where
K: Ord + Deserialize<'de>,
V: Deserialize<'de>,
{
type Value = SortedLinearMap<K, V, N>;

fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a map")
}

fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut values = SortedLinearMap::new();

while let Some((key, value)) = map.next_entry()? {
if values.insert(key, value).is_err() {
return Err(A::Error::invalid_length(values.capacity() + 1, &self))?;
}
}

Ok(values)
}
}
deserializer.deserialize_map(ValueVisitor(PhantomData))
}
}

// String containers

impl<'de, LenT: LenType, const N: usize> Deserialize<'de> for String<N, LenT> {
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
//! - [`IndexMap`]: A hash table.
//! - [`IndexSet`]: A hash set.
//! - [`LinearMap`]: A linear map.
//! - [`SortedLinearMap`]: A map with entries kept sorted by key.
//! - [`SortedLinkedList`](sorted_linked_list::SortedLinkedList): A sorted linked list.
//! - [`String`]: A string.
//! - [`Vec`]: A vector.
Expand Down Expand Up @@ -157,6 +158,7 @@ pub use index_map::IndexMap;
pub use index_set::IndexSet;
pub use len_type::LenType;
pub use linear_map::LinearMap;
pub use sorted_linear_map::SortedLinearMap;
pub use string::String;

pub use vec::{Vec, VecView};
Expand All @@ -173,6 +175,7 @@ pub mod index_set;
mod len_type;
pub mod linear_map;
mod slice;
pub mod sorted_linear_map;
pub mod storage;
pub mod string;
pub mod vec;
Expand Down
18 changes: 18 additions & 0 deletions src/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{
history_buf::{HistoryBufInner, HistoryBufStorage},
len_type::LenType,
linear_map::{LinearMapInner, LinearMapStorage},
sorted_linear_map::{SortedLinearMapInner, SortedLinearMapStorage},
string::{StringInner, StringStorage},
vec::{VecInner, VecStorage},
IndexMap, IndexSet,
Expand Down Expand Up @@ -134,6 +135,23 @@ where
}
}

impl<K, V, S: SortedLinearMapStorage<K, V> + ?Sized> Serialize for SortedLinearMapInner<K, V, S>
where
K: Ord + Serialize,
V: Serialize,
{
fn serialize<SER>(&self, serializer: SER) -> Result<SER::Ok, SER::Error>
where
SER: Serializer,
{
let mut map = serializer.serialize_map(Some(self.len()))?;
for (k, v) in self {
map.serialize_entry(k, v)?;
}
map.end()
}
}

// String containers

impl<LenT: LenType, S: StringStorage + ?Sized> Serialize for StringInner<LenT, S> {
Expand Down
Loading
Loading