zerodds_flatdata/backend.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3//! `SlotBackend`-Trait — abstrahiert das Slot-Storage-Backend.
4//!
5//! ADR-0003: drei produktive Backends — in-memory (Default fuer
6//! Tests + Single-Process), POSIX shm/mmap (Cross-Process Same-Host
7//! per `posix-mmap`-Feature), Iceoryx2 (optionale Bridge per
8//! `iceoryx2-bridge`-Feature). Alle drei implementieren denselben
9//! Trait, sodass `FlatWriter`/`FlatReader` generisch ueber dem
10//! Backend sind.
11
12use alloc::vec::Vec;
13
14use crate::allocator::{SlotError, SlotHandle};
15use crate::slot::{ReaderMask, SlotHeader};
16
17/// Backend-Trait fuer SHM-Slot-Allocator.
18///
19/// Implementer:
20/// - [`crate::InMemorySlotAllocator`] — In-Memory-Backend, Default
21/// fuer Single-Process-Tests und als Referenz-Implementation.
22/// - `PosixSlotAllocator` — POSIX-`shm_open` + `mmap`,
23/// Cross-Process-Same-Host (Feature `posix-mmap`).
24/// - `Iceoryx2SlotAdapter` — Iceoryx2-Bridge (optional Feature
25/// `iceoryx2-bridge`).
26pub trait SlotBackend: Send + Sync {
27 /// Reserviert einen freien Slot. Caller schreibt danach via
28 /// `commit_slot` und veroeffentlicht damit das Sample.
29 ///
30 /// # Errors
31 /// `NoFreeSlot` wenn alle Slots geloant oder unfertig.
32 fn reserve_slot(&self, active_readers_mask: ReaderMask) -> Result<SlotHandle, SlotError>;
33
34 /// Schreibt sample-bytes in den Slot und setzt SlotHeader
35 /// `{ sn, sample_size, reader_mask=0 }`. Liefert die SN.
36 ///
37 /// # Errors
38 /// `OutOfBounds`, `SampleTooLarge`, oder Lock-Poison.
39 fn commit_slot(&self, handle: SlotHandle, bytes: &[u8]) -> Result<u32, SlotError>;
40
41 /// Verwirft einen Loan ohne Commit. Slot wird wieder frei.
42 ///
43 /// # Errors
44 /// `OutOfBounds` oder Lock-Poison.
45 fn discard_slot(&self, handle: SlotHandle) -> Result<(), SlotError>;
46
47 /// Liest Slot-Header + Daten-Bytes (kopiert).
48 ///
49 /// # Errors
50 /// `OutOfBounds` oder Lock-Poison.
51 fn read_slot(&self, handle: SlotHandle) -> Result<(SlotHeader, Vec<u8>), SlotError>;
52
53 /// Setzt das Bit `reader_index` im `reader_mask` des Slots
54 /// (Reader hat gelesen).
55 ///
56 /// # Errors
57 /// `OutOfBounds` oder Lock-Poison.
58 fn mark_read(&self, handle: SlotHandle, reader_index: u8) -> Result<(), SlotError>;
59
60 /// Setzt das `reader_index`-Bit retroaktiv auf allen Slots
61 /// (SPDP-Lease-Expiry).
62 ///
63 /// # Errors
64 /// Lock-Poison.
65 fn mark_reader_disconnected(&self, reader_index: u8) -> Result<(), SlotError>;
66
67 /// Anzahl konfigurierter Slots.
68 ///
69 /// # Errors
70 /// Lock-Poison.
71 fn slot_count(&self) -> Result<usize, SlotError>;
72
73 /// Gesamt-Slot-Groesse (Header + Daten + Padding); fuer Discovery.
74 fn slot_total_size(&self) -> usize;
75
76 /// Daten-Bereich pro Slot (ohne Header, ohne Padding).
77 fn slot_capacity(&self) -> usize;
78
79 /// Spec §6.1: TYPE_HASH des Topic-Type, falls dem Backend
80 /// bekannt. `None` = Backend trackt keinen Hash; Caller muss
81 /// auf andere Weise (z.B. Discovery) verifizieren. Default: None.
82 fn type_hash(&self) -> Option<[u8; 16]> {
83 None
84 }
85}