refactor(errors): adopt reportable error terminology

This commit is contained in:
Onur Özkan committed 2026-08-23 00:49:25 +03:00
1 parent 21e9497915
commit 9fec2fa095
92 files changed
+270 -269

No files matched your search

+5 -5
View File
@@ -80,16 +80,16 @@ The build watches every fragment and generates one `message::kaptan` module;
fragments are never separately generated Rust modules. `kaptan-log` itself has fragments are never separately generated Rust modules. `kaptan-log` itself has
no MAVLink, platform, time, allocation, or filesystem dependency; its sole no MAVLink, platform, time, allocation, or filesystem dependency; its sole
configuration coupling is compile-time enum metadata for `LevelFilter`. configuration coupling is compile-time enum metadata for `LevelFilter`.
`kaptan-err-propagate` independently owns explicitly assigned typed-error identity, `kaptan-err-reportable` independently owns explicitly assigned reportable-error
function-boundary propagation, and a bounded nonblocking ingress; it has identity and a bounded nonblocking ingress; it has
no logging, MAVLink, platform, filesystem, or clock dependency. Event creation no logging, MAVLink, platform, filesystem, or clock dependency. Event creation
is independent from sink filtering, allowing a future blackbox and MAVLink to is independent from sink filtering, allowing a future blackbox and MAVLink to
select different policies. The platform drains typed errors before its bounded select different policies. The platform drains reportable errors before its bounded
critical and best-effort log queues and removes a pending record only after TX critical and best-effort log queues and removes a pending record only after TX
admission. `KAPTAN_LOG` carries one conventional level plus one bounded text admission. `KAPTAN_LOG` carries one conventional level plus one bounded text
field; `KAPTAN_ERROR` carries an explicitly assigned 16-bit ID and the bounded field; `KAPTAN_ERROR` carries an explicitly assigned 16-bit ID and the bounded
`file:line` of the reporting boundary. Its `file:line` of the reporting point. Its
message kind already identifies a typed firmware error. Heartbeat and safety message kind already identifies a reportable firmware error. Heartbeat and safety
telemetry remain separate from diagnostics. telemetry remain separate from diagnostics.
See [Configuration](configuration.md) for the deployment matrix and GCS transaction See [Configuration](configuration.md) for the deployment matrix and GCS transaction
+19 -19
View File
@@ -1,9 +1,9 @@
# Errors # Errors
Public Kaptan error enums derive the pure `KaptanError` implementation: Public reportable Kaptan error enums derive `KaptanError`:
```rust ```rust
#[derive(Debug, kaptan_err_propagate::KaptanError)] #[derive(Debug, kaptan_err_reportable::KaptanError)]
enum SensorError { enum SensorError {
#[kaptan_error(id = 12345)] #[kaptan_error(id = 12345)]
TransferFault, TransferFault,
@@ -11,14 +11,14 @@ enum SensorError {
UnexpectedIdentity(u8), UnexpectedIdentity(u8),
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn service_sensor() -> Result<(), SensorError> { fn service_sensor() -> Result<(), SensorError> {
read_sensor()?; read_sensor()?;
Ok(()) Ok(())
} }
``` ```
The derive implements `core::error::Error`, `Display`, and `ErrorReport`. It The derive implements `core::error::Error`, `Display`, and `ReportableError`. It
requires a nonzero explicit ID on every variant and retains no type, variant, requires a nonzero explicit ID on every variant and retains no type, variant,
or module string. `Display` renders the decimal ID. Renaming, moving, or or module string. `Display` renders the decimal ID. Renaming, moving, or
reordering a Rust variant therefore does not change its receiver contract. reordering a Rust variant therefore does not change its receiver contract.
@@ -26,11 +26,11 @@ Missing and same-enum duplicate IDs are rejected by the derive. Reusing an ID
across error enums generates the same reserved linker symbol and fails the across error enums generates the same reserved linker symbol and fails the
final firmware build. final firmware build.
`#[kaptan_err_propagate::propagate]` observes the ordinary `Result` produced `#[kaptan_err_reportable::propagate]` turns an annotated function into a
by one terminal diagnostic boundary. If an `Err` leaves that function, the attribute reporting point. If a reportable `Err` leaves that function, the attribute makes
makes one nonblocking admission attempt and returns the exact same `Err` to the one nonblocking admission attempt and returns the exact same `Err` to the
caller. The record contains the final converted error ID and the compile-time caller. The record contains the final converted error ID and the compile-time
`file:line` of that annotated boundary. This is where the `Err` enters `file:line` of that reporting point. This is where the `Err` enters
diagnostics, not necessarily the line where a deeper callee originally diagnostics, not necessarily the line where a deeper callee originally
constructed it. `?`, explicit returns, result aliases, and `From` conversion constructed it. `?`, explicit returns, result aliases, and `From` conversion
retain their normal Rust behavior. An error handled inside the function is retain their normal Rust behavior. An error handled inside the function is
@@ -46,35 +46,35 @@ renaming, moving, or reordering an existing variant keeps its assigned ID.
The example numbers above are illustrative and must be replaced with The example numbers above are illustrative and must be replaced with
unallocated catalog values when used in production code. unallocated catalog values when used in production code.
Only the terminal boundary is annotated. If nested functions are both Only the intended reporting point is annotated. If nested functions are both
annotated, each boundary makes its own report attempt; the ingress does not annotated, each function makes its own report attempt; the ingress does not
mark or mutate error values to deduplicate them. Expected validation, mark or mutate error values to deduplicate them. Expected validation,
backpressure, retry, and untrusted-input results remain unannotated. In backpressure, retry, and untrusted-input results remain unannotated. In
particular, transient SPI/I²C `Busy` and unavailable range measurements stay particular, transient SPI/I²C `Busy` and unavailable range measurements stay
inside their service retry/idle paths. In contrast, every logging inside their service retry/idle paths. In contrast, every logging
macro—including `kaptan_log::error!`—produces only macro—including `kaptan_log::error!`—produces only
`KAPTAN_LOG`. Error propagation is not a replacement for safety state, `KAPTAN_LOG`. Error reporting is not a replacement for safety state,
actuator inhibit, or typed configuration results. actuator inhibit, or typed configuration results.
`kaptan-err-propagate` owns error identity and its independent one-slot `kaptan-err-reportable` owns reportable-error identity and its independent
ingress. A pending record contains only the compact ID and a static reference one-slot ingress. A pending record contains only the compact ID and a static
to the propagation boundary's `file:line`. The MAVLink adapter copies that reference to the reporting point's `file:line`. The MAVLink adapter copies that
location into its fixed field when constructing `KAPTAN_ERROR`. Producers never location into its fixed field when constructing `KAPTAN_ERROR`. Producers never
encode or transmit MAVLink themselves. Admission is bounded and lossy if a encode or transmit MAVLink themselves. Admission is bounded and lossy if a
different typed error is already pending. different reportable error is already pending.
## What the receiver sees ## What the receiver sees
- Configuration writes receive authoritative structured failures through - Configuration writes receive authoritative structured failures through
`KAPTAN_CONFIG_RESULT`: operation, lifecycle state, field IDs, validation `KAPTAN_CONFIG_RESULT`: operation, lifecycle state, field IDs, validation
rule, and protocol error code. A terminal persistence failure also reports rule, and protocol error code. A reportable persistence failure also emits
the storage-only `CommitTransactionError::Store` boundary once as the storage-only `CommitTransactionError::Store` ID once as
`KAPTAN_ERROR`; replaying the cached command result does not repeat the error `KAPTAN_ERROR`; replaying the cached command result does not repeat the error
or the flash operation. or the flash operation.
- Terminal typed `ErrorReport` faults reach the F722 MAVLink worker as a - Reported `ReportableError` values reach the F722 MAVLink worker as a
`KAPTAN_ERROR`, subject to bounded transport admission. The payload is `KAPTAN_ERROR`, subject to bounded transport admission. The payload is
`{ error_id, raised_at[96] }`. `raised_at` is a zero-padded UTF-8 `{ error_id, raised_at[96] }`. `raised_at` is a zero-padded UTF-8
`file:line` prefix for the annotated propagation boundary. `file:line` prefix for the reporting point.
The message kind itself identifies an error; no level is duplicated in the The message kind itself identifies an error; no level is duplicated in the
payload. Dynamic human-readable context belongs in `KAPTAN_LOG`, while payload. Dynamic human-readable context belongs in `KAPTAN_LOG`, while
structured protocol failures remain in their owning response message. structured protocol failures remain in their owning response message.
+9 -9
View File
@@ -11,18 +11,18 @@ kaptan_log::trace!("prediction step complete");
``` ```
All five macros emit `KAPTAN_LOG`; their level never selects a different wire All five macros emit `KAPTAN_LOG`; their level never selects a different wire
message. When a terminal typed firmware error escapes a reviewed message. When a reportable firmware error escapes a reviewed
`#[kaptan_err_propagate::propagate]` function, it makes one bounded admission attempt `#[kaptan_err_reportable::propagate]` function, it makes one bounded admission attempt
to the separate `KAPTAN_ERROR` ingress. to the separate `KAPTAN_ERROR` ingress.
`kaptan-log` formats each event once into a fixed bounded buffer and never `kaptan-log` formats each event once into a fixed bounded buffer and never
sends MAVLink, allocates, blocks, changes flight state, or touches DMA. The sends MAVLink, allocates, blocks, changes flight state, or touches DMA. The
composition fans the event into each enabled sink; the sole MAVLink worker composition fans the event into each enabled sink; the sole MAVLink worker
drains its bounded sink queue. Ordinary log text uses one 160-byte bounded drains its bounded sink queue. Ordinary log text uses one 160-byte bounded
record. Typed-error records contain the explicit ID and a static reference to record. Reportable-error records contain the explicit ID and a static reference
the annotated propagation boundary until the MAVLink adapter copies its to the reporting point until the MAVLink adapter copies its
`file:line` into the 96-byte `raised_at` field. `file:line` into the 96-byte `raised_at` field.
Logs and typed errors use independent fixed atomic Logs and reportable errors use independent fixed atomic
ingresses; interrupt and worker producers make one nonblocking admission ingresses; interrupt and worker producers make one nonblocking admission
attempt, and only the MAVLink worker encodes or transmits a retained event. attempt, and only the MAVLink worker encodes or transmits a retained event.
Panic and hard-fault paths still do not attempt live telemetry. Panic and hard-fault paths still do not attempt live telemetry.
@@ -30,7 +30,7 @@ Panic and hard-fault paths still do not attempt live telemetry.
## Receiver contract ## Receiver contract
`definitions/kaptan/log.xml` and `definitions/kaptan/error.xml` separate `definitions/kaptan/log.xml` and `definitions/kaptan/error.xml` separate
ordinary logs and typed errors: ordinary logs and reportable errors:
```text ```text
KAPTAN_LOG { level, flags, message_length, message[160] } KAPTAN_LOG { level, flags, message_length, message[160] }
@@ -46,12 +46,12 @@ or the complete field when no zero is present.
`KAPTAN_LOG.level` accepts only Error (3), Warning (4), Info (6), and Debug `KAPTAN_LOG.level` accepts only Error (3), Warning (4), Info (6), and Debug
(7); Trace is encoded as Debug (7) plus the `TRACE` flag. Other MAVLink (7); Trace is encoded as Debug (7) plus the `TRACE` flag. Other MAVLink
severity numbers are not Kaptan log levels. severity numbers are not Kaptan log levels.
The `KAPTAN_ERROR` message kind already means a typed firmware error, so it has The `KAPTAN_ERROR` message kind already means a reportable firmware error, so it has
no redundant level or flags field. no redundant level or flags field.
`error_id` is the stable nonzero catalog number explicitly assigned to the `error_id` is the stable nonzero catalog number explicitly assigned to the
Rust error variant. Renaming or reordering a variant does not change it. Rust error variant. Renaming or reordering a variant does not change it.
`raised_at` identifies the annotated boundary where the `Err` entered `raised_at` identifies the reporting point where the `Err` entered
diagnostics. Error details requiring diagnostics. Error details requiring
machine action stay in their owning protocol, notably `KAPTAN_CONFIG_RESULT`. machine action stay in their owning protocol, notably `KAPTAN_CONFIG_RESULT`.
Delivery is bounded and lossy under link pressure; heartbeat and safety Delivery is bounded and lossy under link pressure; heartbeat and safety
@@ -65,7 +65,7 @@ event.
The single restart-only `mavlink.logging.level_filter` field uses the familiar The single restart-only `mavlink.logging.level_filter` field uses the familiar
Off, Error, Warn, Info, Debug, and Trace choices. `Info`, for example, accepts Off, Error, Warn, Info, Debug, and Trace choices. `Info`, for example, accepts
Error, Warn, and Info log events. `Off` suppresses `KAPTAN_LOG` on MAVLink Error, Warn, and Info log events. `Off` suppresses `KAPTAN_LOG` on MAVLink
without suppressing typed `KAPTAN_ERROR` reports or events sent to another without suppressing reportable `KAPTAN_ERROR` events or logs sent to another
sink. There is no separate enable flag and no MAVLink-specific set of extra sink. There is no separate enable flag and no MAVLink-specific set of extra
runtime log levels. F722 uses the validated filter recovered at boot, falling runtime log levels. F722 uses the validated filter recovered at boot, falling
back to its board factory when the journal is empty or invalid. back to its board factory when the journal is empty or invalid.
+2 -2
View File
@@ -50,8 +50,8 @@ log history.
The custom Kaptan definitions are aggregated by `definitions/kaptan.xml` from The custom Kaptan definitions are aggregated by `definitions/kaptan.xml` from
`kaptan/config.xml`, `kaptan/log.xml`, and `kaptan/error.xml`. `kaptan/config.xml`, `kaptan/log.xml`, and `kaptan/error.xml`.
`KAPTAN_LOG` is an outbound human-readable four-field record. `KAPTAN_ERROR` `KAPTAN_LOG` is an outbound human-readable four-field record. `KAPTAN_ERROR`
is the separate bounded channel for typed firmware errors, carrying a stable is the separate bounded channel for reportable firmware errors, carrying a
explicit ID plus the `file:line` of its propagation boundary, and needs no stable explicit ID plus the `file:line` of its reporting point, and needs no
redundant level field. Configuration messages back the current target-described redundant level field. Configuration messages back the current target-described
web configurator and the future signed GCS. See web configurator and the future signed GCS. See
[Configuration](configuration.md), [Logs](logs.md), and [Errors](errors.md) for [Configuration](configuration.md), [Logs](logs.md), and [Errors](errors.md) for
+2 -2
View File
@@ -8,12 +8,12 @@ This page collects stable limits and points to the detailed contracts.
| F722 persistence | One bounded fixed scalar snapshot inside each slot of a power-loss-safe two-slot flash journal. | | F722 persistence | One bounded fixed scalar snapshot inside each slot of a power-loss-safe two-slot flash journal. |
| Config transaction | One owner-bound RAM transaction with typed scalar writes; commit is restart-required. | | Config transaction | One owner-bound RAM transaction with typed scalar writes; commit is restart-required. |
| Config discovery | Correlated `KAPTAN_CONFIG_INFO_REQUEST` / `KAPTAN_CONFIG_INFO`, then exact-index descriptor/enum-option and field-value requests. | | Config discovery | Correlated `KAPTAN_CONFIG_INFO_REQUEST` / `KAPTAN_CONFIG_INFO`, then exact-index descriptor/enum-option and field-value requests. |
| Diagnostics | `KAPTAN_LOG` (51020) for macro-produced level/text; `KAPTAN_ERROR` (51021) for a bounded typed `{ error_id, raised_at[96] }` firmware error. | | Diagnostics | `KAPTAN_LOG` (51020) for macro-produced level/text; `KAPTAN_ERROR` (51021) for a bounded reportable `{ error_id, raised_at[96] }` firmware error. |
| F722 configuration | Target-described fields and board factory defaults; the current local transport is a directly wired unsigned UART with motor outputs physically inhibited. | | F722 configuration | Target-described fields and board factory defaults; the current local transport is a directly wired unsigned UART with motor outputs physically inhibited. |
Read [Configuration](configuration.md) for the field/consumer matrix and GCS Read [Configuration](configuration.md) for the field/consumer matrix and GCS
transaction sequence, [Logs](logs.md) for receiver decoding and filtering, and transaction sequence, [Logs](logs.md) for receiver decoding and filtering, and
[Errors](errors.md) for error propagation and panic scope. [Errors](errors.md) for reportable errors and panic scope.
## Verification ## Verification
+16 -16
View File
@@ -156,7 +156,7 @@ name = "kaptan-config"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"kaptan-config-derive", "kaptan-config-derive",
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-log", "kaptan-log",
] ]
@@ -176,7 +176,7 @@ name = "kaptan-config-mavlink"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"kaptan-config", "kaptan-config",
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-mavlink", "kaptan-mavlink",
] ]
@@ -198,7 +198,7 @@ dependencies = [
name = "kaptan-control" name = "kaptan-control"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-math", "kaptan-math",
] ]
@@ -207,7 +207,7 @@ name = "kaptan-data-channel"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"kaptan-dma", "kaptan-dma",
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-mavlink", "kaptan-mavlink",
"kaptan-sensor", "kaptan-sensor",
"kaptan-time", "kaptan-time",
@@ -217,7 +217,7 @@ dependencies = [
name = "kaptan-diagnostics-mavlink" name = "kaptan-diagnostics-mavlink"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-log", "kaptan-log",
"kaptan-mavlink", "kaptan-mavlink",
"mavlink", "mavlink",
@@ -231,7 +231,7 @@ version = "0.1.0"
name = "kaptan-drivers" name = "kaptan-drivers"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-i2c", "kaptan-i2c",
"kaptan-sensor", "kaptan-sensor",
"kaptan-spi", "kaptan-spi",
@@ -239,14 +239,14 @@ dependencies = [
] ]
[[package]] [[package]]
name = "kaptan-err-propagate" name = "kaptan-err-reportable"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"kaptan-err-propagate-macros", "kaptan-err-reportable-macros",
] ]
[[package]] [[package]]
name = "kaptan-err-propagate-macros" name = "kaptan-err-reportable-macros"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
@@ -260,7 +260,7 @@ name = "kaptan-flight-config"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"kaptan-config", "kaptan-config",
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-log", "kaptan-log",
"minicbor", "minicbor",
] ]
@@ -307,7 +307,7 @@ dependencies = [
name = "kaptan-math" name = "kaptan-math"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"kaptan-err-propagate", "kaptan-err-reportable",
] ]
[[package]] [[package]]
@@ -316,7 +316,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"kaptan-dma", "kaptan-dma",
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-sensor", "kaptan-sensor",
"kaptan-time", "kaptan-time",
"kaptan-tx", "kaptan-tx",
@@ -331,7 +331,7 @@ dependencies = [
name = "kaptan-navigation" name = "kaptan-navigation"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-math", "kaptan-math",
"kaptan-sensor", "kaptan-sensor",
"kaptan-time", "kaptan-time",
@@ -341,7 +341,7 @@ dependencies = [
name = "kaptan-safety" name = "kaptan-safety"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-time", "kaptan-time",
] ]
@@ -360,7 +360,7 @@ dependencies = [
"kaptan-config-mavlink", "kaptan-config-mavlink",
"kaptan-control", "kaptan-control",
"kaptan-diagnostics-mavlink", "kaptan-diagnostics-mavlink",
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-flight-config", "kaptan-flight-config",
"kaptan-flight-runtime", "kaptan-flight-runtime",
"kaptan-log", "kaptan-log",
@@ -509,7 +509,7 @@ dependencies = [
"kaptan-diagnostics-mavlink", "kaptan-diagnostics-mavlink",
"kaptan-dma", "kaptan-dma",
"kaptan-drivers", "kaptan-drivers",
"kaptan-err-propagate", "kaptan-err-reportable",
"kaptan-i2c", "kaptan-i2c",
"kaptan-log", "kaptan-log",
"kaptan-mavlink", "kaptan-mavlink",
+2 -2
View File
@@ -10,8 +10,8 @@ members = [
"libs/kaptan-data-channel", "libs/kaptan-data-channel",
"libs/kaptan-dma", "libs/kaptan-dma",
"libs/kaptan-drivers", "libs/kaptan-drivers",
"libs/kaptan-err-propagate", "libs/kaptan-err-reportable",
"libs/kaptan-err-propagate-macros", "libs/kaptan-err-reportable-macros",
"libs/kaptan-flight-config", "libs/kaptan-flight-config",
"libs/kaptan-flight-runtime", "libs/kaptan-flight-runtime",
"libs/kaptan-i2c", "libs/kaptan-i2c",
@@ -10,5 +10,5 @@ workspace = true
[dependencies] [dependencies]
kaptan-config = { path = "../kaptan-config" } kaptan-config = { path = "../kaptan-config" }
kaptan-err-propagate = { path = "../kaptan-err-propagate" } kaptan-err-reportable = { path = "../kaptan-err-reportable" }
kaptan-mavlink = { path = "../kaptan-mavlink", default-features = false, features = ["dialect-kaptan"] } kaptan-mavlink = { path = "../kaptan-mavlink", default-features = false, features = ["dialect-kaptan"] }
@@ -1,7 +1,7 @@
//! Stable typed outcomes for the Kaptan configuration microservice. //! Stable typed outcomes for the Kaptan configuration microservice.
use kaptan_config::{ConfigState, ConfigViolation, FieldId}; use kaptan_config::{ConfigState, ConfigViolation, FieldId};
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
/// Operation reported in an authoritative result record. /// Operation reported in an authoritative result record.
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -23,7 +23,7 @@ pub(super) struct Session {
pub(super) revision: u32, pub(super) revision: u32,
} }
#[derive(Debug, kaptan_err_propagate::KaptanError)] #[derive(Debug, kaptan_err_reportable::KaptanError)]
enum CommitTransactionError<E> { enum CommitTransactionError<E> {
#[kaptan_error(id = 2201)] #[kaptan_error(id = 2201)]
Store(E), Store(E),
@@ -337,9 +337,9 @@ impl ConfigProtocol {
/// Classifies expected configuration rejection separately from a terminal /// Classifies expected configuration rejection separately from a terminal
/// persistence failure. Only the latter leaves this boundary and becomes /// persistence failure. Only the latter leaves this boundary and becomes
/// a typed firmware error; the configuration result remains authoritative /// a reportable firmware error; the configuration result remains authoritative
/// for the requesting user. /// for the requesting user.
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn commit_transaction<C, S>( fn commit_transaction<C, S>(
&mut self, &mut self,
manager: &mut ConfigManager<C, S>, manager: &mut ConfigManager<C, S>,
@@ -1235,7 +1235,7 @@ mod tests {
#[test] #[test]
fn failed_commit_reports_the_returned_error_only_once() { fn failed_commit_reports_the_returned_error_only_once() {
while kaptan_err_propagate::take().is_some() {} while kaptan_err_reportable::take().is_some() {}
let persists = Rc::new(Cell::new(0)); let persists = Rc::new(Cell::new(0));
let store = FailingStore(Rc::clone(&persists)); let store = FailingStore(Rc::clone(&persists));
let mut manager = ConfigManager::new(Candidate(2), (), store).unwrap(); let mut manager = ConfigManager::new(Candidate(2), (), store).unwrap();
@@ -1277,9 +1277,9 @@ mod tests {
Some(ProtocolError::StorageFailure) Some(ProtocolError::StorageFailure)
); );
let error = let error =
kaptan_err_propagate::take().expect("failed commit must report its returned error"); kaptan_err_reportable::take().expect("failed commit must report its returned error");
assert_eq!(error.id(), 2201); assert_eq!(error.id(), 2201);
while kaptan_err_propagate::take().is_some() {} while kaptan_err_reportable::take().is_some() {}
protocol protocol
.dispatch(&mut manager, Authorized::host(7, commit), |_| { .dispatch(&mut manager, Authorized::host(7, commit), |_| {
@@ -1288,7 +1288,7 @@ mod tests {
.unwrap(); .unwrap();
assert_eq!(persists.get(), 1); assert_eq!(persists.get(), 1);
assert!( assert!(
kaptan_err_propagate::take().is_none(), kaptan_err_reportable::take().is_none(),
"a cached command replay must not report the error again" "a cached command replay must not report the error again"
); );
} }
@@ -3,7 +3,7 @@
use kaptan_config::{ use kaptan_config::{
ConfigState, ConfigValue, FieldDescriptor, FieldId, ValidationRule, ValueKind, ConfigState, ConfigValue, FieldDescriptor, FieldId, ValidationRule, ValueKind,
}; };
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_mavlink::message::Message; use kaptan_mavlink::message::Message;
use kaptan_mavlink::message::kaptan::{ use kaptan_mavlink::message::kaptan::{
KAPTAN_CONFIG_DESCRIPTOR_DATA, KAPTAN_CONFIG_ENUM_OPTION_DATA, KAPTAN_CONFIG_INFO_DATA, KAPTAN_CONFIG_DESCRIPTOR_DATA, KAPTAN_CONFIG_ENUM_OPTION_DATA, KAPTAN_CONFIG_INFO_DATA,
+1 -1
View File
@@ -10,5 +10,5 @@ workspace = true
[dependencies] [dependencies]
kaptan-config-derive = { path = "../kaptan-config-derive" } kaptan-config-derive = { path = "../kaptan-config-derive" }
kaptan-err-propagate = { path = "../kaptan-err-propagate" } kaptan-err-reportable = { path = "../kaptan-err-reportable" }
kaptan-log = { path = "../kaptan-log" } kaptan-log = { path = "../kaptan-log" }
+1 -1
View File
@@ -1,7 +1,7 @@
//! Transport-neutral typed configuration fields and descriptors. //! Transport-neutral typed configuration fields and descriptors.
use crate::{ConfigViolation, ValidationRule}; use crate::{ConfigViolation, ValidationRule};
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
/// Maximum choices representable by one enum-backed field. /// Maximum choices representable by one enum-backed field.
/// ///
+1 -1
View File
@@ -4,7 +4,7 @@ use crate::{
ConfigModel, ConfigStore, ConfigValue, ConfigViolation, FieldDescriptor, FieldId, ConfigModel, ConfigStore, ConfigValue, ConfigViolation, FieldDescriptor, FieldId,
FieldWriteError, FieldWriteError,
}; };
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
/// Observable state of the bounded configuration transaction slot. /// Observable state of the bounded configuration transaction slot.
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+1 -1
View File
@@ -16,7 +16,7 @@
//! field IDs and therefore also accepts a complete, uniquely identified set in //! field IDs and therefore also accepts a complete, uniquely identified set in
//! another order. //! another order.
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use crate::{ConfigModel, ConfigValue, FieldId, FieldWriteError, ValueKind}; use crate::{ConfigModel, ConfigValue, FieldId, FieldWriteError, ValueKind};
+1 -1
View File
@@ -9,5 +9,5 @@ version.workspace = true
workspace = true workspace = true
[dependencies] [dependencies]
kaptan-err-propagate = { path = "../kaptan-err-propagate" } kaptan-err-reportable = { path = "../kaptan-err-reportable" }
kaptan-math = { path = "../kaptan-math" } kaptan-math = { path = "../kaptan-math" }
+1 -1
View File
@@ -7,7 +7,7 @@
#![no_std] #![no_std]
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_math::{Frd, Ned, UnitQuaternion, Vector3, sqrt}; use kaptan_math::{Frd, Ned, UnitQuaternion, Vector3, sqrt};
/// Body-frame angular rate in radians per second. /// Body-frame angular rate in radians per second.
+1 -1
View File
@@ -9,7 +9,7 @@ version.workspace = true
workspace = true workspace = true
[dependencies] [dependencies]
kaptan-err-propagate = { path = "../kaptan-err-propagate" } kaptan-err-reportable = { path = "../kaptan-err-reportable" }
kaptan-dma = { path = "../kaptan-dma" } kaptan-dma = { path = "../kaptan-dma" }
kaptan-mavlink = { path = "../kaptan-mavlink" } kaptan-mavlink = { path = "../kaptan-mavlink" }
kaptan-sensor = { path = "../kaptan-sensor" } kaptan-sensor = { path = "../kaptan-sensor" }
+1 -1
View File
@@ -8,7 +8,7 @@
#![no_std] #![no_std]
use kaptan_dma::TxCompletion; use kaptan_dma::TxCompletion;
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_mavlink::message::MessageData; use kaptan_mavlink::message::MessageData;
use kaptan_mavlink::{ use kaptan_mavlink::{
MavlinkFrame, MavlinkFrame,
@@ -9,7 +9,7 @@ version.workspace = true
workspace = true workspace = true
[dependencies] [dependencies]
kaptan-err-propagate = { path = "../kaptan-err-propagate" } kaptan-err-reportable = { path = "../kaptan-err-reportable" }
kaptan-log = { path = "../kaptan-log" } kaptan-log = { path = "../kaptan-log" }
kaptan-mavlink = { path = "../kaptan-mavlink", default-features = false, features = ["dialect-kaptan"] } kaptan-mavlink = { path = "../kaptan-mavlink", default-features = false, features = ["dialect-kaptan"] }
@@ -1,4 +1,4 @@
//! MAVLink projection for Kaptan logs and typed firmware errors. //! MAVLink projection for Kaptan logs and reportable firmware errors.
//! //!
//! This adapter creates generated payload data only. A platform-owned link is //! This adapter creates generated payload data only. A platform-owned link is
//! solely responsible for MAVLink framing, bounded admission, DMA, and retry //! solely responsible for MAVLink framing, bounded admission, DMA, and retry
@@ -9,7 +9,7 @@
#[cfg(test)] #[cfg(test)]
extern crate std; extern crate std;
use kaptan_err_propagate::ErrorRecord; use kaptan_err_reportable::ErrorRecord;
use kaptan_log::{Level, LogRecord, MAXIMUM_LOG_TEXT_BYTES}; use kaptan_log::{Level, LogRecord, MAXIMUM_LOG_TEXT_BYTES};
use kaptan_mavlink::message::kaptan::{KAPTAN_ERROR_DATA, KAPTAN_LOG_DATA, KaptanLogFlags}; use kaptan_mavlink::message::kaptan::{KAPTAN_ERROR_DATA, KAPTAN_LOG_DATA, KaptanLogFlags};
@@ -32,7 +32,7 @@ pub fn encode_log(record: &LogRecord) -> KAPTAN_LOG_DATA {
} }
} }
/// Encodes one typed firmware error as its sole wire message. /// Encodes one reportable firmware error as its sole wire message.
pub fn encode_error(record: &ErrorRecord) -> KAPTAN_ERROR_DATA { pub fn encode_error(record: &ErrorRecord) -> KAPTAN_ERROR_DATA {
let source = record.raised_at().as_bytes(); let source = record.raised_at().as_bytes();
let mut length = source.len().min(ERROR_RAISED_AT_BYTES); let mut length = source.len().min(ERROR_RAISED_AT_BYTES);
@@ -63,7 +63,7 @@ const fn mavlink_severity(level: Level) -> u8 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{LOG_MESSAGE_BYTES, encode_error, encode_log}; use super::{LOG_MESSAGE_BYTES, encode_error, encode_log};
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_log::{Level, LogFlags, LogRecord, LogText}; use kaptan_log::{Level, LogFlags, LogRecord, LogText};
use kaptan_mavlink::{ use kaptan_mavlink::{
MavlinkVersion, MavlinkVersion,
@@ -80,8 +80,8 @@ mod tests {
Transfer, Transfer,
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn report_typed_error() -> Result<(), TestError> { fn report_reportable_error() -> Result<(), TestError> {
Err(TestError::Transfer) Err(TestError::Transfer)
} }
@@ -148,9 +148,9 @@ mod tests {
Ok(MavMessage::KAPTAN_LOG(decoded)) if decoded == data Ok(MavMessage::KAPTAN_LOG(decoded)) if decoded == data
)); ));
while kaptan_err_propagate::take().is_some() {} while kaptan_err_reportable::take().is_some() {}
assert_eq!(report_typed_error(), Err(TestError::Transfer)); assert_eq!(report_reportable_error(), Err(TestError::Transfer));
let error = kaptan_err_propagate::take().expect("typed error retained"); let error = kaptan_err_reportable::take().expect("reportable error retained");
let error_data = encode_error(&error); let error_data = encode_error(&error);
assert_eq!(error_data.error_id, error.id()); assert_eq!(error_data.error_id, error.id());
assert_eq!(KAPTAN_ERROR_DATA::ENCODED_LEN, 98); assert_eq!(KAPTAN_ERROR_DATA::ENCODED_LEN, 98);
+1 -1
View File
@@ -9,7 +9,7 @@ version.workspace = true
workspace = true workspace = true
[dependencies] [dependencies]
kaptan-err-propagate = { path = "../kaptan-err-propagate" } kaptan-err-reportable = { path = "../kaptan-err-reportable" }
kaptan-sensor = { path = "../kaptan-sensor" } kaptan-sensor = { path = "../kaptan-sensor" }
kaptan-i2c = { path = "../kaptan-i2c" } kaptan-i2c = { path = "../kaptan-i2c" }
kaptan-spi = { path = "../kaptan-spi" } kaptan-spi = { path = "../kaptan-spi" }
@@ -1,6 +1,6 @@
//! ICM-42688-P operation errors. //! ICM-42688-P operation errors.
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
/// ICM-42688-P operation failure. /// ICM-42688-P operation failure.
#[derive(Debug, Eq, PartialEq, KaptanError)] #[derive(Debug, Eq, PartialEq, KaptanError)]
@@ -1,6 +1,6 @@
//! LIDAR-Lite v3 operation errors. //! LIDAR-Lite v3 operation errors.
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
/// LIDAR-Lite v3 operation failure. /// LIDAR-Lite v3 operation failure.
#[derive(Debug, Eq, PartialEq, KaptanError)] #[derive(Debug, Eq, PartialEq, KaptanError)]
@@ -1,6 +1,6 @@
//! MPU6000 operation errors. //! MPU6000 operation errors.
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
/// MPU6000 operation failure. /// MPU6000 operation failure.
#[derive(Debug, Eq, PartialEq, KaptanError)] #[derive(Debug, Eq, PartialEq, KaptanError)]
@@ -1,10 +0,0 @@
extern crate self as kaptan_err_propagate;
use kaptan_err_propagate_macros::KaptanError;
#[derive(Debug, KaptanError)]
enum MissingId {
Variant,
}
fn main() {}
@@ -1,6 +0,0 @@
use kaptan_err_propagate_macros::propagate;
#[propagate]
fn invalid() {}
fn main() {}
@@ -1,18 +0,0 @@
use kaptan_err_propagate_macros::propagate;
extern crate self as kaptan_err_propagate;
pub trait ErrorReport {}
pub mod __private {
pub fn report_result<T, E: crate::ErrorReport>(_: &Result<T, E>, _: &'static str) {}
}
struct PlainError;
#[propagate]
fn invalid() -> Result<(), PlainError> {
Err(PlainError)
}
fn main() {}
@@ -1,17 +0,0 @@
error[E0277]: the trait bound `PlainError: ErrorReport` is not satisfied
--> tests/ui/no_error_report.rs:13:1
|
13 | #[propagate]
| ^^^^^^^^^^^^ the trait `ErrorReport` is not implemented for `PlainError`
|
help: this trait has no implementations, consider adding one
--> tests/ui/no_error_report.rs:5:1
|
5 | pub trait ErrorReport {}
| ^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `report_result`
--> tests/ui/no_error_report.rs:8:32
|
8 | pub fn report_result<T, E: crate::ErrorReport>(_: &Result<T, E>, _: &'static str) {}
| ^^^^^^^^^^^^^^^^^^ required by this bound in `report_result`
= note: this error originates in the attribute macro `propagate` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -1,5 +1,5 @@
[package] [package]
name = "kaptan-err-propagate-macros" name = "kaptan-err-reportable-macros"
edition.workspace = true edition.workspace = true
license.workspace = true license.workspace = true
rust-version.workspace = true rust-version.workspace = true
@@ -1,4 +1,4 @@
//! Attribute expansion for `kaptan-err-propagate`. //! Attribute expansion for `kaptan-err-reportable`.
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
@@ -8,7 +8,7 @@ use syn::{
parse_quote, spanned::Spanned, parse_quote, spanned::Spanned,
}; };
/// Implements `kaptan_err_propagate::ErrorReport`, [`core::fmt::Display`], and /// Implements `kaptan_err_reportable::ReportableError`, [`core::fmt::Display`], and
/// [`core::error::Error`] for an explicitly numbered error enum. /// [`core::error::Error`] for an explicitly numbered error enum.
/// ///
/// Every variant must declare a stable nonzero /// Every variant must declare a stable nonzero
@@ -34,7 +34,7 @@ pub fn propagate(arguments: TokenStream, input: TokenStream) -> TokenStream {
if !arguments.is_empty() { if !arguments.is_empty() {
return Error::new( return Error::new(
proc_macro2::Span::call_site(), proc_macro2::Span::call_site(),
"kaptan_err_propagate::propagate does not accept arguments", "kaptan_err_reportable::propagate does not accept arguments",
) )
.into_compile_error() .into_compile_error()
.into(); .into();
@@ -53,22 +53,22 @@ fn expand(mut function: ItemFn) -> syn::Result<proc_macro2::TokenStream> {
function.block = if function.sig.asyncness.is_some() { function.block = if function.sig.asyncness.is_some() {
Box::new(syn::parse_quote!({ Box::new(syn::parse_quote!({
const __KAPTAN_RAISED_AT: &str = concat!(file!(), ":", line!()); const __KAPTAN_RAISED_AT: &str = concat!(file!(), ":", line!());
let __kaptan_err_propagate_result = (async #body).await; let __kaptan_err_reportable_result = (async #body).await;
::kaptan_err_propagate::__private::report_result( ::kaptan_err_reportable::__private::report_result(
&__kaptan_err_propagate_result, &__kaptan_err_reportable_result,
__KAPTAN_RAISED_AT, __KAPTAN_RAISED_AT,
); );
__kaptan_err_propagate_result __kaptan_err_reportable_result
})) }))
} else { } else {
Box::new(syn::parse_quote!({ Box::new(syn::parse_quote!({
const __KAPTAN_RAISED_AT: &str = concat!(file!(), ":", line!()); const __KAPTAN_RAISED_AT: &str = concat!(file!(), ":", line!());
let __kaptan_err_propagate_result = (|| #body)(); let __kaptan_err_reportable_result = (|| #body)();
::kaptan_err_propagate::__private::report_result( ::kaptan_err_reportable::__private::report_result(
&__kaptan_err_propagate_result, &__kaptan_err_reportable_result,
__KAPTAN_RAISED_AT, __KAPTAN_RAISED_AT,
); );
__kaptan_err_propagate_result __kaptan_err_reportable_result
})) }))
}; };
@@ -80,32 +80,32 @@ fn validate_signature(function: &ItemFn) -> syn::Result<()> {
if let Some(token) = signature.constness { if let Some(token) = signature.constness {
return Err(Error::new( return Err(Error::new(
token.span(), token.span(),
"kaptan_err_propagate::propagate does not support const functions", "kaptan_err_reportable::propagate does not support const functions",
)); ));
} }
if let Some(token) = signature.unsafety { if let Some(token) = signature.unsafety {
return Err(Error::new( return Err(Error::new(
token.span(), token.span(),
"kaptan_err_propagate::propagate does not support unsafe functions", "kaptan_err_reportable::propagate does not support unsafe functions",
)); ));
} }
if let Some(abi) = &signature.abi { if let Some(abi) = &signature.abi {
return Err(Error::new( return Err(Error::new(
abi.span(), abi.span(),
"kaptan_err_propagate::propagate does not support foreign-ABI functions", "kaptan_err_reportable::propagate does not support foreign-ABI functions",
)); ));
} }
if let Some(variadic) = &signature.variadic { if let Some(variadic) = &signature.variadic {
return Err(Error::new( return Err(Error::new(
variadic.span(), variadic.span(),
"kaptan_err_propagate::propagate does not support variadic functions", "kaptan_err_reportable::propagate does not support variadic functions",
)); ));
} }
if matches!(signature.output, ReturnType::Default) { if matches!(signature.output, ReturnType::Default) {
return Err(Error::new( return Err(Error::new(
signature.output.span(), signature.output.span(),
"kaptan_err_propagate::propagate requires an explicit Result<T, E> return type", "kaptan_err_reportable::propagate requires an explicit Result<T, E> return type",
)); ));
} }
Ok(()) Ok(())
@@ -168,7 +168,7 @@ fn expand_error(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
Fields::Named(_) => quote!(Self::#variant_ident { .. }), Fields::Named(_) => quote!(Self::#variant_ident { .. }),
}; };
quote! { quote! {
#pattern => ::kaptan_err_propagate::ErrorId::new(#id) #pattern => ::kaptan_err_reportable::ErrorId::new(#id)
} }
}); });
let (impl_generics, type_generics, where_clause) = generics.split_for_impl(); let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
@@ -183,8 +183,8 @@ fn expand_error(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
Ok(quote! { Ok(quote! {
#(#identities)* #(#identities)*
impl #impl_generics ::kaptan_err_propagate::ErrorReport for #ident #type_generics #where_clause { impl #impl_generics ::kaptan_err_reportable::ReportableError for #ident #type_generics #where_clause {
fn error_id(&self) -> ::kaptan_err_propagate::ErrorId { fn error_id(&self) -> ::kaptan_err_reportable::ErrorId {
match self { match self {
#(#arms),* #(#arms),*
} }
@@ -197,7 +197,7 @@ fn expand_error(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
formatter: &mut ::core::fmt::Formatter<'_>, formatter: &mut ::core::fmt::Formatter<'_>,
) -> ::core::fmt::Result { ) -> ::core::fmt::Result {
::core::fmt::Display::fmt( ::core::fmt::Display::fmt(
&<Self as ::kaptan_err_propagate::ErrorReport>::error_id(self).get(), &<Self as ::kaptan_err_reportable::ReportableError>::error_id(self).get(),
formatter, formatter,
) )
} }
@@ -1,4 +1,4 @@
use kaptan_err_propagate_macros::propagate; use kaptan_err_reportable_macros::propagate;
#[propagate(report)] #[propagate(report)]
fn invalid() -> Result<(), ()> { fn invalid() -> Result<(), ()> {
@@ -1,4 +1,4 @@
error: kaptan_err_propagate::propagate does not accept arguments error: kaptan_err_reportable::propagate does not accept arguments
--> tests/ui/arguments.rs:3:1 --> tests/ui/arguments.rs:3:1
| |
3 | #[propagate(report)] 3 | #[propagate(report)]
@@ -1,4 +1,4 @@
use kaptan_err_propagate_macros::propagate; use kaptan_err_reportable_macros::propagate;
#[propagate] #[propagate]
const fn invalid() -> Result<(), ()> { const fn invalid() -> Result<(), ()> {
@@ -1,4 +1,4 @@
error: kaptan_err_propagate::propagate does not support const functions error: kaptan_err_reportable::propagate does not support const functions
--> tests/ui/const_fn.rs:4:1 --> tests/ui/const_fn.rs:4:1
| |
4 | const fn invalid() -> Result<(), ()> { 4 | const fn invalid() -> Result<(), ()> {
@@ -1,6 +1,6 @@
extern crate self as kaptan_err_propagate; extern crate self as kaptan_err_reportable;
use kaptan_err_propagate_macros::KaptanError; use kaptan_err_reportable_macros::KaptanError;
#[derive(Debug, KaptanError)] #[derive(Debug, KaptanError)]
enum DuplicateId { enum DuplicateId {
@@ -1,6 +1,6 @@
extern crate self as kaptan_err_propagate; extern crate self as kaptan_err_reportable;
use kaptan_err_propagate_macros::KaptanError; use kaptan_err_reportable_macros::KaptanError;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct ErrorId(u16); pub struct ErrorId(u16);
@@ -15,7 +15,7 @@ impl ErrorId {
} }
} }
pub trait ErrorReport { pub trait ReportableError {
fn error_id(&self) -> ErrorId; fn error_id(&self) -> ErrorId;
} }
@@ -1,6 +1,6 @@
extern crate self as kaptan_err_propagate; extern crate self as kaptan_err_reportable;
use kaptan_err_propagate_macros::KaptanError; use kaptan_err_reportable_macros::KaptanError;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct ErrorId(u16); pub struct ErrorId(u16);
@@ -15,7 +15,7 @@ impl ErrorId {
} }
} }
pub trait ErrorReport { pub trait ReportableError {
fn error_id(&self) -> ErrorId; fn error_id(&self) -> ErrorId;
} }
@@ -0,0 +1,10 @@
extern crate self as kaptan_err_reportable;
use kaptan_err_reportable_macros::KaptanError;
#[derive(Debug, KaptanError)]
enum MissingId {
Variant,
}
fn main() {}
@@ -0,0 +1,6 @@
use kaptan_err_reportable_macros::propagate;
#[propagate]
fn invalid() {}
fn main() {}
@@ -1,4 +1,4 @@
error: kaptan_err_propagate::propagate requires an explicit Result<T, E> return type error: kaptan_err_reportable::propagate requires an explicit Result<T, E> return type
--> tests/ui/missing_return.rs:3:1 --> tests/ui/missing_return.rs:3:1
| |
3 | #[propagate] 3 | #[propagate]
@@ -0,0 +1,18 @@
use kaptan_err_reportable_macros::propagate;
extern crate self as kaptan_err_reportable;
pub trait ReportableError {}
pub mod __private {
pub fn report_result<T, E: crate::ReportableError>(_: &Result<T, E>, _: &'static str) {}
}
struct PlainError;
#[propagate]
fn invalid() -> Result<(), PlainError> {
Err(PlainError)
}
fn main() {}
@@ -0,0 +1,17 @@
error[E0277]: the trait bound `PlainError: ReportableError` is not satisfied
--> tests/ui/no_error_report.rs:13:1
|
13 | #[propagate]
| ^^^^^^^^^^^^ the trait `ReportableError` is not implemented for `PlainError`
|
help: this trait has no implementations, consider adding one
--> tests/ui/no_error_report.rs:5:1
|
5 | pub trait ReportableError {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `report_result`
--> tests/ui/no_error_report.rs:8:32
|
8 | pub fn report_result<T, E: crate::ReportableError>(_: &Result<T, E>, _: &'static str) {}
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `report_result`
= note: this error originates in the attribute macro `propagate` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -1,6 +1,6 @@
use kaptan_err_propagate_macros::propagate; use kaptan_err_reportable_macros::propagate;
extern crate self as kaptan_err_propagate; extern crate self as kaptan_err_reportable;
pub mod __private { pub mod __private {
pub fn report_result<T, E>(_: &Result<T, E>, _: &'static str) {} pub fn report_result<T, E>(_: &Result<T, E>, _: &'static str) {}
@@ -1,4 +1,4 @@
use kaptan_err_propagate_macros::KaptanError; use kaptan_err_reportable_macros::KaptanError;
#[derive(KaptanError)] #[derive(KaptanError)]
struct NotAnError { struct NotAnError {
@@ -1,4 +1,4 @@
use kaptan_err_propagate_macros::KaptanError; use kaptan_err_reportable_macros::KaptanError;
#[derive(KaptanError)] #[derive(KaptanError)]
union NotAnError { union NotAnError {
@@ -1,4 +1,4 @@
use kaptan_err_propagate_macros::propagate; use kaptan_err_reportable_macros::propagate;
#[propagate] #[propagate]
unsafe fn invalid() -> Result<(), ()> { unsafe fn invalid() -> Result<(), ()> {
@@ -1,4 +1,4 @@
error: kaptan_err_propagate::propagate does not support unsafe functions error: kaptan_err_reportable::propagate does not support unsafe functions
--> tests/ui/unsafe_fn.rs:4:1 --> tests/ui/unsafe_fn.rs:4:1
| |
4 | unsafe fn invalid() -> Result<(), ()> { 4 | unsafe fn invalid() -> Result<(), ()> {
@@ -1,6 +1,6 @@
extern crate self as kaptan_err_propagate; extern crate self as kaptan_err_reportable;
use kaptan_err_propagate_macros::KaptanError; use kaptan_err_reportable_macros::KaptanError;
#[derive(Debug, KaptanError)] #[derive(Debug, KaptanError)]
enum ZeroId { enum ZeroId {
@@ -1,5 +1,5 @@
[package] [package]
name = "kaptan-err-propagate" name = "kaptan-err-reportable"
edition.workspace = true edition.workspace = true
license.workspace = true license.workspace = true
rust-version.workspace = true rust-version.workspace = true
@@ -9,4 +9,4 @@ version.workspace = true
workspace = true workspace = true
[dependencies] [dependencies]
kaptan-err-propagate-macros = { path = "../kaptan-err-propagate-macros" } kaptan-err-reportable-macros = { path = "../kaptan-err-reportable-macros" }
@@ -1,4 +1,4 @@
//! Fixed, allocation-free typed-error ingress. //! Fixed, allocation-free reportable-error ingress.
use core::{ use core::{
cell::UnsafeCell, cell::UnsafeCell,
@@ -68,7 +68,7 @@ pub(crate) fn publish(id: ErrorId, raised_at: &'static str) {
GLOBAL_INGRESS.publish(id, raised_at); GLOBAL_INGRESS.publish(id, raised_at);
} }
/// Takes the pending typed firmware error, if one exists. /// Takes the pending reportable firmware error, if one exists.
pub fn take() -> Option<ErrorRecord> { pub fn take() -> Option<ErrorRecord> {
GLOBAL_INGRESS.take() GLOBAL_INGRESS.take()
} }
@@ -1,12 +1,13 @@
//! Bounded typed firmware errors and function-boundary propagation. //! Stable reportable firmware errors with bounded diagnostic ingress.
//! //!
//! This crate owns error identity and ingress. It contains no logging levels, //! This crate owns error identity and ingress. It contains no logging levels,
//! filtering, MAVLink, board, filesystem, or clock dependency. //! filtering, MAVLink, board, filesystem, or clock dependency.
//! //!
//! `#[propagate]` reports at each annotated boundary. Annotate the terminal //! `#[propagate]` turns an annotated function into a reporting point. When a
//! boundary where an error enters diagnostics; nested annotated callers would //! reportable error leaves that function, the macro makes one reporting
//! attempt to report the same propagation again. The bounded ingress retaining //! attempt. Nested annotated callers would therefore attempt to report the
//! only one pending error is backpressure, not semantic duplicate suppression. //! same error again. The bounded ingress retaining only one pending error is
//! backpressure, not semantic duplicate suppression.
#![no_std] #![no_std]
@@ -18,19 +19,19 @@ mod record;
mod sink; mod sink;
pub use ingress::take; pub use ingress::take;
pub use kaptan_err_propagate_macros::{KaptanError, propagate}; pub use kaptan_err_reportable_macros::{KaptanError, propagate};
pub use record::{ErrorId, ErrorRecord, ErrorReport}; pub use record::{ErrorId, ErrorRecord, ReportableError};
pub use sink::ErrorSink; pub use sink::ErrorSink;
/// Implementation details used only by macro expansions. /// Implementation details used only by macro expansions.
#[doc(hidden)] #[doc(hidden)]
pub mod __private { pub mod __private {
use crate::ErrorReport; use crate::ReportableError;
/// Reports an error only when it is the final result leaving an annotated /// Reports an error only when it is the final result leaving an annotated
/// function. Borrowing preserves the exact result returned to the caller. /// function. Borrowing preserves the exact result returned to the caller.
#[inline] #[inline]
pub fn report_result<T, E: ErrorReport>( pub fn report_result<T, E: ReportableError>(
result: &core::result::Result<T, E>, result: &core::result::Result<T, E>,
raised_at: &'static str, raised_at: &'static str,
) { ) {
@@ -1,6 +1,6 @@
//! Stable error IDs and bounded pending records. //! Stable error IDs and bounded pending records.
/// Stable nonzero identity for one typed firmware error variant. /// Stable nonzero identity for one reportable firmware error variant.
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(transparent)] #[repr(transparent)]
pub struct ErrorId(u16); pub struct ErrorId(u16);
@@ -21,18 +21,18 @@ impl ErrorId {
/// Implemented by [`crate::KaptanError`] derives. /// Implemented by [`crate::KaptanError`] derives.
/// ///
/// Obtaining an ID never publishes, allocates, or changes safety state. /// Obtaining an ID never publishes, allocates, or changes safety state.
pub trait ErrorReport { pub trait ReportableError {
/// Returns the stable ID assigned to this error variant. /// Returns the stable ID assigned to this error variant.
fn error_id(&self) -> ErrorId; fn error_id(&self) -> ErrorId;
} }
impl ErrorReport for ErrorId { impl ReportableError for ErrorId {
fn error_id(&self) -> ErrorId { fn error_id(&self) -> ErrorId {
*self *self
} }
} }
/// One reported typed firmware error and its reporting boundary. /// One reported firmware error and its reporting point.
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ErrorRecord { pub struct ErrorRecord {
id: ErrorId, id: ErrorId,
@@ -49,7 +49,7 @@ impl ErrorRecord {
self.id.get() self.id.get()
} }
/// Compile-time `file:line` of the propagation boundary that reported it. /// Compile-time `file:line` of the reporting point.
pub const fn raised_at(self) -> &'static str { pub const fn raised_at(self) -> &'static str {
self.raised_at self.raised_at
} }
@@ -60,7 +60,7 @@ mod tests {
use super::{ErrorId, ErrorRecord}; use super::{ErrorId, ErrorRecord};
#[test] #[test]
fn record_keeps_only_the_explicit_id_and_reporting_boundary() { fn record_keeps_only_the_explicit_id_and_reporting_point() {
let record = ErrorRecord::new(ErrorId::new(65004), "module.rs:42"); let record = ErrorRecord::new(ErrorId::new(65004), "module.rs:42");
assert_eq!(record.id(), 65004); assert_eq!(record.id(), 65004);
assert_eq!(record.raised_at(), "module.rs:42"); assert_eq!(record.raised_at(), "module.rs:42");
@@ -1,10 +1,10 @@
//! One-slot retry ownership for a typed-error sink. //! One-slot retry ownership for a reportable-error sink.
use crate::ErrorRecord; use crate::ErrorRecord;
/// Retains one typed error until a lower sink accepts it. /// Retains one reportable error until a lower sink accepts it.
/// ///
/// Typed errors are never filtered. A composition may give them priority over /// Reportable errors are never filtered. A composition may give them priority over
/// best-effort logs without coupling the producer to its transport. /// best-effort logs without coupling the producer to its transport.
pub struct ErrorSink { pub struct ErrorSink {
pending: Option<ErrorRecord>, pending: Option<ErrorRecord>,
@@ -1,4 +1,4 @@
use kaptan_err_propagate::{ErrorId, ErrorReport, KaptanError}; use kaptan_err_reportable::{ErrorId, KaptanError, ReportableError};
#[derive(Clone, Copy, Debug, Eq, PartialEq, KaptanError)] #[derive(Clone, Copy, Debug, Eq, PartialEq, KaptanError)]
enum TestError { enum TestError {
@@ -26,18 +26,18 @@ fn middle() -> Result<(), TestError> {
fail() fail()
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn succeeds() -> Result<u8, TestError> { fn succeeds() -> Result<u8, TestError> {
Ok(7) Ok(7)
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn annotated_outer() -> Result<(), TestError> { fn annotated_outer() -> Result<(), TestError> {
middle()?; middle()?;
Ok(()) Ok(())
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn annotated_inner() -> Result<(), TestError> { fn annotated_inner() -> Result<(), TestError> {
fail() fail()
} }
@@ -46,15 +46,15 @@ fn unannotated_outer() -> Result<(), TestError> {
annotated_inner() annotated_inner()
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn handles_inner_error() -> Result<(), TestError> { fn handles_inner_error() -> Result<(), TestError> {
let _handled = fail().is_err(); let _handled = fail().is_err();
Ok(()) Ok(())
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn returns_explicit_error(fail_at_boundary: bool) -> Result<(), TestError> { fn returns_explicit_error(report_error: bool) -> Result<(), TestError> {
if fail_at_boundary { if report_error {
return Err(TestError::Failed); return Err(TestError::Failed);
} }
Ok(()) Ok(())
@@ -62,24 +62,24 @@ fn returns_explicit_error(fail_at_boundary: bool) -> Result<(), TestError> {
type AliasedResult<T> = core::result::Result<T, TestError>; type AliasedResult<T> = core::result::Result<T, TestError>;
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn returns_alias() -> AliasedResult<()> { fn returns_alias() -> AliasedResult<()> {
fail() fail()
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn reports_final_converted_error() -> Result<(), OuterError> { fn reports_converted_error() -> Result<(), OuterError> {
fail()?; fail()?;
Ok(()) Ok(())
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn reports_error_id() -> Result<(), ErrorId> { fn reports_error_id() -> Result<(), ErrorId> {
Err(ErrorId::new(65003)) Err(ErrorId::new(65003))
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
async fn async_boundary() -> Result<(), TestError> { async fn async_reporting_point() -> Result<(), TestError> {
fail()?; fail()?;
Ok(()) Ok(())
} }
@@ -87,28 +87,28 @@ async fn async_boundary() -> Result<(), TestError> {
struct Service; struct Service;
impl Service { impl Service {
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn method(&self, fail_at_boundary: bool) -> Result<(), TestError> { fn method(&self, report_error: bool) -> Result<(), TestError> {
if fail_at_boundary { if report_error {
fail()?; fail()?;
} }
Ok(()) Ok(())
} }
} }
fn take_record() -> kaptan_err_propagate::ErrorRecord { fn take_record() -> kaptan_err_reportable::ErrorRecord {
kaptan_err_propagate::take().expect("escaping error must be reported") kaptan_err_reportable::take().expect("escaping error must be reported")
} }
#[test] #[test]
fn reports_only_final_errors_leaving_annotated_boundaries() { fn reports_only_errors_leaving_annotated_reporting_points() {
while kaptan_err_propagate::take().is_some() {} while kaptan_err_reportable::take().is_some() {}
assert_eq!(succeeds(), Ok(7)); assert_eq!(succeeds(), Ok(7));
assert!(kaptan_err_propagate::take().is_none()); assert!(kaptan_err_reportable::take().is_none());
assert_eq!(handles_inner_error(), Ok(())); assert_eq!(handles_inner_error(), Ok(()));
assert!(kaptan_err_propagate::take().is_none()); assert!(kaptan_err_reportable::take().is_none());
assert_eq!(annotated_outer(), Err(TestError::Failed)); assert_eq!(annotated_outer(), Err(TestError::Failed));
assert_eq!(take_record().id(), TestError::Failed.error_id().get()); assert_eq!(take_record().id(), TestError::Failed.error_id().get());
@@ -123,7 +123,7 @@ fn reports_only_final_errors_leaving_annotated_boundaries() {
assert_eq!(take_record().id(), TestError::Failed.error_id().get()); assert_eq!(take_record().id(), TestError::Failed.error_id().get());
assert_eq!( assert_eq!(
reports_final_converted_error(), reports_converted_error(),
Err(OuterError::Converted(TestError::Failed)) Err(OuterError::Converted(TestError::Failed))
); );
assert_eq!( assert_eq!(
@@ -135,9 +135,9 @@ fn reports_only_final_errors_leaving_annotated_boundaries() {
assert_eq!(take_record().id(), 65003); assert_eq!(take_record().id(), 65003);
assert_eq!(Service.method(false), Ok(())); assert_eq!(Service.method(false), Ok(()));
assert!(kaptan_err_propagate::take().is_none()); assert!(kaptan_err_reportable::take().is_none());
let mut future = core::pin::pin!(async_boundary()); let mut future = core::pin::pin!(async_reporting_point());
let mut context = core::task::Context::from_waker(core::task::Waker::noop()); let mut context = core::task::Context::from_waker(core::task::Waker::noop());
assert_eq!( assert_eq!(
core::future::Future::poll(future.as_mut(), &mut context), core::future::Future::poll(future.as_mut(), &mut context),
@@ -10,6 +10,6 @@ workspace = true
[dependencies] [dependencies]
kaptan-config = { path = "../kaptan-config" } kaptan-config = { path = "../kaptan-config" }
kaptan-err-propagate = { path = "../kaptan-err-propagate" } kaptan-err-reportable = { path = "../kaptan-err-reportable" }
kaptan-log = { path = "../kaptan-log" } kaptan-log = { path = "../kaptan-log" }
minicbor = { version = "0.25", features = ["derive"] } minicbor = { version = "0.25", features = ["derive"] }
@@ -3,7 +3,7 @@
use kaptan_config::{ use kaptan_config::{
ConfigModel, ConfigValue, ConfigViolation, FieldWriteError, ValidationRule, ValueKind, ConfigModel, ConfigValue, ConfigViolation, FieldWriteError, ValidationRule, ValueKind,
}; };
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use minicbor::{Decoder, Encoder, encode::Write}; use minicbor::{Decoder, Encoder, encode::Write};
use crate::{CandidateProfile, FORMAT_VERSION, SCHEMA_ID, VehicleCapabilities}; use crate::{CandidateProfile, FORMAT_VERSION, SCHEMA_ID, VehicleCapabilities};
+1 -1
View File
@@ -9,4 +9,4 @@ version.workspace = true
workspace = true workspace = true
[dependencies] [dependencies]
kaptan-err-propagate = { path = "../kaptan-err-propagate" } kaptan-err-reportable = { path = "../kaptan-err-reportable" }
+1 -1
View File
@@ -7,7 +7,7 @@
#![no_std] #![no_std]
use core::marker::PhantomData; use core::marker::PhantomData;
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
/// Failure reported by a checked mathematical operation. /// Failure reported by a checked mathematical operation.
/// ///
+1 -1
View File
@@ -16,7 +16,7 @@ sensor-telemetry = ["dep:kaptan-sensor"]
dialect-kaptan = [] dialect-kaptan = []
[dependencies] [dependencies]
kaptan-err-propagate = { path = "../kaptan-err-propagate" } kaptan-err-reportable = { path = "../kaptan-err-reportable" }
kaptan-dma = { path = "../kaptan-dma" } kaptan-dma = { path = "../kaptan-dma" }
kaptan-sensor = { path = "../kaptan-sensor", optional = true } kaptan-sensor = { path = "../kaptan-sensor", optional = true }
kaptan-tx = { path = "../kaptan-tx" } kaptan-tx = { path = "../kaptan-tx" }
@@ -5,9 +5,9 @@
<!-- Kaptan-reserved development block. Register these IDs before release. --> <!-- Kaptan-reserved development block. Register these IDs before release. -->
<messages> <messages>
<message id="51021" name="KAPTAN_ERROR"> <message id="51021" name="KAPTAN_ERROR">
<description>Typed firmware error reported when an Err leaves an annotated propagation boundary. This is distinct from every logging macro, which emits KAPTAN_LOG. The stable ID is explicitly assigned to the Rust error variant. Structured configuration failures remain authoritative in KAPTAN_CONFIG_RESULT.</description> <description>Reportable firmware error emitted when an Err leaves an annotated reporting point. This is distinct from every logging macro, which emits KAPTAN_LOG. The stable ID is explicitly assigned to the Rust error variant. Structured configuration failures remain authoritative in KAPTAN_CONFIG_RESULT.</description>
<field type="uint16_t" name="error_id">Stable explicitly assigned error catalog ID. Zero is reserved.</field> <field type="uint16_t" name="error_id">Stable explicitly assigned error catalog ID. Zero is reserved.</field>
<field type="uint8_t[96]" name="raised_at">Zero-padded compile-time file:line of the propagation boundary that reported the error.</field> <field type="uint8_t[96]" name="raised_at">Zero-padded compile-time file:line of the reporting point.</field>
</message> </message>
</messages> </messages>
</mavlink> </mavlink>
@@ -1,7 +1,7 @@
//! MAVLink frame encoding and UART transmission API. //! MAVLink frame encoding and UART transmission API.
use kaptan_dma::{DmaTxBufferFactory, DmaTxEngine, TxCompletion}; use kaptan_dma::{DmaTxBufferFactory, DmaTxEngine, TxCompletion};
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_tx::{PendingFrame, TransmitQueue}; use kaptan_tx::{PendingFrame, TransmitQueue};
use crate::MavlinkFrame; use crate::MavlinkFrame;
+1 -1
View File
@@ -14,7 +14,7 @@ default = []
# executable. It is not part of a board build. # executable. It is not part of a board build.
sitl = ["dep:kaptan-sensor"] sitl = ["dep:kaptan-sensor"]
[dependencies] [dependencies]
kaptan-err-propagate = { path = "../kaptan-err-propagate" } kaptan-err-reportable = { path = "../kaptan-err-reportable" }
kaptan-math = { path = "../kaptan-math" } kaptan-math = { path = "../kaptan-math" }
kaptan-sensor = { path = "../kaptan-sensor", optional = true } kaptan-sensor = { path = "../kaptan-sensor", optional = true }
kaptan-time = { path = "../kaptan-time" } kaptan-time = { path = "../kaptan-time" }
+1 -1
View File
@@ -1,6 +1,6 @@
//! Fixed-size multiplicative error-state Kalman filter. //! Fixed-size multiplicative error-state Kalman filter.
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_math::{Frd, MathError, Ned, Sensor, UnitQuaternion, Vector3, sqrt}; use kaptan_math::{Frd, MathError, Ned, Sensor, UnitQuaternion, Vector3, sqrt};
use kaptan_time::Timestamp; use kaptan_time::Timestamp;
+1 -1
View File
@@ -9,5 +9,5 @@ version.workspace = true
workspace = true workspace = true
[dependencies] [dependencies]
kaptan-err-propagate = { path = "../kaptan-err-propagate" } kaptan-err-reportable = { path = "../kaptan-err-reportable" }
kaptan-time = { path = "../kaptan-time" } kaptan-time = { path = "../kaptan-time" }
+1 -1
View File
@@ -7,7 +7,7 @@
#![no_std] #![no_std]
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_time::Timestamp; use kaptan_time::Timestamp;
/// Supervisor arming state. /// Supervisor arming state.
+1 -1
View File
@@ -15,7 +15,7 @@ workspace = true
test = false test = false
[dependencies] [dependencies]
kaptan-err-propagate = { path = "../../libs/kaptan-err-propagate" } kaptan-err-reportable = { path = "../../libs/kaptan-err-reportable" }
kaptan-config = { path = "../../libs/kaptan-config" } kaptan-config = { path = "../../libs/kaptan-config" }
kaptan-config-mavlink = { path = "../../libs/kaptan-config-mavlink" } kaptan-config-mavlink = { path = "../../libs/kaptan-config-mavlink" }
kaptan-data-channel = { path = "../../libs/kaptan-data-channel" } kaptan-data-channel = { path = "../../libs/kaptan-data-channel" }
+9 -9
View File
@@ -22,7 +22,7 @@ use kaptan_drivers::{
}, },
mtf01::Mtf01Service, mtf01::Mtf01Service,
}; };
use kaptan_err_propagate::{ErrorId, ErrorSink}; use kaptan_err_reportable::{ErrorId, ErrorSink};
use kaptan_log::{DeliveryClass, LogSinkQueue, TransportAdmission}; use kaptan_log::{DeliveryClass, LogSinkQueue, TransportAdmission};
use kaptan_spi::SpiCompletion; use kaptan_spi::SpiCompletion;
use stm32f7::stm32f722; use stm32f7::stm32f722;
@@ -525,7 +525,7 @@ impl F722LidarState {
let _ = publish_lidar_event(event); let _ = publish_lidar_event(event);
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
pub fn on_timer(&mut self) -> Result<(), StartupError> { pub fn on_timer(&mut self) -> Result<(), StartupError> {
if let Some(range) = self.range.as_mut() { if let Some(range) = self.range.as_mut() {
if self.startup_ticks < LIDAR_STARTUP_TICKS { if self.startup_ticks < LIDAR_STARTUP_TICKS {
@@ -568,7 +568,7 @@ pub fn process_imu(imu: &mut F722Imu, events: u8) {
} }
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn accept_imu_event(event: ImuEvent) -> Result<(), ErrorId> { fn accept_imu_event(event: ImuEvent) -> Result<(), ErrorId> {
match event { match event {
ImuEvent::Sample(sample) => { ImuEvent::Sample(sample) => {
@@ -683,7 +683,7 @@ where
fn drain_one_mavlink_diagnostic(&mut self) { fn drain_one_mavlink_diagnostic(&mut self) {
if self.mavlink_errors.is_empty() if self.mavlink_errors.is_empty()
&& let Some(record) = kaptan_err_propagate::take() && let Some(record) = kaptan_err_reportable::take()
{ {
let _ = self.mavlink_errors.publish_record(record); let _ = self.mavlink_errors.publish_record(record);
} }
@@ -789,7 +789,7 @@ pub fn record_mavlink_completion(completion: kaptan_dma::TxCompletion) {
} }
} }
#[kaptan_err_propagate::propagate] #[kaptan_err_reportable::propagate]
fn publish_lidar_event( fn publish_lidar_event(
event: LidarLiteV3ServiceEvent<I2c1Error>, event: LidarLiteV3ServiceEvent<I2c1Error>,
) -> Result<(), LidarError<I2c1Error>> { ) -> Result<(), LidarError<I2c1Error>> {
@@ -810,14 +810,14 @@ mod tests {
#[test] #[test]
fn transient_i2c_busy_is_retry_not_a_typed_lidar_fault() { fn transient_i2c_busy_is_retry_not_a_typed_lidar_fault() {
while kaptan_err_propagate::take().is_some() {} while kaptan_err_reportable::take().is_some() {}
assert_eq!( assert_eq!(
publish_lidar_event(LidarLiteV3ServiceEvent::Fault(LidarError::Start( publish_lidar_event(LidarLiteV3ServiceEvent::Fault(LidarError::Start(
I2c1Error::Busy, I2c1Error::Busy,
))), ))),
Ok(()) Ok(())
); );
assert!(kaptan_err_propagate::take().is_none()); assert!(kaptan_err_reportable::take().is_none());
assert!(matches!( assert!(matches!(
publish_lidar_event(LidarLiteV3ServiceEvent::Fault(LidarError::Start( publish_lidar_event(LidarLiteV3ServiceEvent::Fault(LidarError::Start(
@@ -825,7 +825,7 @@ mod tests {
))), ))),
Err(LidarError::Start(I2c1Error::InvalidLength)) Err(LidarError::Start(I2c1Error::InvalidLength))
)); ));
assert!(kaptan_err_propagate::take().is_some()); assert!(kaptan_err_reportable::take().is_some());
assert!(matches!( assert!(matches!(
publish_lidar_event(LidarLiteV3ServiceEvent::Fault(LidarError::Start( publish_lidar_event(LidarLiteV3ServiceEvent::Fault(LidarError::Start(
@@ -833,6 +833,6 @@ mod tests {
))), ))),
Err(LidarError::Start(I2c1Error::InvalidAddress)) Err(LidarError::Start(I2c1Error::InvalidAddress))
)); ));
assert!(kaptan_err_propagate::take().is_some()); assert!(kaptan_err_reportable::take().is_some());
} }
} }
+1 -1
View File
@@ -1,7 +1,7 @@
//! STM32F722 Pll216 clock-source assembly. //! STM32F722 Pll216 clock-source assembly.
use super::peripherals::{DwtMicrosecondClock, select_pll216_profile}; use super::peripherals::{DwtMicrosecondClock, select_pll216_profile};
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use stm32f7::stm32f722; use stm32f7::stm32f722;
/// Core frequency in whole megahertz after selecting the PLL216 board profile. /// Core frequency in whole megahertz after selecting the PLL216 board profile.
@@ -1,6 +1,6 @@
//! Deterministic STM32F722 PLL clock-source selection. //! Deterministic STM32F722 PLL clock-source selection.
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use stm32f7::stm32f722; use stm32f7::stm32f722;
const CLOCK_SWITCH_POLL_LIMIT: u16 = 1_024; const CLOCK_SWITCH_POLL_LIMIT: u16 = 1_024;
@@ -1,6 +1,6 @@
//! STM32F722 I²C1 interrupt-driven controller. //! STM32F722 I²C1 interrupt-driven controller.
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_i2c::{I2cBus, I2cCompletion}; use kaptan_i2c::{I2cBus, I2cCompletion};
use stm32f7::stm32f722; use stm32f7::stm32f722;
@@ -5,7 +5,7 @@
//! is generated after the last serial frame; transmit completion can occur //! is generated after the last serial frame; transmit completion can occur
//! while the final serial clock is still in progress. //! while the final serial clock is still in progress.
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_spi::SpiCompletion; use kaptan_spi::SpiCompletion;
use stm32f7::stm32f722; use stm32f7::stm32f722;
@@ -5,7 +5,7 @@
//! is generated after the last serial frame; transmit completion can occur //! is generated after the last serial frame; transmit completion can occur
//! while the final serial clock is still in progress. //! while the final serial clock is still in progress.
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_spi::SpiCompletion; use kaptan_spi::SpiCompletion;
use stm32f7::stm32f722; use stm32f7::stm32f722;
@@ -1,7 +1,7 @@
//! DWT-backed monotonic microsecond clock for STM32F722. //! DWT-backed monotonic microsecond clock for STM32F722.
use cortex_m::peripheral::{DCB, DWT}; use cortex_m::peripheral::{DCB, DWT};
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_time::{MonotonicClock, Timestamp}; use kaptan_time::{MonotonicClock, Timestamp};
/// A DWT cycle counter extended into monotonic microseconds. /// A DWT cycle counter extended into monotonic microseconds.
@@ -1,6 +1,6 @@
//! STM32F722 USART routes used by supported boards. //! STM32F722 USART routes used by supported boards.
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use stm32f7::stm32f722; use stm32f7::stm32f722;
/// UART baud-rate configuration error. /// UART baud-rate configuration error.
@@ -5,7 +5,7 @@
//! cannot be selected at construction. //! cannot be selected at construction.
use kaptan_dma::{DmaReadableBuffer, DmaTxEngine, TxCompletion}; use kaptan_dma::{DmaReadableBuffer, DmaTxEngine, TxCompletion};
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use stm32f7::stm32f722; use stm32f7::stm32f722;
use super::Usart1Tx; use super::Usart1Tx;
@@ -5,7 +5,7 @@
//! cannot be selected at construction. //! cannot be selected at construction.
use kaptan_dma::{DmaReadableBuffer, DmaTxEngine, TxCompletion}; use kaptan_dma::{DmaReadableBuffer, DmaTxEngine, TxCompletion};
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use stm32f7::stm32f722; use stm32f7::stm32f722;
use super::Usart2Tx; use super::Usart2Tx;
@@ -5,7 +5,7 @@ use kaptan_drivers::{
icm42688::{Error as Icm42688Error, Icm42688, Icm42688Service, Icm42688ServiceEvent}, icm42688::{Error as Icm42688Error, Icm42688, Icm42688Service, Icm42688ServiceEvent},
mpu6000::{Error as Mpu6000Error, Mpu6000, Mpu6000Config, Mpu6000Service, Mpu6000ServiceEvent}, mpu6000::{Error as Mpu6000Error, Mpu6000, Mpu6000Config, Mpu6000Service, Mpu6000ServiceEvent},
}; };
use kaptan_err_propagate::{ErrorId, ErrorReport}; use kaptan_err_reportable::{ErrorId, ReportableError};
use kaptan_sensor::imu::ImuSnapshot; use kaptan_sensor::imu::ImuSnapshot;
use kaptan_spi::SpiCompletion; use kaptan_spi::SpiCompletion;
use stm32f7::stm32f722; use stm32f7::stm32f722;
+1 -1
View File
@@ -9,7 +9,7 @@
#![no_std] #![no_std]
use kaptan_config::Config; use kaptan_config::Config;
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
pub use kaptan_drivers::mpu6000::{ pub use kaptan_drivers::mpu6000::{
AccelerometerRange, DigitalLowPassFilter, GyroscopeRange, Mpu6000Config, AccelerometerRange, DigitalLowPassFilter, GyroscopeRange, Mpu6000Config,
@@ -369,10 +369,10 @@ fn mavlink_transport_faults_do_not_recurse_or_retain_dead_accounting() {
} }
#[test] #[test]
fn f722_producers_keep_logs_and_typed_errors_separate() { fn f722_producers_keep_logs_and_reportable_errors_separate() {
let board = platform_source("src/f722/board.rs"); let board = platform_source("src/f722/board.rs");
let logger = platform_source("../../libs/kaptan-log/src/facade.rs"); let logger = platform_source("../../libs/kaptan-log/src/facade.rs");
let errors = platform_source("../../libs/kaptan-err-propagate/src/ingress.rs"); let errors = platform_source("../../libs/kaptan-err-reportable/src/ingress.rs");
for macro_name in [ for macro_name in [
"kaptan_log::debug!", "kaptan_log::debug!",
@@ -385,7 +385,7 @@ fn f722_producers_keep_logs_and_typed_errors_separate() {
"f722 does not exercise {macro_name}" "f722 does not exercise {macro_name}"
); );
} }
assert!(board.contains("#[kaptan_err_propagate::propagate]")); assert!(board.contains("#[kaptan_err_reportable::propagate]"));
assert!(!board.contains("report_error")); assert!(!board.contains("report_error"));
assert!(!board.contains("report_static_error")); assert!(!board.contains("report_static_error"));
assert!(logger.contains("GLOBAL_INGRESS_CAPACITY")); assert!(logger.contains("GLOBAL_INGRESS_CAPACITY"));
@@ -539,7 +539,7 @@ mod tests {
} }
#[test] #[test]
fn packet_and_history_decode_a_typed_kaptan_error() { fn packet_and_history_decode_a_reportable_kaptan_error() {
let raised_at_text = "platforms/stm32f7/src/f722/board.rs:572"; let raised_at_text = "platforms/stm32f7/src/f722/board.rs:572";
let mut raised_at = [0; 96]; let mut raised_at = [0; 96];
raised_at[..raised_at_text.len()].copy_from_slice(raised_at_text.as_bytes()); raised_at[..raised_at_text.len()].copy_from_slice(raised_at_text.as_bytes());
@@ -684,7 +684,7 @@ mod tests {
} }
#[test] #[test]
fn malformed_typed_error_location_is_not_added_to_history() { fn malformed_reportable_error_location_is_not_added_to_history() {
let mut raised_at = [0_u8; 96]; let mut raised_at = [0_u8; 96];
raised_at[0] = 0xff; raised_at[0] = 0xff;
let mut frame = MavlinkFrame::new(); let mut frame = MavlinkFrame::new();
+1 -1
View File
@@ -9,7 +9,7 @@ version.workspace = true
workspace = true workspace = true
[dependencies] [dependencies]
kaptan-err-propagate = { path = "../../libs/kaptan-err-propagate" } kaptan-err-reportable = { path = "../../libs/kaptan-err-reportable" }
kaptan-control = { path = "../../libs/kaptan-control" } kaptan-control = { path = "../../libs/kaptan-control" }
kaptan-config = { path = "../../libs/kaptan-config" } kaptan-config = { path = "../../libs/kaptan-config" }
kaptan-config-mavlink = { path = "../../libs/kaptan-config-mavlink" } kaptan-config-mavlink = { path = "../../libs/kaptan-config-mavlink" }
+1 -1
View File
@@ -7,7 +7,7 @@ use std::{
}; };
use kaptan_config::ConfigStore; use kaptan_config::ConfigStore;
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use kaptan_flight_config::{ use kaptan_flight_config::{
CandidateProfile, CborEncodeError, CborError, MAXIMUM_CANDIDATE_BYTES, VehicleProfile, CandidateProfile, CborEncodeError, CborError, MAXIMUM_CANDIDATE_BYTES, VehicleProfile,
decode_candidate, encode_candidate, decode_candidate, encode_candidate,
+1 -1
View File
@@ -4,7 +4,7 @@
//! dialect. It is confined to one host network namespace and is versioned so //! dialect. It is confined to one host network namespace and is versioned so
//! malformed simulator traffic never becomes estimator or motor authority. //! malformed simulator traffic never becomes estimator or motor authority.
use kaptan_err_propagate::KaptanError; use kaptan_err_reportable::KaptanError;
use std::net::SocketAddr; use std::net::SocketAddr;
pub const SENSOR_PORT: u16 = 14_660; pub const SENSOR_PORT: u16 = 14_660;