dbc-rs 0.1.0-rc.3

Database CAN (DBC) parsing and editing library
Documentation

dbc-rs

A clean, zero-dependency DBC (CAN Database) file parser and editor for Rust.

Crates.io Documentation License MSRV CI

Features

  • Zero dependencies with alloc/std features (optional heapless for embedded)
  • no_std support - Works on embedded targets
  • Full editing & writing - Modify and save DBC files
  • Well tested - Tested with real-world DBC files

Quick Start

use dbc_rs::Dbc;
let content = std::fs::read_to_string("example.dbc").unwrap();
let dbc = Dbc::parse(&content).expect("invalid dbc");

if let Some(engine_msg) = dbc.messages().iter().find(|m| m.id() == 256) {
    if let Some(rpm) = engine_msg.signals().iter().find(|s| s.name() == "RPM") {
        println!("RPM factor: {}", rpm.factor());
    }
}

Feature Flags

⚠️ Important: You MUST enable either alloc OR heapless (or use std which includes alloc).

Feature Default Description
alloc Heap-allocated collections via alloc crate. Requires global allocator. Zero dependencies.
heapless Stack-allocated, bounded collections (no allocator). One dependency: heapless.
std Includes alloc + std library (builders, I/O, formatting). Zero dependencies.

Examples:

# Default: std enabled
dbc-rs = "1"

# no_std with heap allocation
dbc-rs = { version = "1", default-features = false, features = ["alloc"] }

# no_std with stack allocation
dbc-rs = { version = "1", default-features = false, features = ["heapless"] }

DBC Format Support

Core Features ✅

  • Version (VERSION), Nodes (BU_), Messages (BO_), Signals (SG_), Value Descriptions (VAL_)
  • All signal features: start bit, length, byte order, sign, factor, offset, min/max, unit, receivers
  • 29-bit Extended CAN IDs (2048-536870911)

Limitations ❌

Not implemented: Value tables (VAL_TABLE_), structured comments (CM_), attributes (BA_*), signal groups, environment variables (EV_), signal multiplexing.

Note: NS_ and BS_ are parsed but ignored. Single-line // comments are parsed but not preserved on save.

Examples

Basic Parsing

use dbc_rs::Dbc;

let dbc = Dbc::parse(&content)?;
println!("Messages: {}", dbc.messages().len());

Creating DBC Files

use dbc_rs::{DbcBuilder, VersionBuilder, NodesBuilder, MessageBuilder, SignalBuilder, ByteOrder};

let version = VersionBuilder::new().version("1.0").build()?;
let nodes = NodesBuilder::new().add_node("ECM").build()?;

let signal = SignalBuilder::new()
    .name("EngineSpeed")
    .start_bit(0)
    .length(16)
    .byte_order(ByteOrder::BigEndian)
    .factor(0.25)
    .unit("rpm")
    .build()?;

let message = MessageBuilder::new()
    .id(256)
    .name("EngineData")
    .dlc(8)
    .sender("ECM")
    .add_signal(signal)
    .build()?;

let dbc = DbcBuilder::new()
    .version(version)
    .nodes(nodes)
    .add_message(message)
    .build()?;

let dbc_string = dbc.to_dbc_string();

Error Handling

use dbc_rs::{Dbc, Error};

match Dbc::parse(invalid_content) {
    Ok(dbc) => println!("Parsed: {} messages", dbc.messages().len()),
    Err(Error::Expected(msg)) => eprintln!("Expected {}", msg),
    Err(Error::UnexpectedEof) => eprintln!("Unexpected end of input"),
    Err(Error::Validation(msg)) => eprintln!("Validation error: {}", msg),
    Err(e) => eprintln!("Error: {}", e),
}

Security & Limits

Capacity limits prevent resource exhaustion (DoS protection). Defaults accommodate typical DBC files. Limits are configurable at build time:

Environment Variable Default Description
DBC_MAX_MESSAGES 8192 Maximum number of messages per DBC file (must be power of 2 for heapless)
DBC_MAX_SIGNALS_PER_MESSAGE 64 Maximum number of signals per message
DBC_MAX_NODES 256 Maximum number of nodes in the bus
DBC_MAX_VALUE_DESCRIPTIONS 64 Maximum number of value descriptions
DBC_MAX_NAME_SIZE 64 Maximum length of names (messages, signals, nodes, etc.)

Example:

# Reduce capacity limits for embedded targets (recommended for heapless)
DBC_MAX_MESSAGES=512 cargo build --release --verbose --no-default-features --features heapless --target thumbv7em-none-eabihf -p dbc-rs

Performance Notes:

  • alloc/std: Heap-allocated, dynamic sizing
  • heapless: Stack-allocated, fixed-size arrays (default 8192 messages; reduce to 256-512 for embedded targets. All values must be powers of 2.)
  • Parsing: O(n) complexity, entire file parsed into memory

Troubleshooting

  • "Message ID out of valid range": Standard 11-bit (0-0x7FF) or Extended 29-bit (0x800-0x1FFFFFFF)
  • "Signal extends beyond message": Ensure start_bit + length <= DLC * 8
  • "Signal overlap": Signals must not occupy overlapping bit ranges
  • "Sender not in nodes": Add message sender to nodes list
  • "Duplicate message ID": Use unique CAN IDs

Design

  • Immutability: All data structures are immutable after creation
  • Validation: Input validation at construction time
  • no_std First: Designed for no_std, optional std feature
  • Zero Dependencies: No dependencies with alloc/std features
  • Result-based errors: All fallible operations return Result<T>

Contributing

Contributions welcome! Areas needing work: Value tables, structured comments, attributes, environment variables, signal multiplexing.

License

Available under MIT OR Apache-2.0 (open source) or commercial licensing. See LICENSING.md for details.

References