1#![no_std]
2
3use core::str;
4use byteorder::{ByteOrder, BigEndian};
5#[cfg(feature = "postcard-values")]
6use serde::{Deserialize, Serialize};
7
8mod error;
9pub use error::{Error, ReadError, WriteError};
10mod iter;
11use iter::Iter;
12pub mod no_flash;
13mod test;
14
15pub trait StoreBackend {
17 type Data: ?Sized + AsRef<[u8]>;
19
20 fn data(&self) -> &Self::Data;
22 fn len(&self) -> usize {
24 self.data().as_ref().len()
25 }
26
27 type Error;
29 fn erase(&mut self) -> Result<(), Self::Error>;
31 fn program(&mut self, offset: usize, payload: &[u8]) -> Result<(), Self::Error>;
33 fn program_done(&mut self) {}
35
36 fn backup_space(&self) -> &'static mut [u8];
40}
41
42pub struct Store<B: StoreBackend> {
44 backend: B,
45}
46
47impl<B: StoreBackend> Store<B> {
48 pub fn new(backend: B) -> Self {
50 Store { backend }
51 }
52
53 pub fn read(&self, key: &str) -> Result<Option<&[u8]>, ReadError> {
55 let mut iter = Iter::new(self.backend.data().as_ref());
56 let mut value = None;
57 while let Some(result) = iter.next() {
58 let (record_key, record_value) = result?;
59 if key.as_bytes() == record_key {
60 value = Some(record_value)
62 }
63 }
64 Ok(value)
65 }
66
67 pub fn read_str(&self, key: &str) -> Result<Option<&str>, ReadError> {
69 self.read(key)
70 .and_then(|value| value
71 .map(|value| str::from_utf8(value)
72 .map_err(ReadError::Utf8Error)
73 )
74 .transpose()
75 )
76 }
77
78 #[cfg(feature = "postcard-values")]
80 pub fn read_value<'a, T: Deserialize<'a>>(&'a self, key: &str) -> Result<Option<T>, Error<B::Error>> {
81 self.read(key)?
82 .map(
83 |data| postcard::from_bytes(data)
84 .map_err(Error::Decode)
85 ).transpose()
86 }
87
88 pub fn get_bytes_used(&self) -> Result<usize, ReadError> {
92 let mut iter = Iter::new(self.backend.data().as_ref());
93 while let Some(result) = iter.next() {
94 let _ = result?;
95 }
96 Ok(iter.offset)
97 }
98
99 unsafe fn append_at(&mut self, mut offset: usize,
100 key: &[u8], value: &[u8]) -> Result<usize, WriteError<B::Error>> {
101 let record_size = 4 + key.len() + 1 + value.len();
102 if offset + record_size > self.backend.len() {
103 return Err(WriteError::SpaceExhausted)
104 }
105
106 let mut record_size_bytes = [0u8; 4];
107 BigEndian::write_u32(&mut record_size_bytes[..], record_size as u32);
108
109 {
110 let mut write = |payload| -> Result<(), WriteError<B::Error>> {
111 self.backend.program(offset, payload)
112 .map_err(WriteError::Backend)?;
113 offset += payload.len();
114 Ok(())
115 };
116
117 write(&record_size_bytes[..])?;
118 write(key)?;
119 write(&[0])?;
120 write(value)?;
121 }
122 self.backend.program_done();
123
124 Ok(offset)
125 }
126
127 fn compact(&mut self) -> Result<(), Error<B::Error>> {
128 let old_data = self.backend.backup_space();
129 old_data.copy_from_slice(self.backend.data().as_ref());
130
131 self.erase()?;
132
133 let mut offset = 0;
136 let mut iter = Iter::new(old_data.as_ref());
137 'iter: while let Some(result) = iter.next() {
138 let (key, value) = result?;
139 if value.is_empty() {
140 continue
142 }
143
144 let mut next_iter = iter.clone();
145 while let Some(next_result) = next_iter.next() {
146 let (next_key, _) = next_result?;
147 if key == next_key {
148 continue 'iter
150 }
151 }
152 offset = unsafe { self.append_at(offset, key, value)? };
153 }
154
155 Ok(())
156 }
157
158 fn append(&mut self, key: &str, value: &[u8]) -> Result<(), Error<B::Error>> {
159 let free_offset = {
160 let mut iter = Iter::new(self.backend.data().as_ref());
161 let mut not_modified = false;
162 while let Some(result) = iter.next() {
163 let (record_key, record_value) = result?;
164 if key.as_bytes() == record_key {
165 not_modified = value == record_value;
166 }
167 }
168 if not_modified {
169 return Ok(())
170 }
171 iter.offset
172 };
173
174 unsafe { self.append_at(free_offset, key.as_bytes(), value)? };
175 Ok(())
176 }
177
178 pub fn write<V: AsRef<[u8]>>(&mut self, key: &str, value: V) -> Result<(), Error<B::Error>> {
180 let value = value.as_ref();
181 match self.append(key, value) {
182 Err(Error::Write(WriteError::SpaceExhausted)) => {
183 self.compact()?;
184 self.append(key, value)
185 }
186 res => res
187 }
188 }
189
190 #[cfg(feature = "postcard-values")]
192 pub fn write_value<T, V>(&mut self, key: &str, value: &T, mut value_buf: V) -> Result<(), Error<B::Error>>
193 where
194 T: Serialize,
195 V: AsMut<[u8]>,
196 {
197 let data = postcard::to_slice(value, value_buf.as_mut())
198 .map_err(Error::Encode)?;
199 self.write(key, data)
200 }
201
202 pub fn remove(&mut self, key: &str) -> Result<(), Error<B::Error>> {
204 self.write(key, &[])
205 }
206
207 pub fn erase(&mut self) -> Result<(), WriteError<B::Error>> {
209 self.backend.erase()
210 .map_err(WriteError::Backend)?;
211
212 Ok(())
213 }
214}