This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Robocodec is a common reader and writer library for robotics data formats (MCAP, ROS1 bag). It provides a unified, format-agnostic API that other projects can depend on for reading and writing robotics data files.
# Build
make build # Debug build
make build-release # Release build
make build-python-dev # Install Python package in dev mode
# Test
make test # Run Rust tests
cargo test test_name # Run specific test
# Code quality
make fmt # Format code
make lint # Run clippy (all features, denies warnings)
make check # Format + lint
make check-license # REUSE compliance check
# Coverage
make coverage # Generate coverage reports (requires cargo-llvm-cov)Important: Do NOT use --all-features or --features python when running tests. PyO3 conflicts with Rust test harness in some configurations.
Robocodec is a format-centric robotics data codec library with a layered architecture:
┌─────────────────────────────────────────────┐
│ Public API Layer (lib.rs re-exports) │
│ - RoboReader, RoboWriter, RoboRewriter │
│ - DecodedMessageIter, DecodedMessageResult │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ Unified I/O Layer │
│ - io/reader/mod.rs (RoboReader, iterators) │
│ - io/writer/mod.rs (RoboWriter) │
│ - io/traits.rs (FormatReader, FormatWriter) │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ Format-Specific Layer │
│ - io/formats/mcap/ (MCAP read/write) │
│ - io/formats/bag/ (ROS1 bag read/write) │
│ - io/formats/rrd/ (RRF2 read/write) │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ Transport & Streaming Layer (Internal) │
│ - io/transport/ (Transport trait) │
│ - io/streaming/ (StreamingParser trait) │
│ - LocalTransport, S3Transport, HttpTransport│
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ Foundation Layer │
│ - core/ (CodecError, Result) │
│ - encoding/ (CDR, Protobuf, JSON) │
│ - schema/ (msg, IDL parsing) │
│ - io/metadata.rs (unified types) │
└─────────────────────────────────────────────┘
-
Format-Centric: Each format (MCAP, ROS1 bag, RRD) lives in
src/io/formats/{format}/with its own readers and writers. -
Unified Public API: High-level
RoboReader,RoboWriterprovide a consistent interface across formats. Downcasting to format-specific types is intentionally not part of the public API. -
Transport Abstraction: Internal
Transporttrait enables reading from any data source (local files, S3, HTTP) with a single API. URL detection (s3://,https://) is handled automatically. -
Streaming Parser Pattern:
StreamingParsertrait provides chunk-based parsing for memory-efficient processing of large files from any transport. -
Simplified Iteration: Single-level iteration via
reader.decoded()returnsDecodedMessageIterdirectly. No need to call.stream()separately. -
Unified Result Types:
DecodedMessageResultcombines message data, channel info, and timestamps in a single type. -
Auto-Detection: Format is detected from file extension automatically.
src/io/reader/- Unified reader API (RoboReader, iterators, config)src/io/writer/- Unified writer API (RoboWriter, config)src/io/transport/- Transport layer (LocalTransport, S3Transport, HttpTransport, MemoryTransport)src/io/streaming/- Streaming parser trait and utilitiessrc/io/formats/mcap/- MCAP format (read/write, streaming)src/io/formats/bag/- ROS1 bag format (read/write, streaming)src/io/formats/rrd/- RRF2 format (read/write, streaming)src/io/metadata.rs- Unified types (ChannelInfo, RawMessage, DecodedMessageResult)src/io/traits.rs- FormatReader, FormatWriter traitssrc/encoding/- Message codecs (CDR, Protobuf, JSON)src/schema/- Schema parsers (ROS .msg, ROS2 IDL, OMG IDL)src/rewriter/- Format conversion with auto-detectionsrc/transform/- Topic/type transformationssrc/types/- Arena allocation, chunk managementtests/- Integration tests with fixtures intests/fixtures/
The library exports these key types at the top level:
-
RoboReader- Unified reader with format auto-detectionopen(path)- Open file with auto-detection (supports local paths,s3://,https://URLs)open_with_config(path, config)- Open with configurationdecoded()- Iterate over decoded messages with timestamps (returnsDecodedMessageIter)supports_parallel()- Check if parallel reading is availablechunk_count()- Get number of chunks for progress tracking
-
RoboWriter- Unified writer with format auto-detectioncreate(path)- Create writer based on extensioncreate_with_config(path, config)- Create with configuration- Inherits
FormatWritertrait methods (add_channel, write, finish)
-
DecodedMessageIter- Iterator yieldingDecodedMessageResult -
DecodedMessageResult- Combined message + metadatamessage- Decoded message fieldschannel- Channel informationlog_time,publish_time- Timestampssequence- Sequence number (if available)
RoboReader::open() supports URL-based sources:
- Local files:
/path/to/file.mcapor./relative/path.mcap - S3:
s3://bucket/path/file.mcap(with optional?endpoint=and?region=query params) - HTTP/HTTPS:
https://example.com/file.mcap(via HttpTransport)
Transport-based reading dispatches to format readers via FormatReader::open_from_transport.
-
RoboWriter- Unified writer with format auto-detectioncreate(path)- Create writer based on extensioncreate_with_config(path, config)- Create with configuration- Inherits
FormatWritertrait methods (add_channel, write, finish)
-
DecodedMessageIter- Iterator yieldingDecodedMessageResult -
DecodedMessageResult- Combined message + metadatamessage- Decoded message fieldschannel- Channel informationlog_time,publish_time- Timestampssequence- Sequence number (if available)
As a common library for other projects to use, these do NOT belong:
CLI tools - Should be in a separate(MOVED - CLI is now inrobocodec-clicraterobocodec-cli/)CLI dependencies -(MOVED - these are now inclap,indicatif,human-sizeshould be feature-gated or movedrobocodec-cli/)- Development examples - Files with hardcoded paths in
examples/ - Internal type exposure - Downcasting methods expose implementation details
This is a Cargo workspace with two members:
robocodec- The library crate (this directory)robocodec-cli/- The CLI tool crate (separate binary)
To build just the library:
cargo build --package robocodecTo build and install the CLI:
cargo install --path robocodec-cli
# or
cargo build --release --package robocodec-cli- Naming: Modules
snake_case, typesPascalCase, functionssnake_case - Errors: Use
CodecErrorandResult<T>type alias fromsrc/core/error.rs - Public API: All public items require rustdoc comments
- License: All source files must include SPDX license headers
As a staff Rust engineer, always follow these guidelines:
- Follow Rust API Guidelines
- Use
&strfor stable public APIs that accept both paths and URLs - Handle URL detection (
s3://) internally withinopen()/create()methods - Use builder patterns for complex configuration (
ReaderConfigBuilder,WriterConfigBuilder)
- Use
Result<T>and?operator properly - Avoid
.unwrap()in library code - use proper error propagation - Provide meaningful error messages with context
- Use
CodecErrorfromcore/error.rsfor consistency
- Prefer borrowing over cloning when possible
- Use
Cow<'_, str>for conditional ownership - Accept
impl AsRef<Path>for ergonomic APIs where appropriate - Minimize allocations in hot paths
- Use iterators (
map,filter,and_then) over imperative loops - Leverage
OptionandResultcombinators (?,map,unwrap_or) - Use
collect()to build collections from iterators
- Use the type system to prevent invalid states (newtypes, enums)
- Leverage
#[must_use]for important return values - Use
#[non_exhaustive]for enums that may grow
- Minimize
unsafecode - Document why
unsafeis necessary when used - Prefer safe abstractions over raw pointers
- All public items must have rustdoc with examples
- Include
# Examplesections showing typical usage - Document panics and errors in doc comments
- Write unit tests alongside code in
#[cfg(test)]modules - Use integration tests in
tests/for cross-module testing - Test both success and error paths
- Use descriptive test names (
test_round_trip_preserves_topics)
Always use public API in tests (RoboReader, RoboWriter):
- Tests should verify the library works through its public interface
- Never use format-specific types directly (e.g.,
BagFormat,McapFormat,RrdFormat) - This ensures the "chain of API" is tested - code changes that break the public API will fail tests
- Example:
RoboReader::open(path).expect("...")notBagFormat::open(path)
python- PyO3 Python bindingsjemalloc- Use jemalloc allocator (Linux only)s3- S3/HTTPS transport support (default enabled)- Enables
S3Transportfor reading from S3-compatible storage - Enables
HttpTransportfor reading from HTTP/HTTPS URLs - Requires tokio runtime for async operations
- Enables