Skip to main content

ove/
nvs.rs

1// Copyright (C) 2026 Kamil Lulko <kamil.lulko@gmail.com>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4//
5// This file is part of oveRTOS.
6
7//! Non-Volatile Storage (NVS) subsystem for oveRTOS.
8//!
9//! Provides key-value persistence backed by flash or EEPROM. All keys must be
10//! null-terminated byte slices (e.g. `b"my_key\0"`).
11
12use crate::bindings;
13use crate::error::{Error, Result};
14
15// SAFETY (module-wide contract for the `unsafe { bindings::ove_*(...) }` FFI
16// calls below): any handle passed to the C API is non-null and refers to a
17// live RTOS object — wrapper constructors establish validity via
18// `Error::from_code`, and `Drop` (or an explicit `deinit`) is the only place
19// a handle is released. Pointer and slice arguments reference caller-owned
20// memory valid for the duration of the call; the C side copies whatever it
21// retains and does not alias them past return (verified against the
22// signatures in `include/ove/*.h`). Blocks that deviate — `transmute`, raw
23// pointer casts from user data, slice reconstruction via `from_raw_parts`,
24// or storing a callback across the FFI boundary — carry their own
25// `// SAFETY:` comment.
26
27/// Initialize the NVS subsystem.
28///
29/// Must be called once before any `read`, `write`, or `erase` operations.
30///
31/// # Errors
32/// Returns an error if the underlying storage backend fails to initialize.
33pub fn init() -> Result<()> {
34    let rc = unsafe { bindings::ove_nvs_init() };
35    Error::from_code(rc)
36}
37
38/// Read a value from NVS into `buf`. `key` must be `\0`-terminated.
39///
40/// Returns the number of bytes actually read, which may be less than `buf.len()`
41/// if the stored value is shorter.
42///
43/// # Errors
44/// Returns [`Error::NotFound`] if the key does not exist, or another error
45/// if the read fails.
46pub fn read(key: &[u8], buf: &mut [u8]) -> Result<usize> {
47    let mut out_len: usize = 0;
48    let rc = unsafe {
49        bindings::ove_nvs_read(
50            key.as_ptr() as *const _,
51            buf.as_mut_ptr() as *mut _,
52            buf.len(),
53            &mut out_len,
54        )
55    };
56    Error::from_code(rc)?;
57    Ok(out_len)
58}
59
60/// Write `data` under `key` in NVS. `key` must be `\0`-terminated.
61///
62/// If the key already exists its value is replaced.
63///
64/// # Errors
65/// Returns [`Error::NoMemory`] if storage is full, or another error on failure.
66pub fn write(key: &[u8], data: &[u8]) -> Result<()> {
67    let rc = unsafe {
68        bindings::ove_nvs_write(
69            key.as_ptr() as *const _,
70            data.as_ptr() as *const _,
71            data.len(),
72        )
73    };
74    Error::from_code(rc)
75}
76
77/// Erase the entry for `key` from NVS. `key` must be `\0`-terminated.
78///
79/// No-op when the key does not exist (the C API treats erase-of-missing
80/// as success).
81///
82/// # Errors
83/// Returns an error if the underlying storage backend reports a failure.
84pub fn erase(key: &[u8]) -> Result<()> {
85    let rc = unsafe { bindings::ove_nvs_erase(key.as_ptr() as *const _) };
86    Error::from_code(rc)
87}