rustdis 0.1.1

A partial Redis server implementation intended purely for educational purposes
Documentation
use bytes::Bytes;
use std::collections::HashMap;
use std::ops::AddAssign;
use std::str::FromStr;

pub struct Store {
    store: HashMap<String, Bytes>,
}

impl Store {
    pub fn new() -> Store {
        Store {
            store: HashMap::new(),
        }
    }

    pub fn set(&mut self, key: String, value: Bytes) {
        self.store.insert(key, value);
    }

    pub fn get(&self, key: &str) -> Option<&Bytes> {
        self.store.get(key)
    }

    pub fn remove(&mut self, key: &str) -> Option<Bytes> {
        self.store.remove(key)
    }

    pub fn exists(&self, key: &str) -> bool {
        self.store.contains_key(key)
    }

    pub fn keys(&self) -> impl Iterator<Item = &String> {
        self.store.keys()
    }

    pub fn size(&self) -> usize {
        self.store.len()
    }

    pub fn iter(&self) -> impl Iterator<Item = (&String, &Bytes)> {
        self.store.iter()
    }

    pub fn incr_by<T>(&mut self, key: &str, increment: T) -> Result<T, String>
    where
        T: FromStr + ToString + AddAssign + Default,
    {
        let err = "value is not of the correct type or out of range".to_string();

        let mut value = match self.get(key) {
            Some(value) => match std::str::from_utf8(value.as_ref())
                .map_err(|_| err.clone())
                .and_then(|s| s.parse::<T>().map_err(|_| err.clone()))
            {
                Ok(value) => value,
                Err(e) => return Err(e),
            },
            None => T::default(),
        };

        value += increment;

        self.set(key.to_string(), value.to_string().into());

        Ok(value)
    }
}

impl Default for Store {
    fn default() -> Self {
        Self::new()
    }
}