mirror of
https://github.com/ruvnet/RuView
synced 2026-07-30 18:41:42 +00:00
1e684cb208
First implementation milestone for the rvCSI edge RF sensing runtime:
- rvcsi-core — the foundation: CsiFrame/CsiWindow/CsiEvent normalized schema,
ValidationStatus, AdapterProfile, CsiSource plugin trait, id newtypes +
IdGenerator, RvcsiError, and the validate_frame pipeline (length/finiteness/
subcarrier/RSSI/monotonicity hard checks + multiplicative quality scoring →
Accepted/Degraded/Recovered/Rejected). 29 unit tests, forbid(unsafe_code).
- rvcsi-adapter-nexmon — the napi-c boundary: native/rvcsi_nexmon_shim.{c,h}
(the only C in the runtime, allocation-free, bounds-checked, parses/writes a
byte-defined "rvCSI Nexmon record" — a normalized superset of the nexmon_csi
UDP payload), compiled via build.rs + cc, wrapped by a documented ffi module
and a NexmonAdapter implementing CsiSource. 9 tests round-tripping through C.
- Workspace registration in v2/Cargo.toml (8 new members + napi/cc workspace
deps) and compiling skeletons for rvcsi-dsp, rvcsi-events, rvcsi-adapter-file,
rvcsi-ruvector, rvcsi-node (napi-rs cdylib + build.rs napi_build::setup) and
rvcsi-cli (`rvcsi` binary) — to be filled in by the implementation swarm.
cargo build -p rvcsi-core -p rvcsi-adapter-nexmon -p rvcsi-node -p rvcsi-cli: OK
cargo test -p rvcsi-core -p rvcsi-adapter-nexmon: 38 passed, 0 failed
https://claude.ai/code/session_01CdYAPvRTjcch6YrYf42n1z
87 lines
2.6 KiB
Rust
87 lines
2.6 KiB
Rust
//! Error type for the rvCSI runtime.
|
|
|
|
use thiserror::Error;
|
|
|
|
use crate::validation::ValidationError;
|
|
|
|
/// Errors surfaced by the rvCSI core, adapters, DSP and event pipeline.
|
|
///
|
|
/// Parser failures are structured (never panics, never raw pointers across
|
|
/// boundaries — ADR-095 D6). A `Validation` error means a frame was *rejected*;
|
|
/// a *degraded* frame is not an error and is returned normally with reduced
|
|
/// `quality_score`.
|
|
#[derive(Debug, Error)]
|
|
#[non_exhaustive]
|
|
pub enum RvcsiError {
|
|
/// A source/adapter could not be opened or talked to.
|
|
#[error("adapter '{kind}' failed: {message}")]
|
|
Adapter {
|
|
/// The adapter kind (`"file"`, `"nexmon"`, `"esp32"`, ...).
|
|
kind: String,
|
|
/// Human-readable detail.
|
|
message: String,
|
|
},
|
|
|
|
/// A raw byte buffer could not be parsed into a frame.
|
|
#[error("parse error at offset {offset}: {message}")]
|
|
Parse {
|
|
/// Byte offset where parsing failed (best effort).
|
|
offset: usize,
|
|
/// Human-readable detail.
|
|
message: String,
|
|
},
|
|
|
|
/// A frame failed validation and was rejected.
|
|
#[error("frame rejected: {0}")]
|
|
Validation(#[from] ValidationError),
|
|
|
|
/// A configuration value was out of range or inconsistent.
|
|
#[error("invalid configuration: {0}")]
|
|
Config(String),
|
|
|
|
/// An I/O error (file capture, replay, WebSocket, ...).
|
|
#[error("io error: {0}")]
|
|
Io(#[from] std::io::Error),
|
|
|
|
/// Serialization / deserialization error (JSON capture sidecars, RuVector export).
|
|
#[error("serde error: {0}")]
|
|
Serde(#[from] serde_json::Error),
|
|
|
|
/// The requested operation is not supported by this source/adapter.
|
|
#[error("unsupported: {0}")]
|
|
Unsupported(String),
|
|
}
|
|
|
|
impl RvcsiError {
|
|
/// Convenience constructor for adapter errors.
|
|
pub fn adapter(kind: impl Into<String>, message: impl Into<String>) -> Self {
|
|
RvcsiError::Adapter {
|
|
kind: kind.into(),
|
|
message: message.into(),
|
|
}
|
|
}
|
|
|
|
/// Convenience constructor for parse errors.
|
|
pub fn parse(offset: usize, message: impl Into<String>) -> Self {
|
|
RvcsiError::Parse {
|
|
offset,
|
|
message: message.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn display_messages_are_useful() {
|
|
let e = RvcsiError::adapter("nexmon", "device /dev/wlan0 not in monitor mode");
|
|
assert!(e.to_string().contains("nexmon"));
|
|
assert!(e.to_string().contains("monitor mode"));
|
|
|
|
let e = RvcsiError::parse(12, "frame length 0");
|
|
assert!(e.to_string().contains("offset 12"));
|
|
}
|
|
}
|