Skip to content
Merged
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: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repository = "https://github.com/lowcarboncode/quickleaf"
readme = "README.md"

[dependencies]
valu3 = "0.6.5"
valu3 = "0.6"

[features]
default = []
Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Quickleaf Cache is a Rust library that provides a simple and efficient in-memory
- List cache entries with support for filtering, ordering, and limiting results
- Custom error handling
- Event notifications for cache operations
- Support for generic values using [valu3](https://github.com/lowcarboncode/valu3)

## Installation

Expand All @@ -18,6 +19,7 @@ Add the following to your `Cargo.toml`:
```toml
[dependencies]
quickleaf = "0.1"
valu3 = "0.1"
```

## Usage
Expand All @@ -26,6 +28,7 @@ Here's a basic example of how to use Quickleaf Cache:

```rust
use quickleaf::{Quickleaf, ListProps, Order, Filter};
use quickleaf::valu3::value::Value;

fn main() {
let mut cache = Quickleaf::new(2);
Expand All @@ -34,8 +37,8 @@ fn main() {
cache.insert("key3", 3);

assert_eq!(cache.get("key1"), None);
assert_eq!(cache.get("key2"), Some(&2));
assert_eq!(cache.get("key3"), Some(&3));
assert_eq!(cache.get("key2"), Some(&2.to_value()));
assert_eq!(cache.get("key3"), Some(&3.to_value()));

let list_props = ListProps::default()
.order(Order::Asc)
Expand Down Expand Up @@ -128,6 +131,7 @@ You can use events to get notified when cache entries are inserted, removed, or
```rust
use quickleaf::{Quickleaf, Event};
use std::sync::mpsc::channel;
use quickleaf::valu3::value::Value;

fn main() {
let (tx, rx) = channel();
Expand All @@ -150,15 +154,15 @@ fn main() {
assert_eq!(items.len(), 3);
assert_eq!(
items[0],
Event::insert("key1".to_string(), 1)
Event::insert("key1".to_string(), 1.to_value())
);
assert_eq!(
items[1],
Event::insert("key2".to_string(), 2)
Event::insert("key2".to_string(), 2.to_value())
);
assert_eq!(
items[2],
Event::insert("key3".to_string(), 3)
Event::insert("key3".to_string(), 3.to_value())
);
}
```
Expand Down
52 changes: 19 additions & 33 deletions src/cache.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::HashMap;
use std::fmt::Debug;

use valu3::traits::ToValueBehavior;
use valu3::value::Value;

use crate::error::Error;
Expand All @@ -12,27 +13,21 @@ use std::sync::mpsc::Sender;
pub type Key = String;

#[derive(Clone, Debug)]
pub struct Cache<V>
where
V: PartialEq,
{
map: HashMap<Key, V>,
pub struct Cache {
map: HashMap<Key, Value>,
list: Vec<Key>,
capacity: usize,
sender: Option<Sender<Event<V>>>,
_phantom: std::marker::PhantomData<V>,
sender: Option<Sender<Event<Value>>>,
_phantom: std::marker::PhantomData<Value>,
}

impl PartialEq for Cache<Value> {
impl PartialEq for Cache {
fn eq(&self, other: &Self) -> bool {
self.map == other.map && self.list == other.list && self.capacity == other.capacity
}
}

impl<V> Cache<V>
where
V: PartialEq + Clone,
{
impl Cache {
pub fn new(capacity: usize) -> Self {
Self {
map: HashMap::new(),
Expand All @@ -43,7 +38,7 @@ where
}
}

pub fn with_sender(capacity: usize, sender: Sender<Event<V>>) -> Self {
pub fn with_sender(capacity: usize, sender: Sender<Event<Value>>) -> Self {
Self {
map: HashMap::new(),
list: Vec::new(),
Expand All @@ -53,22 +48,22 @@ where
}
}

pub fn set_event(&mut self, sender: Sender<Event<V>>) {
pub fn set_event(&mut self, sender: Sender<Event<Value>>) {
self.sender = Some(sender);
}

pub fn remove_event(&mut self) {
self.sender = None;
}

fn send_insert(&self, key: Key, value: V) {
fn send_insert(&self, key: Key, value: Value) {
if let Some(sender) = &self.sender {
let event = Event::insert(key, value);
sender.send(event).unwrap();
}
}

fn send_remove(&self, key: Key, value: V) {
fn send_remove(&self, key: Key, value: Value) {
if let Some(sender) = &self.sender {
let event = Event::remove(key, value);
sender.send(event).unwrap();
Expand All @@ -82,9 +77,10 @@ where
}
}

pub fn insert<T>(&mut self, key: T, value: V)
pub fn insert<T, V>(&mut self, key: T, value: V)
where
T: Into<String> + Clone + AsRef<str>,
V: ToValueBehavior,
{
let key = key.into();

Expand All @@ -108,26 +104,16 @@ where
.unwrap_or(self.list.len());

self.list.insert(position, key.clone());
self.map.insert(key.clone(), value.clone().into());
self.map.insert(key.clone(), value.to_value());

self.send_insert(key, value);
self.send_insert(key, value.to_value());
}

pub fn insert_if_not_exists(&mut self, key: Key, value: V) -> Result<(), Error> {
if self.map.contains_key(&key) {
return Err(Error::SortKeyExists);
}

self.insert(key, value);

Ok(())
}

pub fn get(&self, key: &str) -> Option<&V> {
pub fn get(&self, key: &str) -> Option<&Value> {
self.map.get(key)
}

pub fn get_mut(&mut self, key: &str) -> Option<&mut V> {
pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> {
self.map.get_mut(key)
}

Expand Down Expand Up @@ -175,7 +161,7 @@ where
self.map.contains_key(key)
}

pub fn list<T>(&self, props: T) -> Result<Vec<(Key, &V)>, Error>
pub fn list<T>(&self, props: T) -> Result<Vec<(Key, &Value)>, Error>
where
T: Into<ListProps>,
{
Expand All @@ -191,7 +177,7 @@ where
&self,
mut list_iter: I,
props: ListProps,
) -> Result<Vec<(Key, &V)>, Error>
) -> Result<Vec<(Key, &Value)>, Error>
where
I: Iterator<Item = &'a Key>,
{
Expand Down
6 changes: 3 additions & 3 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ pub struct EventData<V> {
}

impl<V> Event<V> {
pub(crate) fn insert(key: Key, value: V) -> Self {
pub fn insert(key: Key, value: V) -> Self {
Self::Insert(EventData { key, value })
}

pub(crate) fn remove(key: Key, value: V) -> Self {
pub fn remove(key: Key, value: V) -> Self {
Self::Remove(EventData { key, value })
}

pub(crate) fn clear() -> Self {
pub fn clear() -> Self {
Self::Clear
}
}
38 changes: 20 additions & 18 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//! - List cache entries with support for filtering, ordering, and limiting results
//! - Custom error handling
//! - Event notifications for cache operations
//! - Support for generic values using [valu3](https://github.com/lowcarboncode/valu3)
//!
//! ## Installation
//!
Expand All @@ -18,14 +19,16 @@
//! ```toml
//! [dependencies]
//! quickleaf = "0.1"
//! valu3 = "0.1"
//! ```
//!
//! ## Usage
//!
//! Here's a basic example of how to use Quickleaf Cache:
//!
//! ```rust
//! use quickleaf::{Quickleaf, ListProps, Order, Filter};
//! use quickleaf::{Quickleaf, ListProps, Order, Filter, prelude::*};
//! use quickleaf::valu3::value::Value;
//!
//! fn main() {
//! let mut cache = Quickleaf::new(2);
Expand All @@ -34,12 +37,11 @@
//! cache.insert("key3", 3);
//!
//! assert_eq!(cache.get("key1"), None);
//! assert_eq!(cache.get("key2"), Some(&2));
//! assert_eq!(cache.get("key3"), Some(&3));
//! assert_eq!(cache.get("key2"), Some(&2.to_value()));
//! assert_eq!(cache.get("key3"), Some(&3.to_value()));
//!
//! let list_props = ListProps::default()
//! .order(Order::Asc)
//! .limit(10);
//! .order(Order::Asc);
//!
//! let result = cache.list(list_props).unwrap();
//! for (key, value) in result {
Expand All @@ -57,6 +59,7 @@
//! ```rust
//! use quickleaf::{Quickleaf, ListProps, Order, Filter};
//!
//!
//! fn main() {
//! let mut cache = Quickleaf::new(10);
//! cache.insert("apple", 1);
Expand All @@ -65,8 +68,7 @@
//!
//! let list_props = ListProps::default()
//! .order(Order::Asc)
//! .filter(Filter::StartWith("ap"))
//! .limit(10);
//! .filter(Filter::StartWith("ap"));
//!
//! let result = cache.list(list_props).unwrap();
//! for (key, value) in result {
Expand All @@ -88,8 +90,7 @@
//!
//! let list_props = ListProps::default()
//! .order(Order::Asc)
//! .filter(Filter::EndWith("apple"))
//! .limit(10);
//! .filter(Filter::EndWith("apple"));
//!
//! let result = cache.list(list_props).unwrap();
//! for (key, value) in result {
Expand All @@ -111,8 +112,7 @@
//!
//! let list_props = ListProps::default()
//! .order(Order::Asc)
//! .filter(Filter::StartAndEndWith("apple", "pie"))
//! .limit(10);
//! .filter(Filter::StartAndEndWith("apple", "pie"));
//!
//! let result = cache.list(list_props).unwrap();
//! for (key, value) in result {
Expand All @@ -126,8 +126,9 @@
//! You can use events to get notified when cache entries are inserted, removed, or cleared. Here is an example:
//!
//! ```rust
//! use quickleaf::{Quickleaf, Event};
//! use quickleaf::{Quickleaf, Event, prelude::*};
//! use std::sync::mpsc::channel;
//! use quickleaf::valu3::value::Value;
//!
//! fn main() {
//! let (tx, rx) = channel();
Expand All @@ -150,15 +151,15 @@
//! assert_eq!(items.len(), 3);
//! assert_eq!(
//! items[0],
//! Event::insert("key1".to_string(), 1)
//! Event::insert("key1".to_string(), 1.to_value())
//! );
//! assert_eq!(
//! items[1],
//! Event::insert("key2".to_string(), 2)
//! Event::insert("key2".to_string(), 2.to_value())
//! );
//! assert_eq!(
//! items[2],
//! Event::insert("key3".to_string(), 3)
//! Event::insert("key3".to_string(), 3.to_value())
//! );
//! }
//! ```
Expand All @@ -176,15 +177,16 @@ mod error;
mod event;
mod filter;
mod list_props;
pub mod prelude;
mod quickleaf;
#[cfg(test)]
mod tests;

pub use cache::Cache;
pub use error::Error;
pub use event::{Event, EventData};
pub use filter::Filter;
pub use list_props::ListProps;
pub use list_props::{ListProps, Order, StartAfter};
pub use quickleaf::Quickleaf;
pub use valu3;
pub use valu3::value::Value;

pub type Quickleaf = Cache<Value>;
1 change: 1 addition & 0 deletions src/prelude.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub use valu3::prelude::*;
2 changes: 2 additions & 0 deletions src/quickleaf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
use crate::Cache;
pub type Quickleaf = Cache;
Loading
Loading