Skip to main content

ove/
containers.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//! Fixed-capacity containers re-exported from [`heapless`].
8//!
9//! These containers compile in both heap and zeroheap modes because their
10//! capacity is a const generic and their storage is owned in the type — no
11//! global allocator is ever consulted.  Use them for general-purpose
12//! collections (resizable vectors, fixed strings, hashmaps, deques) that
13//! complement the RTOS-aware primitives (`ove::Queue`, `ove::Stream`).
14//!
15//! ```no_run
16//! use ove::containers::{Vec, String};
17//! use ove::containers::ContainerExt;
18//!
19//! let mut buf: Vec<u8, 64> = Vec::new();
20//! let _ = buf.ove_push(0xAB);   // Result<(), ove::Error>
21//!
22//! let mut name: String<32> = String::new();
23//! let _ = name.push_str("hello");
24//! ```
25//!
26//! ## Choosing between `ove::heap::Vec` and `ove::containers::Vec`
27//!
28//! - [`crate::heap::Vec`] (re-exported from `alloc::vec::Vec`) is a
29//!   growable vector backed by the global allocator.  Available only when
30//!   the `alloc` (or `std`) feature is enabled and a `#[global_allocator]`
31//!   is registered.  Cannot be used in zeroheap mode.
32//!
33//! - [`Vec<T, N>`](Vec) from this module is fixed-capacity; capacity is
34//!   a const generic and storage lives inline in the type.  Always
35//!   available, in both heap and zeroheap modes.  Fallible: `push`
36//!   returns `Result<(), T>`; the [`ContainerExt::ove_push`] adapter
37//!   converts that into [`crate::Error::NoMemory`] for consistency with
38//!   the rest of the binding's error type.
39//!
40//! ## What is intentionally **not** re-exported
41//!
42//! - `heapless::spsc::Queue` and `heapless::mpmc::Q*` overlap semantically
43//!   with [`crate::Queue`] (the kernel-aware FIFO).  Apps that explicitly
44//!   want a lock-free SPSC ring should reach into `heapless::spsc` directly
45//!   — the extra import documents the intent.
46
47pub use heapless::{
48    Deque, HistoryBuf, IndexMap, IndexSet, LinearMap, String, Vec, binary_heap, sorted_linked_list,
49};
50
51// `heapless::pool` is gated on architecture features (arm_llsc / 32- or
52// 64-bit non-atomic-blocked targets); reach into `heapless::pool` directly
53// from app code where supported, instead of relying on a re-export here
54// that would fail to compile on hosts without those features.
55
56use crate::{Error, Result};
57
58/// Adapter trait that maps a [`heapless`] container's capacity-overflow
59/// return into an [`crate::Error::NoMemory`].  Use the `ove_*` methods when
60/// you want the result to flow through the same `?` chain as other
61/// `ove::Result` calls.
62///
63/// The native `heapless` API is also available — pick whichever is clearer
64/// at the call site.  The adapter discards the rejected element on
65/// overflow; if you need to recover it, use the underlying `push` /
66/// `push_back` directly.
67pub trait ContainerExt<T> {
68    /// Append `item`, returning [`crate::Error::NoMemory`] when full.
69    fn ove_push(&mut self, item: T) -> Result<()>;
70}
71
72impl<T, const N: usize> ContainerExt<T> for Vec<T, N> {
73    #[inline]
74    fn ove_push(&mut self, item: T) -> Result<()> {
75        self.push(item).map_err(|_| Error::NoMemory)
76    }
77}
78
79impl<T, const N: usize> ContainerExt<T> for Deque<T, N> {
80    #[inline]
81    fn ove_push(&mut self, item: T) -> Result<()> {
82        self.push_back(item).map_err(|_| Error::NoMemory)
83    }
84}
85
86/// Append a string slice to a fixed-capacity [`String`], returning
87/// [`crate::Error::NoMemory`] when the buffer is full.
88#[inline]
89pub fn ove_push_str<const N: usize>(s: &mut String<N>, value: &str) -> Result<()> {
90    s.push_str(value).map_err(|_| Error::NoMemory)
91}