Phase18f docs and 0 8 0 finalize#97
Draft
JustinKovacich wants to merge 7 commits into
Draft
Conversation
Drops the std-only HashMap backing in favor of a fixed-capacity
heapless::FnvIndexMap, sized to E2E_REGISTRY_CAP = 32. The registry
is now const-constructible and no_std-compatible; gating drops from
both the registry module itself and the e2e_check / e2e_protect /
E2EState support code (none of which actually used std).
Why this matters: phase 17 / 0.8.0 gated `bare_metal_handle_impls`
behind +std specifically because StaticE2EHandle wraps E2ERegistry
and the registry's HashMap was std-only. With the registry ported,
that gate is no longer load-bearing — phase 18c will drop it. This
sub-phase isolates the storage swap so the gating change has a
clean baseline.
API surface change (breaking, queued for 0.9.0):
- E2ERegistry::register now returns Result<(), E2ERegistryFull>.
Replacing an already-registered key always succeeds (the slot is
reused). Inserting a new key when the registry is at capacity
returns Err(E2ERegistryFull(E2E_REGISTRY_CAP)).
- E2ERegistryHandle trait method `register` lifted to the same
return type, so std (Arc<Mutex<E2ERegistry>>), bare_metal
(StaticE2EHandle), and test (NullE2ERegistry) impls all forward
the typed overflow.
- Client::register_e2e and Server::register_e2e now return
Result<(), E2ERegistryFull> through to the public API. Callers
that previously discarded the unit return must add a
`?` / `.expect("E2E registry has capacity")` / explicit handling.
Two new regression tests:
- register_replacement_succeeds_when_full — re-registering an
existing key at capacity must reuse the slot (locks in the
FnvIndexMap "full + present" branch).
- register_overflow_returns_err_and_does_not_mutate — adding a new
key beyond cap returns Err(E2ERegistryFull(E2E_REGISTRY_CAP)) AND
does not insert.
512 lib tests pass (was 510; +2 new). cargo build clean across all
13 feature combos. cargo clippy --workspace --all-features
-- -D warnings -D clippy::pedantic clean. cargo build
--no-default-features (true no_std without bare_metal) compiles.
This is sub-phase 18a of phase 18 (per bare_metal_plan_v3.md).
Remaining sub-phases:
- 18b: replace std::sync references in SubscriptionManager
- 18c: provide no_std default lock-handle impls (ungate StaticE2EHandle, add StaticSubscriptionHandle)
- 18d: drop std from `client` / `server` Cargo features
- 18e: add the no_std-target CI gate (cross-build for thumbv7em-none-eabihf)
- 18f: docs + 0.9.0 bump
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Narrow scope per bare_metal_plan_v3.md 18b: drop the unconditional
`use std::{net::SocketAddrV4, vec::Vec};` from production code in
`src/server/subscription_manager.rs`, gate `get_subscribers ->
std::vec::Vec<Subscriber>` behind `#[cfg(feature = "std")]`, and
swap the unconditional `std::net::SocketAddrV4` import for
`core::net::SocketAddrV4`. The internal storage (FnvIndexMap +
heapless::Vec) was already heap-free since phase 13.5/13.6; this
sub-phase is what makes it literally compile in pure no_std.
`get_subscribers` is the only Vec-returning method on the manager,
and production code paths migrated to `for_each_subscriber`
(visitor) in phase 17. Std consumers keep the convenience accessor
unchanged; no_std consumers either use `for_each_subscriber` or
collect into their own heapless::Vec.
Out of scope (deferred to 18d's broad sweep):
- ServiceInfo / EventGroupInfo (still use std::vec::Vec for their
pub fields) — 18d will port to heapless::Vec with documented
caps.
- event_publisher.rs / sd_state.rs / mod.rs std::sync references
for the `Arc<Mutex<E2ERegistry>>` / `Arc<RwLock<...>>` lock-handle
defaults.
Verification:
- cargo build --no-default-features clean
- cargo build --no-default-features --features bare_metal clean
- cargo build --all-features clean
- cargo clippy --workspace --all-features -- -D warnings -D clippy::pedantic clean
- cargo clippy --no-default-features -- -D warnings -D clippy::pedantic clean
- cargo test --lib --all-features: 512 pass, 0 fail (no regressions)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two changes that complete the no_std default lock-handle story for
the bare-metal server:
1. Drop the `+ std` gate from `bare_metal_e2e_impl`. Phase 18a
ported `E2ERegistry` to `heapless::FnvIndexMap`, so
`StaticE2EHandle` no longer needs std. It's now reachable in
pure no_std builds via `feature = "bare_metal"` alone. Updated
the lib.rs feature-table line accordingly.
2. New `StaticSubscriptionHandle` (and `StaticSubscriptionStorage`
alias) in `src/server/subscription_manager.rs`. Modeled on
`StaticE2EHandle`: a `&'static BlockingMutex<CriticalSectionRawMutex,
RefCell<SubscriptionManager>>` wrapper that implements the full
`SubscriptionHandle` trait (subscribe / unsubscribe /
for_each_subscriber). Gated on `feature = "bare_metal"`, so
bare-metal Server consumers no longer need to write their own
subscription handle.
Made `SubscriptionManager::new()` `const` so the storage can live in
a plain `static`, no `Box::leak` required:
```rust
static SUBS: StaticSubscriptionStorage =
Mutex::new(RefCell::new(SubscriptionManager::new()));
let handle = StaticSubscriptionHandle::new(&SUBS);
```
Re-exported `StaticSubscriptionHandle` and `StaticSubscriptionStorage`
from `server::*` (gated on `bare_metal`).
Regression test (`static_subscription_handle_full_contract`) walks
subscribe → for_each_subscriber → unsubscribe → for_each_subscriber
through the trait surface to lock in the wiring. Includes a
`block_on_sync` helper that asserts the futures complete
synchronously (no .await inside the critical section), since the
embassy-sync `lock` closure is sync.
After this sub-phase, the three default lock-handles
(`StaticE2EHandle`, `AtomicInterfaceHandle`, `StaticSubscriptionHandle`)
are all available on pure no_std via `feature = "bare_metal"` —
matching the surface that bare-metal Client + Server consumers will
need from 18d onward when `client` / `server` features drop their
std requirement.
Verification:
- cargo build --no-default-features --features bare_metal clean
- cargo build --no-default-features --features server,bare_metal clean
- cargo build --all-features clean
- cargo clippy --workspace --all-features -- -D warnings -D clippy::pedantic clean
- cargo clippy --no-default-features -- -D warnings -D clippy::pedantic clean
- cargo test --lib --all-features: 513 pass, 0 fail (+1 new test)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The actual gate-closer for phase 18. After this sub-phase: cargo build --no-default-features --features client,server,bare_metal …compiles in pure no_std (no allocator required for `client`; `server` still pulls `extern crate alloc;` for its `Arc<EventPublisher>` / `Arc<Socket>` plumbing, documented as a known limitation tracked for a future refactor). ## Cargo.toml - `client = ["dep:futures"]` (was `["std", "dep:futures"]`). - `server = ["dep:futures"]` (was `["std", "dep:futures"]`). - `client-tokio = ["client", "std", "dep:tokio", "dep:socket2"]` (added `"std"` so the tokio convenience constructors keep their std backing). - `server-tokio = ["server", "std", "dep:tokio", "dep:socket2"]` (same). - `extern crate alloc;` in lib.rs now activates on `cfg(any(feature = "embassy_channels", feature = "server"))` instead of just `embassy_channels`. Server's Arc usage is the trigger. ## Trait surface change (breaking, queued for 0.9.0) `PayloadWireFormat` was tangled with std-only items (`new_subscription_sd_header` took `std::net::Ipv4Addr`; `offered_endpoints` / `service_instances` returned `Vec<_>`; `set_reboot_flag` was `cfg(feature = "std")`). Restructured: - `OfferedEndpoint` is no longer std-gated; `addr` is now `Option<core::net::SocketAddrV4>`. - `set_reboot_flag` is no longer std-gated. - `new_subscription_sd_header` is no longer std-gated; `client_ip` is now `core::net::Ipv4Addr`. - `offered_endpoints -> Vec<...>` and `service_instances -> Vec<...>` replaced by visitor-pattern `for_each_offered_endpoint(&self, F)` and `for_each_service_instance(&self, F)` (no_std-friendly, alloc-free). - Old `offered_endpoints` / `service_instances` Vec-returning signatures preserved as `cfg(feature = "std")` convenience wrappers that delegate to the new visitors. Std consumers' code keeps compiling unchanged. `Client::run_future` updated to use the new visitor methods directly. `RawPayload`'s impl block updated to override the new visitor signatures (was overriding the old Vec-returning ones). ## server::Error API change - `Error::Io(std::io::Error)` is now gated on `cfg(feature = "std")`. No-std consumers receive transport failures via `Error::Transport(_)` carrying the portable `IoErrorKind` instead. - New `Error::InvalidUsage(&'static str)` variant for misuse paths (`announcement_loop` on a passive server, `announcement_loop` called twice, `run` on a passive server). These previously returned `Error::Io(std::io::Error::new(InvalidInput, ...))` with a formatted message; the new variant carries a `&'static str` tag and the diagnostic moves to `tracing::warn!`. Tags: `"passive_server_announcement_loop"`, `"announcement_loop_already_started"`, `"passive_server_run"`. ## ServiceInfo / EventGroupInfo Both gated on `cfg(feature = "std")` because their pub fields hold `Vec<EventGroupInfo>` / `Vec<u16>`. Bare-metal consumers don't construct these types today; a future port will switch to `heapless::Vec` if a use case emerges. `Subscriber` (no Vec field) stays no_std and exported. ## Other std → core sweeps - `src/client/session.rs`: `std::net::SocketAddr` → `core::net::SocketAddr`. - `src/client/socket_manager.rs`: same. - `src/client/inner.rs`: removed `use std::borrow::ToOwned;`, replaced `sd_header.to_owned()` with `Clone::clone(sd_header)`; replaced `std::future::poll_fn` with `core::future::poll_fn`; replaced `std::fmt::*` with `core::fmt::*`. - `src/server/mod.rs`: `std::net::*` → `core::net::*`, `Arc` from `alloc::sync::Arc`, large `vec![0u8; 65535]` buffers use `alloc::vec![]`. - `src/server/event_publisher.rs`: `Arc` from `alloc::sync::Arc`, `std::net::SocketAddrV4` → `core::net::SocketAddrV4`. - `src/server/sd_state.rs`: `std::net::SocketAddrV4` → `core::net`. - 3 server::tests assertions updated for the new `Error::InvalidUsage` variant (was matching `Error::Io` with InvalidInput kind). ## Verification - cargo build --all-features clean - cargo build --no-default-features clean - cargo build --no-default-features --features client clean - cargo build --no-default-features --features server clean - cargo build --no-default-features --features client,bare_metal clean - cargo build --no-default-features --features server,bare_metal clean - cargo build --no-default-features --features client,server,bare_metal clean - cargo clippy --workspace --all-features -- -D warnings -D clippy::pedantic clean - cargo clippy --no-default-features -- -D warnings -D clippy::pedantic clean - cargo clippy --no-default-features --features client,bare_metal -- -D warnings -D clippy::pedantic clean - cargo fmt --all --check clean - cargo test --lib --all-features: 513 pass, 0 fail (test assertions updated for new error variant) The `cargo build --target thumbv7em-none-eabihf` cross-compile gate is the next sub-phase (18e). Locally these cargo build invocations target host x86_64 — they prove the std refs are gone but do NOT prove the bare-metal ABI works end-to-end. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cross-compiling `client,server,bare_metal` to a true no_std target
surfaced two issues that the host-side x86_64 build hid:
1. **`futures::select!` requires the futures crate's `std` feature**,
which transitively pulls `slab` / `memchr` / `futures-io` —
none of which compile on no_std. Switched dep from the `futures`
umbrella to `futures-util` directly with features
`["async-await", "async-await-macro"]`. `select_biased!` is in
that subset; `select!` is not (it needs std for the random
fairness shuffle). Replaced all four `select!` call sites with
`select_biased!`.
Behavioral consequence: `select_biased!` polls arms top-first
instead of pseudo-randomly. For our three uses
(`socket_loop_future`, `Inner::run_future`, `server::run`) the
bias actually gives slightly better behavior — control messages
and sends get priority over recvs. Genuine starvation requires
the top arm to never go pending, which doesn't happen for any
of these workloads (sends are sporadic, control is sparse, SD
multicast is 1Hz).
2. **`futures::FutureExt::catch_unwind` requires futures-util's
`std` feature.** Replaced the catch-unwind dance with
`JoinHandle::is_panic()` on the `JoinHandle` returned by
`tokio::spawn`. A second tokio task awaits the join and logs
the panic via `tracing::error!` if `is_panic()` is true. Same
observable behavior, no extra dep gating needed.
Verification — both host AND cortex-m4f cross-compile:
cargo build --all-features ✓
cargo build --no-default-features ✓
cargo build --no-default-features --features bare_metal ✓
cargo build --no-default-features --features client,bare_metal ✓
cargo build --no-default-features --features server,bare_metal ✓
cargo build --no-default-features --features client,server,bare_metal ✓
cargo build --target thumbv7em-none-eabihf --no-default-features --features bare_metal ✓
cargo build --target thumbv7em-none-eabihf --no-default-features --features client,bare_metal ✓
cargo build --target thumbv7em-none-eabihf --no-default-features --features server,bare_metal ✓
cargo build --target thumbv7em-none-eabihf --no-default-features --features client,server,bare_metal ✓
cargo clippy --workspace --all-features -- -D warnings -D clippy::pedantic ✓
cargo fmt --all --check ✓
cargo test --lib --all-features: 513 pass, 0 fail ✓
Alloc-symbol audit on the cortex-m4f rlib:
client + bare_metal: 0 alloc references (truly alloc-free)
client + server + bare_metal: 14 alloc references (Arc<EventPublisher>
/ Arc<F::Socket> as documented in 18d)
This commit closes phase 18's literal compile gate. The 18e CI step
(adding the cross-build to `.github/workflows/ci.yml`) plus 18f
(0.9.0 docs + bump) remain.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Locks in phase 18's literal compile gate by cross-building the crate for `thumbv7em-none-eabihf` (cortex-m4f, no_std, no allocator) on every PR. Until this job is green, the crate cannot actually be consumed on bare-metal — phases 4–17 shipped the trait surface and no-alloc primitives but the literal cross-build was never verified in CI. Four feature combos exercised, each as a separate `cargo build` so a failure surfaces the specific combo that regressed: - bare_metal alone - server + bare_metal - client + server + bare_metal - client + bare_metal (last, for the alloc-symbol audit below) Plus an alloc-symbol audit step: greps the resulting `libsimple_someip.rlib` for `__rust_alloc` / `__rg_alloc` and fails if any are found. `client + bare_metal` MUST stay alloc-free. The `server` and `client+server` paths reference allocator symbols via `Arc<EventPublisher>` / `Arc<F::Socket>` (documented in `src/lib.rs`) and are not gated by the audit. ## Why thumbv7em-none-eabihf and not tricore The project's actual production target is Infineon AURIX TriCore. Mainline Rust does not have a TriCore target — `rustc --print target-list | grep tricore` returns nothing, and upstream LLVM does not ship a TriCore backend. Compiling Rust for TriCore today requires HighTec's commercial Rust distribution (or a custom LLVM build with their out-of-tree TriCore backend). `thumbv7em-none-eabihf` is the closest no_std proxy mainline Rust supports and runs for free in GitHub Actions: - Same `no_std` posture (no `extern crate std`). - Same alloc-optionality (no implicit allocator). - Same `core::*` / `alloc::*` surface. - Same fixed-width integer / atomic widths as TC1.6. What the proxy does NOT prove for TriCore: - LLVM TriCore-specific codegen edge cases. - Atomic-instruction lowering on the actual chip. - `critical-section` impl behavior under TriCore's split ISR / main-thread context model. A future phase 20 will swap (or layer) this CI step onto a TriCore HighTec runner once that infrastructure is in place. For now, the cortex-m4f proxy is the strongest verification CI can give us without a TriCore toolchain. Verified locally: cargo build --target thumbv7em-none-eabihf --no-default-features --features bare_metal ✓ cargo build --target thumbv7em-none-eabihf --no-default-features --features client,bare_metal ✓ cargo build --target thumbv7em-none-eabihf --no-default-features --features server,bare_metal ✓ cargo build --target thumbv7em-none-eabihf --no-default-features --features client,server,bare_metal ✓ alloc-symbol audit: client+bare_metal = 0 alloc references in rlib ✓ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final sub-phase for the literal no_std compile gate. Folds 18a-18e
into the existing 0.8.0 CHANGELOG entry, updates the lib.rs and
README feature tables, and rewrites the bare-metal examples to use
the new no-alloc lock handles directly (no more `Arc<Mutex<_>>` /
`Arc<RwLock<_>>` placeholders).
## CHANGELOG
Folded into 0.8.0's existing Added / Changed / Notes sections:
Added:
- StaticSubscriptionHandle + StaticSubscriptionStorage
- server::Error::InvalidUsage(&'static str)
- E2ERegistryFull (typed overflow on E2ERegistry::register)
- PayloadWireFormat::for_each_offered_endpoint /
for_each_service_instance visitor methods
Changed (breaking, queued for 0.8.0):
- client / server features no longer imply std (moved to
*-tokio); client compiles in pure no_std, server pulls
extern crate alloc for Arc<EventPublisher> /
Arc<F::Socket>.
- futures dep replaced with futures-util (futures::select! is
std-gated; switched to select_biased!).
- Internal select! → select_biased! (top-arm-first instead of
pseudo-random; observable only under contrived workloads).
- PayloadWireFormat::offered_endpoints / service_instances
Vec-returning forms preserved as cfg(feature = "std")
convenience wrappers; trait now requires the visitor methods.
- PayloadWireFormat::set_reboot_flag and
new_subscription_sd_header no longer std-gated.
- OfferedEndpoint no longer std-gated; addr is
Option<core::net::SocketAddrV4>.
- server::Error::Io now cfg(feature = "std")-gated; misuse paths
return Error::InvalidUsage(tag) instead.
- SubscriptionManager::get_subscribers now
cfg(feature = "std")-only.
- server::ServiceInfo / server::EventGroupInfo now
cfg(feature = "std")-only.
- E2ERegistry: HashMap → heapless::FnvIndexMap (cap = 32);
register returns Result<(), E2ERegistryFull>; new() is const.
- E2ERegistryHandle::register trait method lifts the same
Result through every impl.
Notes:
- Bare-metal compile gate is now literal — cargo build
--target thumbv7em-none-eabihf --no-default-features --features
client,server,bare_metal succeeds in CI; client + bare_metal
is verified alloc-free.
- Known limitation: server pulls extern crate alloc; refactor
to &'static borrows tracked for v3 phase 21+.
## lib.rs feature table
Rewritten to honestly describe each feature:
- std: now described as the gate for the std lock-handle defaults
(Arc<Mutex<E2ERegistry>> etc.) used by tokio backends.
- client: pure no_std-clean, does not pull extern crate alloc.
- server: pulls extern crate alloc.
- client-tokio / server-tokio: imply client/server + std.
- bare_metal: lists all five no-alloc types
(static_channels, AtomicInterfaceHandle, StaticE2EHandle,
StaticSubscriptionHandle).
## README feature table
Mirrors lib.rs. Adds explicit note that the cross-build for
thumbv7em is verified in CI.
## Examples — bare_metal_client / bare_metal_server
Both now use the actual no-alloc handles end-to-end:
- StaticE2EHandle over &'static StaticE2EStorage (was
Arc<Mutex<E2ERegistry>>)
- AtomicInterfaceHandle over &'static AtomicU32 (was
Arc<RwLock<Ipv4Addr>>) -- bare_metal_client only
- StaticSubscriptionHandle over &'static
StaticSubscriptionStorage (was MockSubscriptions, ~75 LoC of
inline trait impl deleted) -- bare_metal_server only
Storage `static`s declared at module scope (clippy::pedantic
dislikes `static` after `let`). `E2ERegistry::new()` and
`SubscriptionManager::new()` are both const, so no Box::leak.
Both example Cargo.toml files now opt into the std feature
explicitly. The examples use RawPayload (std-only) and tokio for
their host-side mock drivers; firmware drops std and provides its
own PayloadWireFormat impl. Documented inline.
The "What is not yet demonstrated" stale section in
bare_metal_client is gone — there is nothing left undemonstrated;
the example covers the actual firmware-target shape end-to-end.
## Verification
cargo fmt --all --check ✓
cargo clippy --workspace --all-features -- -D warnings -D clippy::pedantic ✓
cargo clippy --no-default-features -- -D warnings -D clippy::pedantic ✓
cargo test --lib --all-features: 513 pass ✓
cargo run -p bare_metal_client ✓ (runs end-to-end)
cargo run -p bare_metal_server ✓ (announces + asserts SD sent)
cargo build --target thumbv7em-none-eabihf --no-default-features --features client,server,bare_metal ✓
Phase 18 (a through f) is complete. The literal "client + server
compile on cortex-m4f no_std" gate from bare_metal_plan_v3.md is
closed and CI-enforced. Phase 19 (embassy-net reference adapter)
is the next milestone per the v3 plan.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR finalizes the 0.8.0 “phase18f” work to make the crate’s client/server trait surfaces viable on real no_std targets, eliminating hidden heap usage in hot paths and adding CI enforcement for the bare-metal build matrix.
Changes:
- Make E2E registry and SD parsing
no_std-compatible (fixed-capacityheaplessregistry + visitor APIs replacingVecreturns). - Introduce/expand bare-metal handle implementations (
StaticE2EHandle,StaticSubscriptionHandle) and adjust public APIs to surface capacity/misuse errors. - Replace
futuresumbrella usage withfutures-utiland add a new CI job to cross-build and audit alloc usage on a thumb target.
Reviewed changes
Copilot reviewed 27 out of 28 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/no_alloc_witness.rs | Updates E2E registration calls to handle fallible register() without allocating in hot paths. |
| tests/client_server.rs | Updates integration test to handle fallible register_e2e(). |
| src/transport.rs | Makes E2ERegistryHandle::register fallible; exposes bare-metal E2E handle under bare_metal (not std). |
| src/traits.rs | Introduces visitor APIs for SD iteration; makes OfferedEndpoint no_std-friendly. |
| src/tokio_transport.rs | Changes tokio task panic logging strategy to use a watcher task + JoinError. |
| src/server/subscription_manager.rs | Makes SubscriptionManager::new() const; adds StaticSubscriptionHandle; gates heap-alloc accessor behind std. |
| src/server/service_info.rs | Gates heap-backed service info types behind std; keeps Subscriber no_std. |
| src/server/sd_state.rs | Moves SocketAddrV4 usage to core::net for no_std. |
| src/server/mod.rs | Makes server APIs no_std friendlier (InvalidUsage tags), switches address types to core::net, and updates select macro usage. |
| src/server/event_publisher.rs | Uses alloc::sync::Arc and core::net address types; updates E2E registration calls. |
| src/server/error.rs | Gates Error::Io behind std; adds Error::InvalidUsage for misuse paths. |
| src/raw_payload.rs | Implements SD iteration via new visitor methods (keeps std-only convenience type). |
| src/lib.rs | Updates feature docs and alloc gating rules; exports StaticE2EHandle under bare_metal. |
| src/e2e/registry.rs | Replaces HashMap with fixed-capacity FnvIndexMap; adds E2ERegistryFull + cap constant. |
| src/e2e/mod.rs | Makes E2E registry available outside std and exports new cap/error types. |
| src/client/socket_manager.rs | Updates to futures-util and biased select usage; updates E2E registration calls. |
| src/client/session.rs | Switches SocketAddr import to core::net. |
| src/client/mod.rs | Makes register_e2e fallible and switches Debug bounds/imports to core. |
| src/client/inner.rs | Uses visitor APIs for SD iteration and switches to futures-util biased select usage. |
| examples/bare_metal_server/src/main.rs | Switches host example to use static bare-metal handles for E2E + subscriptions. |
| examples/bare_metal_server/Cargo.toml | Enables std for host tokio usage; adds explicit embassy-sync dep for storage types. |
| examples/bare_metal_client/src/main.rs | Switches host example to static bare-metal E2E + atomic interface handle. |
| examples/bare_metal_client/Cargo.toml | Enables std for RawPayload in host example; adds explicit embassy-sync dep. |
| README.md | Updates feature matrix and no_std guidance to match new feature split and handles. |
| Cargo.toml | Replaces optional futures with optional futures-util; updates feature wiring for client/server. |
| Cargo.lock | Reflects dependency graph changes (futures-util, embassy-sync in examples). |
| CHANGELOG.md | Documents breaking changes and new no_std/bare-metal contracts for 0.8.0. |
| .github/workflows/ci.yml | Adds thumb no_std cross-build + alloc-symbol audit job. |
Comments suppressed due to low confidence (1)
src/server/mod.rs:679
- The comment claims
select!(unbiased) is used for pseudo-random fairness, but the code now usesselect_biased!, which always prioritizes the first ready arm. Either switch back to the unbiasedselect!macro, or update the comment and ensure the bias cannot starve SD-multicast receive handling under sustained unicast load (SD socket backlog/drops).
// `select!` (not `select_biased!`) gives pseudo-random fairness
// across ready arms each poll — matches the prior
// `tokio::select!` behavior and avoids starving either the
// unicast or SD-multicast arm under sustained one-sided load.
//
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
476
to
486
| &self, | ||
| ) -> Result<impl core::future::Future<Output = ()> + Send + 'static, Error> { | ||
| if self.is_passive { | ||
| return Err(Error::Io(std::io::Error::new( | ||
| std::io::ErrorKind::InvalidInput, | ||
| format!( | ||
| "announcement_loop called on passive Server for service 0x{:04X}; \ | ||
| announcements must be driven externally (e.g. via \ | ||
| `simple_someip::Client::sd_announcements_loop`)", | ||
| self.config.service_id | ||
| ), | ||
| ))); | ||
| tracing::warn!( | ||
| "announcement_loop called on passive Server for service 0x{:04X}; \ | ||
| announcements must be driven externally (e.g. via \ | ||
| `simple_someip::Client::sd_announcements_loop`)", | ||
| self.config.service_id | ||
| ); | ||
| return Err(Error::InvalidUsage("passive_server_announcement_loop")); | ||
| } |
Comment on lines
649
to
662
| use crate::protocol::MessageView; | ||
|
|
||
| if self.is_passive { | ||
| return Err(Error::Io(std::io::Error::new( | ||
| std::io::ErrorKind::InvalidInput, | ||
| format!( | ||
| "run called on passive Server for service 0x{:04X}; \ | ||
| SD receive must be driven externally (e.g. via the \ | ||
| Client's discovery socket, routing Subscribes to \ | ||
| `EventPublisher::register_subscriber`)", | ||
| self.config.service_id | ||
| ), | ||
| ))); | ||
| tracing::warn!( | ||
| "run called on passive Server for service 0x{:04X}; \ | ||
| SD receive must be driven externally (e.g. via the \ | ||
| Client's discovery socket, routing Subscribes to \ | ||
| `EventPublisher::register_subscriber`)", | ||
| self.config.service_id | ||
| ); | ||
| return Err(Error::InvalidUsage("passive_server_run")); | ||
| } | ||
|
|
||
| // Incoming-peer buffers sized to the IP datagram limit (64 KiB - 1). |
| let recv_fut = socket.recv_from(&mut buf).fuse(); | ||
| pin_mut!(send_fut, recv_fut); | ||
| select! { | ||
| select_biased! { |
Comment on lines
1075
to
1080
| // `select!` (not `select_biased!`) randomizes the | ||
| // arm check order each poll so no single arm can | ||
| // starve the others under sustained load. Matches | ||
| // the original `tokio::select!` fairness behavior. | ||
| select! { | ||
| select_biased! { | ||
| // Receive a control message |
Comment on lines
+106
to
+110
| alloc_refs=$(nm -A "$rlib" 2>/dev/null | grep -c -E '__rust_alloc|__rg_alloc' || true) | ||
| echo "client+bare_metal alloc-symbol references: $alloc_refs" | ||
| if [ "$alloc_refs" -ne 0 ]; then | ||
| echo "::error::client+bare_metal must be alloc-free; found $alloc_refs alloc references." | ||
| nm -A "$rlib" 2>/dev/null | grep -E '__rust_alloc|__rg_alloc' || true |
Comment on lines
74
to
+83
| # Feature split (matches the client side): `server` exposes the | ||
| # trait-surface server (no tokio, no socket2). The engine itself uses | ||
| # `futures::select!` so `dep:futures` lives here. `server-tokio` adds | ||
| # the tokio + socket2 convenience defaults (`Server::new`, | ||
| # `Server::new_with_loopback`, `Server::new_passive`), bringing | ||
| # `Arc<Mutex<E2ERegistry>>` / `Arc<RwLock<SubscriptionManager>>` / | ||
| # / `TokioTransport` / `TokioTimer` defaults into scope. | ||
| server = ["std", "dep:futures"] | ||
| server-tokio = ["server", "dep:tokio", "dep:socket2"] | ||
| # trait-surface server (no tokio, no socket2, no std). The engine | ||
| # itself uses `futures::select!` so `dep:futures` lives here. | ||
| # `server-tokio` adds the tokio + socket2 convenience defaults | ||
| # (`Server::new`, `Server::new_with_loopback`, `Server::new_passive`), | ||
| # bringing `Arc<Mutex<E2ERegistry>>` / `Arc<RwLock<SubscriptionManager>>` / | ||
| # / `TokioTransport` / `TokioTimer` defaults into scope, and forces | ||
| # `std`. | ||
| server = ["dep:futures-util"] | ||
| server-tokio = ["server", "std", "dep:tokio", "dep:socket2"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.