kernel/hil/
kv.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2023.
4
5//! Interface for Key-Value (KV) Stores
6//!
7//! The KV store implementation in Tock has two levels:
8//!
9//! 1. **KV Level**: This level provides a standard key-value interface with
10//!    common get/set/add/update/delete operations.
11//!
12//! 2. **KV Permissions Level**: This level mirrors the `KV` interface, but each
13//!    call requires storage permissions. This permits implementing access
14//!    control permissions with key-value stores in Tock.
15//!
16//! The expected setup inside Tock will look like this:
17//!
18//! ```text
19//! +-----------------------+
20//! |  Capsule using K-V    |
21//! +-----------------------+
22//!
23//!    hil::kv::KVPermissions (this file)
24//!
25//! +-----------------------+
26//! |  K-V in Tock          |
27//! +-----------------------+
28//!
29//!    hil::kv::KV (this file)
30//!
31//! +-----------------------+
32//! |  K-V library          |
33//! +-----------------------+
34//!
35//!    hil::flash
36//! ```
37
38use crate::storage_permissions::StoragePermissions;
39use crate::utilities::leasable_buffer::SubSliceMut;
40use crate::ErrorCode;
41
42/// Callback trait for KV stores.
43///
44/// Implement this trait and use `set_client()` to receive callbacks.
45pub trait KVClient {
46    /// This callback is called when the get operation completes.
47    ///
48    /// If there wasn't enough room to store the entire buffer `SIZE` will be
49    /// returned in `result` and the bytes that did fit will be copied into the
50    /// buffer.
51    ///
52    /// ### Return Values
53    ///
54    /// - `result`: `Ok(())` on success
55    /// - `Err(ErrorCode)` on error. Valid `ErrorCode`s:
56    ///   - `SIZE`: The value is longer than the provided buffer. The amount of
57    ///     the value that fits in the buffer is provided.
58    ///   - `NOSUPPORT`: The key could not be found or the caller does not have
59    ///     permission to read this key. The data in the `value` buffer is
60    ///     meaningless.
61    ///   - `FAIL`: An internal error occurred and the operation cannot be
62    ///     completed.
63    /// - `key`: The key buffer.
64    /// - `value`: The value buffer.
65    fn get_complete(
66        &self,
67        result: Result<(), ErrorCode>,
68        key: SubSliceMut<'static, u8>,
69        value: SubSliceMut<'static, u8>,
70    );
71
72    /// This callback is called when the set operation completes.
73    ///
74    /// ### Return Values
75    ///
76    /// - `result`: `Ok(())` on success, `Err(ErrorCode)` on error. Valid
77    ///   `ErrorCode`s:
78    ///   - `NOSUPPORT`: The caller does not have permission to store this key.
79    ///   - `NOMEM`: The key could not be set because the KV store is full.
80    ///   - `SIZE`: The key could not be set because the key or value is too
81    ///     many bytes.
82    ///   - `FAIL`: An internal error occurred and the operation cannot be
83    ///     completed.
84    /// - `key`: The key buffer.
85    /// - `value`: The value buffer.
86    fn set_complete(
87        &self,
88        result: Result<(), ErrorCode>,
89        key: SubSliceMut<'static, u8>,
90        value: SubSliceMut<'static, u8>,
91    );
92
93    /// This callback is called when the add operation completes.
94    ///
95    /// ### Return Values
96    ///
97    /// - `result`: `Ok(())` on success, `Err(ErrorCode)` on error. Valid
98    ///   `ErrorCode`s:
99    ///   - `NOSUPPORT`: The key already exists and cannot be added.
100    ///   - `NOMEM`: The key could not be added because the KV store is full.
101    ///   - `SIZE`: The key could not be set because the key or value is too
102    ///     many bytes.
103    ///   - `FAIL`: An internal error occurred and the operation cannot be
104    ///     completed.
105    /// - `key`: The key buffer.
106    /// - `value`: The value buffer.
107    fn add_complete(
108        &self,
109        result: Result<(), ErrorCode>,
110        key: SubSliceMut<'static, u8>,
111        value: SubSliceMut<'static, u8>,
112    );
113
114    /// This callback is called when the update operation completes.
115    ///
116    /// ### Return Values
117    ///
118    /// - `result`: `Ok(())` on success, `Err(ErrorCode)` on error. Valid
119    ///   `ErrorCode`s:
120    ///   - `NOSUPPORT`: The key does not already exist and cannot be modified
121    ///     or the caller does not have permission to modify this key.
122    ///   - `NOMEM`: The key could not be updated because the KV store is full.
123    ///   - `SIZE`: The key could not be set because the key or value is too
124    ///     many bytes.
125    ///   - `FAIL`: An internal error occurred and the operation cannot be
126    ///     completed.
127    /// - `key`: The key buffer.
128    /// - `value`: The value buffer.
129    fn update_complete(
130        &self,
131        result: Result<(), ErrorCode>,
132        key: SubSliceMut<'static, u8>,
133        value: SubSliceMut<'static, u8>,
134    );
135
136    /// This callback is called when the delete operation completes.
137    ///
138    /// ### Return Values
139    ///
140    /// - `result`: `Ok(())` on success, `Err(ErrorCode)` on error. Valid
141    ///   `ErrorCode`s:
142    ///   - `NOSUPPORT`: The key does not exist or the caller does not have
143    ///     permission to delete this key.
144    ///   - `FAIL`: An internal error occurred and the operation cannot be
145    ///     completed.
146    /// - `key`: The key buffer.
147    fn delete_complete(&self, result: Result<(), ErrorCode>, key: SubSliceMut<'static, u8>);
148
149    /// This callback is called when the garbage collection operation completes.
150    ///
151    /// ### Return Values
152    ///
153    /// - `result`: `Ok(())` on success, `Err(ErrorCode)` on error. Valid
154    ///   `ErrorCode`s:
155    ///   - `FAIL`: An internal error occurred and the operation cannot be
156    ///     completed.
157    fn garbage_collection_complete(&self, result: Result<(), ErrorCode>);
158}
159
160/// Key-Value interface with permissions.
161///
162/// This interface provides access to key-value storage with access control.
163/// Each object is marked with a `write_id` (based on the `StoragePermissions`
164/// used to create it), and all further accesses and modifications to that
165/// object require suitable permissions.
166pub trait KVPermissions<'a> {
167    /// Configure the client for operation callbacks.
168    fn set_client(&self, client: &'a dyn KVClient);
169
170    /// Retrieve a value based on the given key.
171    ///
172    /// ### Arguments
173    ///
174    /// - `key`: The key to identify the k-v pair.
175    /// - `value`: Where the returned value buffer will be stored.
176    /// - `permissions`: The read/write/modify permissions for this access.
177    ///
178    /// ### Return
179    ///
180    /// - On success returns `Ok(())`. A callback will be issued.
181    /// - On error, returns the buffers and:
182    ///   - `BUSY`: An operation is already in progress.
183    ///   - `FAIL`: An internal error occurred and the operation cannot be
184    ///     completed.
185    fn get(
186        &self,
187        key: SubSliceMut<'static, u8>,
188        value: SubSliceMut<'static, u8>,
189        permissions: StoragePermissions,
190    ) -> Result<
191        (),
192        (
193            SubSliceMut<'static, u8>,
194            SubSliceMut<'static, u8>,
195            ErrorCode,
196        ),
197    >;
198
199    /// Store a value based on the given key. If the key does not exist it will
200    /// be added. If the key already exists the value will be updated.
201    ///
202    /// The `value` buffer must have room for a header.
203    ///
204    /// ### Arguments
205    ///
206    /// - `key`: The key to identify the k-v pair.
207    /// - `value`: The value to store. The provided buffer MUST start
208    ///   `KVPermissions.header_size()` bytes after the beginning of the buffer
209    ///   to enable the implementation to insert a header.
210    /// - `permissions`: The read/write/modify permissions for this access.
211    ///
212    /// ### Return
213    ///
214    /// - On success returns `Ok(())`. A callback will be issued.
215    /// - On error, returns the buffers and:
216    ///   - `BUSY`: An operation is already in progress.
217    ///   - `SIZE`: There is insufficient room to include the permission header
218    ///     in the `value` buffer or the key/value is too large to store.
219    ///   - `INVAL`: The caller does not have write permissions.
220    ///   - `FAIL`: An internal error occurred and the operation cannot be
221    ///     completed.
222    fn set(
223        &self,
224        key: SubSliceMut<'static, u8>,
225        value: SubSliceMut<'static, u8>,
226        permissions: StoragePermissions,
227    ) -> Result<
228        (),
229        (
230            SubSliceMut<'static, u8>,
231            SubSliceMut<'static, u8>,
232            ErrorCode,
233        ),
234    >;
235
236    /// Store a new value based on the given key. If the key does not exist it
237    /// will be added. If the key already exists an error callback will be
238    /// provided.
239    ///
240    /// The `value` buffer must have room for a header.
241    ///
242    /// ### Arguments
243    ///
244    /// - `key`: The key to identify the k-v pair.
245    /// - `value`: The value to store. The provided buffer MUST start
246    ///   `KVPermissions.header_size()` bytes after the beginning of the buffer
247    ///   to enable the implementation to insert a header.
248    /// - `permissions`: The read/write/modify permissions for this access.
249    ///
250    /// ### Return
251    ///
252    /// - On success returns `Ok(())`. A callback will be issued.
253    /// - On error, returns the buffers and:
254    ///   - `BUSY`: An operation is already in progress.
255    ///   - `SIZE`: There is insufficient room to include the permission header
256    ///     in the `value` buffer or the key/value is too large to store.
257    ///   - `INVAL`: The caller does not have write permissions.
258    ///   - `FAIL`: An internal error occurred and the operation cannot be
259    ///     completed.
260    fn add(
261        &self,
262        key: SubSliceMut<'static, u8>,
263        value: SubSliceMut<'static, u8>,
264        permissions: StoragePermissions,
265    ) -> Result<
266        (),
267        (
268            SubSliceMut<'static, u8>,
269            SubSliceMut<'static, u8>,
270            ErrorCode,
271        ),
272    >;
273
274    /// Modify a value based on the given key. If the key does not exist it an
275    /// error callback will be provided.
276    ///
277    /// The `value` buffer must have room for a header.
278    ///
279    /// ### Arguments
280    ///
281    /// - `key`: The key to identify the k-v pair.
282    /// - `value`: The value to store. The provided buffer MUST start
283    ///   `KVPermissions.header_size()` bytes after the beginning of the buffer
284    ///   to enable the implementation to insert a header.
285    /// - `permissions`: The read/write/modify permissions for this access.
286    ///
287    /// ### Return
288    ///
289    /// - On success returns `Ok(())`. A callback will be issued.
290    /// - On error, returns the buffers and:
291    ///   - `BUSY`: An operation is already in progress.
292    ///   - `SIZE`: There is insufficient room to include the permission header
293    ///     in the `value` buffer or the key/value is too large to store.
294    ///   - `INVAL`: The caller does not have write permissions.
295    ///   - `FAIL`: An internal error occurred and the operation cannot be
296    ///     completed.
297    fn update(
298        &self,
299        key: SubSliceMut<'static, u8>,
300        value: SubSliceMut<'static, u8>,
301        permissions: StoragePermissions,
302    ) -> Result<
303        (),
304        (
305            SubSliceMut<'static, u8>,
306            SubSliceMut<'static, u8>,
307            ErrorCode,
308        ),
309    >;
310
311    /// Delete a key-value object based on the given key.
312    ///
313    /// ### Arguments
314    ///
315    /// - `key`: The key to identify the k-v pair.
316    /// - `permissions`: The read/write/modify permissions for this access.
317    ///
318    /// ### Return
319    ///
320    /// - On success returns `Ok(())`. A callback will be issued.
321    /// - On error, returns the buffers and:
322    ///   - `BUSY`: An operation is already in progress.
323    ///   - `INVAL`: The caller does not have modify permissions.
324    ///   - `FAIL`: An internal error occurred and the operation cannot be
325    ///     completed.
326    fn delete(
327        &self,
328        key: SubSliceMut<'static, u8>,
329        permissions: StoragePermissions,
330    ) -> Result<(), (SubSliceMut<'static, u8>, ErrorCode)>;
331
332    /// Run garbage collection on the underlying Key/Value store.
333    ///
334    /// This is generally used to reclaim keys that have been removed with
335    /// the `delete()` call.
336    ///
337    /// ### Return
338    ///
339    /// - On success returns `Ok(())`. A callback will be issued.
340    /// - On error, returns the buffers and:
341    ///   - `BUSY`: An operation is already in progress.
342    ///   - `FAIL`: An internal error occurred and the operation cannot be
343    ///     completed.
344    fn garbage_collect(&self) -> Result<(), ErrorCode>;
345
346    /// Returns the length of the key-value store's header in bytes.
347    ///
348    /// Room for this header must be accommodated in a `set`, `add`, or `update`
349    /// operation.
350    fn header_size(&self) -> usize;
351}
352
353/// Key-Value interface.
354///
355/// This interface provides access to key-value storage.
356///
357/// `KV` includes five typical commands:
358/// - `get(key) -> value`
359/// - `set(key, value)`
360/// - `add(key, value)`
361/// - `update(key, value)`
362/// - `delete(key)`
363pub trait KV<'a> {
364    /// Configure the client for operation callbacks.
365    fn set_client(&self, client: &'a dyn KVClient);
366
367    /// Retrieve a value based on the given key.
368    ///
369    /// ### Arguments
370    ///
371    /// - `key`: The key to identify the k-v pair.
372    /// - `value`: Where the returned value buffer will be stored.
373    ///
374    /// ### Return
375    ///
376    /// - On success returns `Ok(())`. A callback will be issued.
377    /// - On error, returns the buffers and:
378    ///   - `BUSY`: An operation is already in progress.
379    ///   - `FAIL`: An internal error occurred and the operation cannot be
380    ///     completed.
381    fn get(
382        &self,
383        key: SubSliceMut<'static, u8>,
384        value: SubSliceMut<'static, u8>,
385    ) -> Result<
386        (),
387        (
388            SubSliceMut<'static, u8>,
389            SubSliceMut<'static, u8>,
390            ErrorCode,
391        ),
392    >;
393
394    /// Store a value based on the given key. If the key does not exist it will
395    /// be added. If the key already exists the value will be updated.
396    ///
397    /// The `value` buffer must have room for a header.
398    ///
399    /// ### Arguments
400    ///
401    /// - `key`: The key to identify the k-v pair.
402    /// - `value`: The value to store.
403    ///
404    /// ### Return
405    ///
406    /// - On success returns `Ok(())`. A callback will be issued.
407    /// - On error, returns the buffers and:
408    ///   - `BUSY`: An operation is already in progress.
409    ///   - `SIZE`: The key/value is too large to store.
410    ///   - `FAIL`: An internal error occurred and the operation cannot be
411    ///     completed.
412    fn set(
413        &self,
414        key: SubSliceMut<'static, u8>,
415        value: SubSliceMut<'static, u8>,
416    ) -> Result<
417        (),
418        (
419            SubSliceMut<'static, u8>,
420            SubSliceMut<'static, u8>,
421            ErrorCode,
422        ),
423    >;
424
425    /// Store a new value based on the given key. If the key does not exist it
426    /// will be added. If the key already exists an error callback will be
427    /// provided.
428    ///
429    /// The `value` buffer must have room for a header.
430    ///
431    /// ### Arguments
432    ///
433    /// - `key`: The key to identify the k-v pair.
434    /// - `value`: The value to store.
435    ///
436    /// ### Return
437    ///
438    /// - On success returns `Ok(())`. A callback will be issued.
439    /// - On error, returns the buffers and:
440    ///   - `BUSY`: An operation is already in progress.
441    ///   - `SIZE`: The key/value is too large to store.
442    ///   - `FAIL`: An internal error occurred and the operation cannot be
443    ///     completed.
444    fn add(
445        &self,
446        key: SubSliceMut<'static, u8>,
447        value: SubSliceMut<'static, u8>,
448    ) -> Result<
449        (),
450        (
451            SubSliceMut<'static, u8>,
452            SubSliceMut<'static, u8>,
453            ErrorCode,
454        ),
455    >;
456
457    /// Modify a value based on the given key. If the key does not exist it an
458    /// error callback will be provided.
459    ///
460    /// The `value` buffer must have room for a header.
461    ///
462    /// ### Arguments
463    ///
464    /// - `key`: The key to identify the k-v pair.
465    /// - `value`: The value to store.
466    ///
467    /// ### Return
468    ///
469    /// - On success returns `Ok(())`. A callback will be issued.
470    /// - On error, returns the buffers and:
471    ///   - `BUSY`: An operation is already in progress.
472    ///   - `SIZE`: The key/value is too large to store.
473    ///   - `FAIL`: An internal error occurred and the operation cannot be
474    ///     completed.
475    fn update(
476        &self,
477        key: SubSliceMut<'static, u8>,
478        value: SubSliceMut<'static, u8>,
479    ) -> Result<
480        (),
481        (
482            SubSliceMut<'static, u8>,
483            SubSliceMut<'static, u8>,
484            ErrorCode,
485        ),
486    >;
487
488    /// Delete a key-value object based on the given key.
489    ///
490    /// ### Arguments
491    ///
492    /// - `key`: The key to identify the k-v pair.
493    ///
494    /// ### Return
495    ///
496    /// - On success returns `Ok(())`. A callback will be issued.
497    /// - On error, returns the buffers and:
498    ///   - `BUSY`: An operation is already in progress.
499    ///   - `FAIL`: An internal error occurred and the operation cannot be
500    ///     completed.
501    fn delete(
502        &self,
503        key: SubSliceMut<'static, u8>,
504    ) -> Result<(), (SubSliceMut<'static, u8>, ErrorCode)>;
505
506    /// Run garbage collection on the underlying Key/Value store.
507    ///
508    /// This is generally used to reclaim keys that have been removed with
509    /// the `delete()` call.
510    ///
511    /// ### Return
512    ///
513    /// - On success returns `Ok(())`. A callback will be issued.
514    /// - On error, returns the buffers and:
515    ///   - `BUSY`: An operation is already in progress.
516    ///   - `FAIL`: An internal error occurred and the operation cannot be
517    ///     completed.
518    fn garbage_collect(&self) -> Result<(), ErrorCode>;
519}