use std::collections::btree_map::{
IntoIter,
Iter,
Keys,
Values,
};
use std::collections::BTreeMap;
use std::ops::Bound;
use crate::core::limits::MAX_ENTRY_COUNT;
use crate::error::{
AgentMemoryError,
NotFoundError,
Result,
};
use crate::types::{
Entry,
Key,
KeyPrefix,
SetRequest,
Value,
};
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct MemoryMap {
entries: BTreeMap<Key, Value>,
}
impl MemoryMap {
#[must_use]
pub fn new() -> Self {
Self {
entries: BTreeMap::new(),
}
}
#[must_use]
pub fn with_capacity(_capacity: usize) -> Self {
Self::new()
}
#[must_use]
pub fn len(&self) -> usize {
self.entries.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn clear(&mut self) {
self.entries.clear();
}
#[must_use]
pub fn contains_key(
&self,
key: &Key,
) -> bool {
self.entries.contains_key(key)
}
pub fn insert(
&mut self,
key: Key,
value: Value,
) -> Result<Option<Value>> {
self.ensure_capacity_for_insert()?;
Ok(self.entries.insert(key, value))
}
pub fn set(
&mut self,
request: SetRequest,
) -> Result<Option<Value>> {
self.insert(request.key, request.value)
}
#[must_use]
pub fn get(
&self,
key: &Key,
) -> Option<&Value> {
self.entries.get(key)
}
pub fn require(
&self,
key: &Key,
) -> Result<&Value> {
self.get(key).ok_or_else(|| {
AgentMemoryError::NotFound(
NotFoundError::new(
"key",
key.as_str(),
),
)
})
}
pub fn remove(
&mut self,
key: &Key,
) -> Option<Value> {
self.entries.remove(key)
}
pub fn remove_required(
&mut self,
key: &Key,
) -> Result<Value> {
self.remove(key).ok_or_else(|| {
AgentMemoryError::NotFound(
NotFoundError::new(
"key",
key.as_str(),
),
)
})
}
#[must_use]
pub fn entries(&self) -> Vec<Entry> {
self.entries
.iter()
.map(|(k, v)| {
Entry::new(k.clone(), v.clone())
})
.collect()
}
#[must_use]
pub fn keys(&self) -> Vec<Key> {
self.entries.keys().cloned().collect()
}
#[must_use]
pub fn values(&self) -> Vec<Value> {
self.entries.values().cloned().collect()
}
#[must_use]
pub fn entries_with_prefix(
&self,
prefix: &KeyPrefix,
) -> Vec<Entry> {
self.range_for_prefix(prefix)
.map(|(k, v)| {
Entry::new(k.clone(), v.clone())
})
.collect()
}
#[must_use]
pub fn keys_with_prefix(
&self,
prefix: &KeyPrefix,
) -> Vec<Key> {
self.range_for_prefix(prefix)
.map(|(k, _)| k.clone())
.collect()
}
pub fn remove_prefix(
&mut self,
prefix: &KeyPrefix,
) -> usize {
let keys = self.keys_with_prefix(prefix);
let removed = keys.len();
for key in keys {
let _ = self.entries.remove(&key);
}
removed
}
pub fn extend<I>(
&mut self,
iter: I,
) -> Result<()>
where
I: IntoIterator<Item = Entry>,
{
for entry in iter {
self.insert(entry.key, entry.value)?;
}
Ok(())
}
#[must_use]
pub fn iter(&self) -> Iter<'_, Key, Value> {
self.entries.iter()
}
#[must_use]
pub fn iter_keys(
&self,
) -> Keys<'_, Key, Value> {
self.entries.keys()
}
#[must_use]
pub fn iter_values(
&self,
) -> Values<'_, Key, Value> {
self.entries.values()
}
#[must_use]
pub fn first(&self) -> Option<Entry> {
self.entries
.first_key_value()
.map(|(k, v)| {
Entry::new(k.clone(), v.clone())
})
}
#[must_use]
pub fn last(&self) -> Option<Entry> {
self.entries
.last_key_value()
.map(|(k, v)| {
Entry::new(k.clone(), v.clone())
})
}
#[must_use]
pub fn stats(&self) -> MapStats {
MapStats {
entry_count: self.len(),
is_empty: self.is_empty(),
}
}
#[must_use]
pub fn into_iter_owned(
self,
) -> IntoIter<Key, Value> {
self.entries.into_iter()
}
fn ensure_capacity_for_insert(
&self,
) -> Result<()> {
if self.entries.len() >= MAX_ENTRY_COUNT {
return Err(
AgentMemoryError::overflow(
"inserting beyond MAX_ENTRY_COUNT",
),
);
}
Ok(())
}
fn range_for_prefix<'a>(
&'a self,
prefix: &'a KeyPrefix,
) -> impl Iterator<
Item = (&'a Key, &'a Value),
> + 'a {
let start = Bound::Included(
Key::new(prefix.as_str())
.expect(
"validated prefix must convert to key boundary",
),
);
self.entries
.range((start, Bound::Unbounded))
.take_while(move |(key, _)| {
prefix.matches(key)
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MapStats {
pub entry_count: usize,
pub is_empty: bool,
}
impl IntoIterator for MemoryMap {
type Item = (Key, Value);
type IntoIter = IntoIter<Key, Value>;
fn into_iter(
self,
) -> Self::IntoIter {
self.entries.into_iter()
}
}
impl FromIterator<Entry> for MemoryMap {
fn from_iter<T>(
iter: T,
) -> Self
where
T: IntoIterator<Item = Entry>,
{
let mut map = Self::new();
for entry in iter {
map.entries.insert(
entry.key,
entry.value,
);
}
map
}
}