corpus-ipc
Inter-Process Communication (IPC) library for bridging Rust to external compute engines.
corpus-ipc is the schema and transport layer for cross-process compute workflows. It provides backend abstractions for local/native execution and optional ZeroMQ IPC, plus canonical wire message models used across services.
Features
IpcBackendtrait for backend-agnostic signal processing (deprecated alias:RuntimeBackend)RustBackendreference backend (always available)ZmqIpcBackendbackend via ZMQ SUB socket (featurezmq; deprecated alias:ZmqRuntimeBackend)- Optional
corpus_ipc_serverREST binary (featureserver; not compiled for library consumers) - Canonical protocol models:
IpcMessageSpikeBatch,SpikeEvent(IPC wire types; aliasIpcSpikeBatch)EmbeddingBatchStimulusBatchfor typed, variable-width runtime stimulus ingressGradientBatch,GradientUpdateTraceBatch,TraceData(IPC wire types; aliasIpcTraceBatch)ConfigPayload,ConfigValue,BatchMetadata
HybridFlowBackendtrait for message-oriented hybrid transportsNeuromodulatorSnapshotfor typed neuromodulator ingress/readout payloadsWireCompatibilityenvelope (decode_ipc_message_json) for fail-closed schema versions
Feature flags
The default dependency graph is wire models plus RustBackend. HTTP and ZeroMQ
are opt-in so a consumer of IpcMessage / StimulusBatch does not compile or
link those stacks.
| Feature | Default | What it enables |
|---|---|---|
| (none) | yes | Wire models (IpcMessage, batches, snapshots) and RustBackend |
zmq |
no | ZmqIpcBackend (vendored libzmq via zmq-sys; needs a C++ compiler). Send + Sync via mutex-serialized SUB socket ownership; libzmq sockets themselves are Send + !Sync. |
server |
no | corpus_ipc_server Axum REST binary (axum + minimized tokio) |
tower is not a direct crate dependency. Axum 0.7 depends on it unconditionally,
so it appears only when the optional server feature enables Axum. serde_json
is a library dependency so the compatibility envelope can inspect wire_version
before deserializing a payload. The server binary uses Axum's Json extractor
(the json feature), which also depends on serde_json.
ZMQ backend concurrency
ZmqIpcBackend is Send + Sync because IpcBackend requires both. libzmq
sockets are not safe to share (zmq(7) Thread safety; zmq 0.10's
Socket is Send + !Sync). This crate does not unsafe impl Sync on the
socket. The SUB socket is created, subscribed, and connected on the
initializing thread (initialize takes &mut self) before it is stored in a
Mutex. Non-blocking receive and reset's close path take that lock; dropping
the backend closes the socket through exclusive ownership of the struct.
Moving the backend to another thread is supported. process_batch still takes
&mut self; concurrent process calls need an outer lock, which is how
corpus_ipc_server uses Arc<Mutex<Box<dyn IpcBackend>>>.
Installation
[]
= "0.1"
# Optional ZMQ backend support
# corpus-ipc = { version = "0.1", features = ["zmq"] }
Development / unreleased-main option (tracks main, not a registry release):
[]
= { = "https://github.com/Limen-Neural/corpus-ipc" }
Run the REST service from this repo (not pulled in by a library dependency):
# RustBackend only
CORPUS_IPC_BIND=127.0.0.1:8080
# With ZMQ backend selectable via CORPUS_IPC_BACKEND_TYPE=zmq
CORPUS_IPC_BIND=127.0.0.1:8080
Quick Start
use ;
use BackendFactory;
let mut backend = create;
backend.initialize?;
let inputs = ;
let outputs = backend.process_batch?;
println!;
# Ok::
Protocol Ownership
corpus-ipc is the owner of serialized network schemas for hybrid flow messaging.
Use these re-exports directly from crate root:
use ;
SpikeBatch / TraceBatch are IPC transport types
These names are wire payloads, not the training-side types in
SynapticDistill.jl
(src/types.jl).
| Crate | Domain | SpikeBatch |
TraceBatch |
|---|---|---|---|
corpus-ipc |
IPC transport | session/batch id + SpikeEvent list |
session/batch id + TraceData rows |
SynapticDistill.jl |
SNN training | spike trains + optional times / targets |
unstructured e-prop traces |
The Rust type names stay SpikeBatch / TraceBatch so serde identifiers
(IpcMessage::Spikes, IpcMessage::EligibilityTraces) and existing imports
remain compatible. When the collision would be confusing, use the aliases
IpcSpikeBatch and IpcTraceBatch — they are the same types and the same
wire format.
Stimulus and neuromodulator ingress
corpus-ipc is the schema owner for the stimulus/neuromodulator leg of the
sensory pipeline. The intended flow is:
thalamic-relay -> corpus-ipc -> brainstem-daemon
sensory/safety wire/schema SNN runtime
thalamic-relay and brainstem-daemon encode/decode through
IpcMessage::Stimuli(StimulusBatch) and
IpcMessage::Neuromodulators(NeuromodulatorSnapshot) instead of bespoke UDP
JSON or a private packet struct. StimulusBatch is domain-neutral: its
values width is not fixed by this crate (do not encode any one network's
axon/channel count here), and an optional valid_mask lets a channel be
marked invalid/missing for a tick instead of silently reading as 0.0. See
the StimulusBatch doc comments for the exact semantics.
Wire compatibility envelope
Crate semver does not define on-wire acceptance. WireCompatibility is the
source of truth for the current and minimum supported wire versions
(currently both 1). Decode hybrid-flow JSON through
decode_ipc_message_json so too-old and too-new envelopes return typed
errors before the payload is used. Unversioned tagged IpcMessage JSON
(the pre-release git encoding), including JSON-string unit variants such as
"Ping", is still accepted as legacy wire version 1.
Current encoding rules:
- Unknown fields on structs and on the envelope object are ignored, so additive optional fields can be skipped by older readers.
- Unknown
IpcMessagevariants fail to deserialize. They never become a valid default (IpcMessagehas noDefaultand no serdeothercatch-all).
Bump WireCompatibility::CURRENT when the on-wire schema changes in a way
existing decoders cannot ignore. See CHANGELOG.md for the full bump rules,
including when to raise MIN_SUPPORTED. The compiled example lives on
decode_ipc_message_json.
Crate Exports
- Backends and traits:
IpcBackend,HybridFlowBackendBackendType(Rust,ZmqIpc; deprecatedZmqRuntimestill selects ZMQ)RustBackendZmqIpcBackend(whenzmqfeature enabled; mutex-serialized socket ownership)- Deprecated compatibility aliases:
RuntimeBackend,ZmqRuntimeBackend
- Models:
IpcMessageand all batch/config/trace/gradient payload structsIpcSpikeBatch/IpcTraceBatchaliases for the IPC wire batchesStimulusBatch,NeuromodulatorSnapshotValidationError,ValidationKind,ProtocolLimits,Validate
- Wire compatibility:
WireCompatibility,classify_wire_version,accept_wire_versionWireEnvelope,decode_ipc_message_json,encode_ipc_message_jsonCompatibility,CompatibilityError,EnvelopeError
Repository
Canonical GitHub home: Limen-Neural/corpus-ipc.
rmems/corpus-ipc redirects here.
The GitHub wiki is enabled
and is the extra-docs home (architecture, backends, REST server, ecosystem).
In-tree docs/ is a pointer only — not a second documentation site.
Links to SynapticDistill.jl
stay on rmems; that sibling has not transferred.
License
Dual-licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE-2.0 or http://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.