Cap’n Proto RPC serving

Overview

readcon-core provides an optional Cap’n Proto RPC interface (behind the rpc feature flag) that allows any language with a Cap’n Proto implementation to request frame parsing and writing over the network.

Schema

The schema defines a ReadConService interface with two methods:

parseFrames

Accepts raw file bytes, returns parsed frame data.

writeFrames

Accepts structured frame data, returns serialized file bytes.

The schema file is at schema/ReadCon.capnp.

**CON v3 field parity** (wire shape of a parsed ConFrame, not an on-disk bcon file):

Cap’n Proto

Maps to

ConAtom.fixedMask (u8, 0–7)

per-axis constraints (encode_fixed_bitmask)

ConAtom velocity / force / energy / charge / spin / magmom / displacement / spread

AtomDatum optional sections

ConFrameData.specVersion

FrameHeader.spec_version (default 2)

hasForces / hasEnergies / hasCharges / hasSpins / hasMagmoms / hasDisplacements / hasSpreads

section presence

massesPerType / natmsPerType

type table

sections

declared section names

metadataJson

free-form + reserved JSON keys (units, energy, NEB, …)

strictValidation / sectionsDeclared

parse policy flags

Round-trip helpers live in src/rpc/convert.rs (fill_frame_builder / frame_from_reader). Text .con remains the on-disk interchange authority.

Breaking note: pre-v3 wire used a single isFixed: Bool and velocity-only atoms. Clients must regenerate from the current schema (0.x RPC surface).

Building

# Requires capnproto installed (via pixi or system package)
cargo build --features rpc

# Or via pixi (capnproto is a dependency)
pixi r build-rpc

Server

// Start a TCP RPC server
#[tokio::main]
async fn main() {
    readcon_core::rpc::server::start_server("127.0.0.1:9876")
        .await
        .unwrap();
}

Client

use readcon_core::rpc::client::RpcClient;
use std::path::Path;

let client = RpcClient::new("127.0.0.1:9876").unwrap();
let frames = client.parse_file(Path::new("input.con")).unwrap();
let output = client.write_frames(&frames).unwrap();

Protocol

The RPC uses Cap’n Proto two-party as the encoding. The byte pipe is not UCX, libfabric, Mercury, or ADIOS.

Spec

Pipe

host:port or [ipv6]:port

TCP

unix:/abs/path, unix:///abs/path, or /abs/path

Unix domain socket

Same-node HPC jobs should use a Unix socket (no TCP loopback). TCP is for inet. UCX/ADIOS/DAOS are optional later adapters if a campaign consumer exists; they are not this crate and they are not the CON store. Corpus I/O decisions live in the readcon-db 2026-08-23 exascale I/O literature note (ADIOS2/DAOS/SST move GB-class arrays; they do not replace a FrameKey mmap of CON).

The MD-engine leaf is pack-then-Bcast on the caller comm. Encode a parsed frame with readcon_core::rcso::Rcso::encode_frame (magic RCSO, v1, same bytes as readcon-db cooked SoA). Many frames go in one RCSB envelope. This crate never calls MPI_Init.

readcon_core::rpc::server::start_server("unix:/tmp/readcon.sock")
let client = RpcClient::new("unix:/tmp/readcon.sock").unwrap();