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)
}
#[allow(dead_code)]
pub(crate) fn get_mut(&mut self, key: &Key) -> Option<&mut Value> {
self.entries.get_mut(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(|(key, value)| Entry::new(key.clone(), value.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(|(key, value)| Entry::new(key.clone(), value.clone()))
.collect()
}
#[must_use]
pub fn keys_with_prefix(&self, prefix: &KeyPrefix) -> Vec<Key> {
self.range_for_prefix(prefix)
.map(|(key, _)| key.clone())
.collect()
}
pub fn remove_prefix(&mut self, prefix: &KeyPrefix) -> usize {
let keys: Vec<Key> = 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(|(key, value)| Entry::new(key.clone(), value.clone()))
}
#[must_use]
pub fn last(&self) -> Option<Entry> {
self.entries
.last_key_value()
.map(|(key, value)| Entry::new(key.clone(), value.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 be convertible to key boundary"),
);
let end = Bound::Unbounded;
self.entries
.range((start, end))
.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: IntoIterator<Item = Entry>>(iter: T) -> Self {
let mut map = Self::new();
for entry in iter {
map.entries.insert(entry.key, entry.value);
}
map
}
}