log_kv/
lib.rs

1extern crate bincode;
2extern crate serde;
3
4use bincode::SizeLimit;
5use bincode::serde::{DeserializeError, deserialize_from, SerializeError, serialize_into};
6use serde::{Serialize, Deserialize};
7use std::{error, fmt, io};
8use std::cmp::Eq;
9use std::collections::hash_map::HashMap;
10use std::hash::Hash;
11use std::io::{Read, Write, Seek, SeekFrom, ErrorKind as IoErrorKind};
12use std::marker::PhantomData;
13
14#[derive(Debug)]
15pub enum LogKvError {
16    Io(io::Error),
17    SerializeError(SerializeError),
18    DeserializeError(DeserializeError),
19}
20
21impl fmt::Display for LogKvError {
22    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23        match *self {
24            LogKvError::Io(ref err) => write!(f, "IO error: {}", err),
25            LogKvError::SerializeError(ref err) => write!(f, "Encoding error: {}", err),
26            LogKvError::DeserializeError(ref err) => write!(f, "Decoding error: {}", err),
27        }
28    }
29}
30
31impl error::Error for LogKvError {
32    fn description(&self) -> &str {
33        match *self {
34            LogKvError::Io(ref err) => err.description(),
35            LogKvError::SerializeError(ref err) => err.description(),
36            LogKvError::DeserializeError(ref err) => err.description(),
37        }
38    }
39
40    fn cause(&self) -> Option<&error::Error> {
41        match *self {
42            LogKvError::Io(ref err) => Some(err),
43            LogKvError::SerializeError(ref err) => Some(err),
44            LogKvError::DeserializeError(ref err) => Some(err),
45        }
46    }
47}
48
49impl From<io::Error> for LogKvError {
50    fn from(err: io::Error) -> LogKvError {
51        LogKvError::Io(err)
52    }
53}
54
55impl From<SerializeError> for LogKvError {
56    fn from(err: SerializeError) -> LogKvError {
57        LogKvError::SerializeError(err)
58    }
59}
60
61impl From<DeserializeError> for LogKvError {
62    fn from(err: DeserializeError) -> LogKvError {
63        LogKvError::DeserializeError(err)
64    }
65}
66
67pub struct LogKv<K, V, T> {
68    cursor: T,
69    index: HashMap<K, u64>,
70    _phantom: PhantomData<V>,
71}
72
73impl<K, V, T> LogKv<K, V, T>
74    where K: Serialize + Deserialize + Eq + Hash,
75          V: Serialize + Deserialize,
76          T: Read + Write + Seek
77{
78    pub fn create(cursor: T) -> Result<LogKv<K, V, T>, LogKvError> {
79        let mut logkv = LogKv {
80            cursor: cursor,
81            index: HashMap::new(),
82            _phantom: PhantomData,
83        };
84
85        logkv.cursor.seek(SeekFrom::Start(0))?;
86        loop {
87            let key = match deserialize_from::<T, K>(&mut logkv.cursor, SizeLimit::Infinite) {
88                Ok(key) => key,
89                Err(DeserializeError::IoError(ref e)) if e.kind() == IoErrorKind::UnexpectedEof => {
90                    break;
91                }
92                Err(e) => return Err(LogKvError::from(e)),
93            };
94
95            let position = logkv.cursor.seek(SeekFrom::Current(0))?;
96            logkv.index.insert(key, position);
97            deserialize_from::<T, V>(&mut logkv.cursor, SizeLimit::Infinite)?;
98        }
99
100        Ok(logkv)
101    }
102
103    /// Stores a key-value pair, writing to the given Write.
104    ///
105    /// # Examples
106    ///
107    /// ```
108    /// use std::io::Cursor;
109    /// use log_kv::LogKv;
110    ///
111    /// let mut cursor = Cursor::new(Vec::new());
112    /// let mut db : LogKv<String, String, _> = LogKv::create(cursor).unwrap();
113    /// db.put("this is a key", "this is a value").unwrap();
114    /// let retrieved = db.get("this is a key").unwrap().expect("No value retrieved");
115    /// assert_eq!(retrieved, "this is a value");
116    /// ```
117    pub fn put<L : Into<K>, W : Into<V>>(&mut self, key: L, value: W) -> Result<(), LogKvError> {
118        let serialize_key = key.into();
119        serialize_into(&mut self.cursor, &serialize_key, SizeLimit::Infinite)?;
120        let position = self.cursor.seek(SeekFrom::Current(0))?;
121        self.index.insert(serialize_key, position);
122        serialize_into(&mut self.cursor, &value.into(), SizeLimit::Infinite)?;
123        Ok(())
124    }
125
126    /// Retrieves a value previously stored in the map.
127    ///
128    /// # Examples
129    ///
130    /// ```
131    /// use std::io::Cursor;
132    /// use log_kv::LogKv;
133    ///
134    /// let mut cursor = Cursor::new(Vec::new());
135    /// let mut db : LogKv<String, String, _> = LogKv::create(cursor).unwrap();
136    /// db.put("A", "a").unwrap();
137    /// db.put("B", "b").unwrap();
138    /// let retrieved = db.get("A").unwrap().expect("No value
139    /// retrieved");
140    /// assert_eq!(retrieved, "a");
141    ///
142    /// let not_found = db.get("C").unwrap();
143    /// assert_eq!(not_found.is_some(), false);
144    /// ```
145    pub fn get<L : Into<K>>(&mut self, key: L) -> Result<Option<V>, LogKvError> {
146        return match self.index.get(&key.into()) {
147            Some(position) => {
148                self.cursor.seek(SeekFrom::Start(*position))?;
149                let value = deserialize_from(&mut self.cursor, SizeLimit::Infinite)?;
150                Ok(Some(value))
151            }
152            None => Ok(None),
153        };
154    }
155}