Expand description
§Simple SOME/IP
A Rust implementation of the SOME/IP automotive communication protocol — remote procedure calls, event notifications, service discovery, and wire-format serialization.
The core protocol layer (protocol, e2e, and trait modules) is no_std-compatible with
zero heap allocation, making it suitable for embedded targets. Optional client and server
modules provide async tokio-based networking for std environments.
§Modules
| Module | no_std | Description |
|---|---|---|
protocol | Yes | Wire format: headers, messages, message types, return codes, and service discovery (SD) entries/options |
e2e | Yes | End-to-End protection — Profile 4 (CRC-32) and Profile 5 (CRC-16) |
WireFormat / PayloadWireFormat | Yes | Traits for serializing messages and defining custom payload types |
client | No | Async client trait surface — service discovery, subscriptions, request/response (feature client; add client-tokio for Client::new) |
server | No | Async server trait surface — service offering, event publishing, subscription management (feature server; add server-tokio for Server::new) |
§Feature Flags
| Feature | Default | Description |
|---|---|---|
std | yes | Enables std-dependent helpers (RawPayload, VecSdHeader) and the Arc<Mutex<E2ERegistry>> / Arc<RwLock<…>> default lock-handle impls used by the tokio backends. |
client | no | Trait-surface client. Pure no_std-clean (does not pull extern crate alloc). Caller supplies Spawner / Timer / ChannelFactory / TransportFactory / E2ERegistryHandle / InterfaceHandle impls. |
client-tokio | no | Adds the Client::new / TokioSpawner / TokioTransport convenience defaults; implies client + std + tokio + socket2. |
server | no | Trait-surface server. Alloc-free since PR #124: the no-alloc path is Server::new_with_handles + run_with_buffers with static handles. The Arc-backed conveniences (new_with_deps, run) are gated behind the internal _alloc feature (pulled in by std / embassy_channels). |
server-tokio | no | Adds the Server::new / TokioTransport / TokioTimer convenience defaults; implies server + std + tokio + socket2. |
bare_metal | no | Activates embassy-sync, the static_channels module (no-alloc ChannelFactory), AtomicInterfaceHandle, StaticE2EHandle, and StaticSubscriptionHandle. All five are pure no_std (no allocator required). See examples/bare_metal_client/ and examples/bare_metal_server/ for runnable bare-metal integration examples. |
embassy_channels | no | Heap-backed EmbassySyncChannels ChannelFactory. Implies bare_metal and pulls extern crate alloc; into the crate; on no_std, downstream consumers must provide a #[global_allocator]. Useful for tests / early prototypes before sizing static pools. |
The default feature set is ["std"], which links std and enables
the RawPayload / VecSdHeader helpers. For a minimal build with
no allocator requirement — the protocol, trait, transport, and
e2e modules only — pass --no-default-features. The
trait-surface canary workspace members (examples/bare_metal_client,
examples/bare_metal_server) depend on the crate with
default-features = false, features = ["bare_metal", "client"] /
["bare_metal", "server"] and validate that configuration when built
in isolation (cargo build -p bare_metal_client /
cargo build -p bare_metal_server), rather than as part of a workspace-wide
build where features may be unified across members.
§Examples
§Encoding a SOME/IP-SD header (no_std)
use simple_someip::WireFormat;
use simple_someip::protocol::sd::{self, Entry, RebootFlag, ServiceEntry};
// Build an SD header with a FindService entry
let entries = [Entry::FindService(ServiceEntry::find(0x1234))];
// A fresh process should set RebootFlag::RecentlyRebooted until its
// session counter wraps past 0xFFFF for the first time.
let sd_header =
sd::Header::new(sd::Flags::new_sd(RebootFlag::RecentlyRebooted), &entries, &[]);
// Encode to bytes
let mut buf = [0u8; 64];
let n = sd_header.encode(&mut buf.as_mut_slice()).unwrap();
// Decode from bytes (zero-copy view)
let view = sd::SdHeaderView::parse(&buf[..n]).unwrap();
assert_eq!(view.entry_count(), 1);§Async client (requires feature = "client-tokio")
use simple_someip::{Client, ClientUpdate, RawPayload};
#[tokio::main]
async fn main() {
// Client::new returns a Clone-able handle, an update stream, and
// the run-loop future. Spawn the future on the tokio runtime;
// the returned future depends on `tokio::select!` / `tokio::time`
// / tokio sockets, so it is not executor-agnostic today.
let (client, mut updates, run) = Client::<RawPayload, _, _, _>::new([192, 168, 1, 100].into());
let _run_task = tokio::spawn(run);
client.bind_discovery().await.unwrap();
while let Some(update) = updates.recv().await {
match update {
ClientUpdate::DiscoveryUpdated(msg) => { /* SD message received */ }
ClientUpdate::Unicast { message, e2e_status, source } => { /* unicast reply */ }
ClientUpdate::SenderRebooted(addr) => { /* remote reboot */ }
ClientUpdate::Error(err) => { /* error */ }
}
}
}§References
Re-exports§
pub use e2e::E2ECheckStatus;pub use e2e::E2EKey;pub use e2e::E2EProfile;pub use transport::ChannelFactory;pub use transport::E2ERegistryHandle;pub use transport::InterfaceHandle;pub use transport::IoErrorKind;pub use transport::LocalSpawner;pub use transport::MpscRecv;pub use transport::MpscSend;pub use transport::OneshotCancelled;pub use transport::OneshotRecv;pub use transport::OneshotSend;pub use transport::ReceivedDatagram;pub use transport::SocketOptions;pub use transport::Spawner;pub use transport::Timer;pub use transport::TransportError;pub use transport::TransportFactory;pub use transport::TransportSocket;pub use transport::UnboundedRecv;pub use transport::UnboundedSend;
Modules§
- buffer_
pool - Fixed-capacity pool of
&'static mut [u8]receive/scratch buffers. Pureno_std(uses onlycore::). Exposed without a feature gate so both the bare-metal and std/tokio paths can reachbuffer_pool::BufferPoolandbuffer_pool::BufferLease. Fixed-capacity pool of byte buffers with claim/release semantics, mirroring the channel pools in this module. ABufferPoolis declared as astatic(bare-metal) or held behind anArc(std/tokio) by the consumer; each claim hands out one slot as aBufferLease(a rawNonNullslice whose exclusivity is enforced by the per-slotAtomicBool, not the borrow checker) that returns the slot on drop. - e2e
- End-to-end (E2E) protection utilities for SOME/IP payloads. E2E (End-to-End) protection for SOME/IP payloads.
- protocol
- SOME/IP protocol primitives: headers, messages, return codes, and service discovery.
- transport
- Executor-agnostic UDP transport abstraction used by the client and
server modules.
no_std-compatible; a defaultstd + tokiobackend ships intokio_transport(available under theclient-tokio/server-tokiofeatures) — the link is rendered as a code literal because the target module is feature-gated and would break default-feature rustdoc builds. Executor-agnostic transport abstraction.
Structs§
- Offered
Endpoint - Information about a service endpoint extracted from an SD message.
- RawPayload
- A concrete
PayloadWireFormatbacked by heap-allocated storage. - VecSd
Header - Owned SD header backed by heap-allocated vectors.
Constants§
- UDP_
BUFFER_ SIZE - Maximum size, in bytes, of UDP payloads for
client/serversend paths that serialize into a fixed-size buffer of this size.
Traits§
- Payload
Wire Format - A trait for SOME/IP Payload types that can be serialized to a
Writerand constructed from raw payload bytes. - Wire
Format - A trait for types that can be serialized to a
Writer.