dbc
A clean, zero-dependency DBC (CAN Database) file parser and editor for Rust.
Minimum Supported Rust Version (MSRV)
The minimum supported Rust version is 1.85.0. The crate is tested against this version and may use features available in it or later.
Features
- ✅ Zero dependencies - Pure Rust implementation
- ✅ no_std + alloc support - Works on embedded targets without the standard library
- ✅ Full editing & writing - Modify and save DBC files with the same structs
- ✅ Feature flag control - Optional
stdfeature for desktop conveniences - ✅ Well tested - Tested with real-world DBC files
Quick Start
use Dbc;
// Parse a DBC file
let content = read_to_string.unwrap;
let dbc = parse.expect;
// Access messages and signals (read-only)
if let Some = dbc.messages.iter.find
Feature Flags
The crate is #![no_std] + alloc friendly. The following features are available:
| Feature | Default | Description |
|---|---|---|
std |
✅ | Enables standard library integration (I/O helpers, tests). Disable it for pure no_std builds. |
Example (no_std build):
[]
= { = "1", = false }
Internationalization (i18n)
Error messages can be localized at build time using feature flags. The language is selected during compilation and cannot be changed at runtime.
Supported Languages
| Language | Feature Flag | Code |
|---|---|---|
| English (default) | (none) | en |
| French | lang-fr |
fr |
| Spanish | lang-es |
es |
| German | lang-de |
de |
| Japanese | lang-ja |
ja |
Example:
[]
= { = "1", = ["lang-fr"] }
Note: Language features are mutually exclusive. If multiple language features are enabled, the last one in the feature list will be used.
⚠️ Warning: Translations have been generated and may contain errors. They have not been fully verified by native speakers. Contributions to improve translations are welcome! See Contributing section.
DBC Format Feature Support
Core Features ✅
| Feature | Statement | Parse | Write | Notes |
|---|---|---|---|---|
| Version | VERSION |
✅ | ✅ | Database version string |
| New Symbols | NS_ |
⚠️ | ❌ | Parsed but ignored |
| Bit Timing | BS_ |
⚠️ | ❌ | Parsed but ignored |
| Bus Nodes | BU_ |
✅ | ✅ | List of ECUs on the bus |
| Messages | BO_ |
✅ | ✅ | CAN message definitions |
| Signals | SG_ |
✅ | ✅ | Signal definitions |
| Comments | // |
✅ | ❌ | Single-line comments parsed but not preserved |
Signal Features ✅
All signal features are fully supported: name, start bit, length, byte order (@0/@1), sign (+/-), factor, offset, min/max values, unit, and receivers (Broadcast *, specific nodes, or None).
Extended Features ❌
Not yet implemented: Value tables (VAL_TABLE_, VAL_), structured comments (CM_), attributes (BA_DEF_, BA_DEF_DEF_, BA_), signal groups (SIG_GROUP_), environment variables (EV_), signal multiplexing, and advanced node relationships.
Advanced Features
| Feature | Parse | Write | Notes |
|---|---|---|---|
| 29-bit Extended CAN IDs | ✅ | ✅ | Validated (range: 2048-536870911) |
| Signal multiplexing | ❌ | ❌ |
Example DBC File
VERSION "1.0"
BU_: ECM TCM
BO_ 256 EngineData : 8 ECM
SG_ RPM : 0|16@0+ (0.25,0) [0|8000] "rpm"
SG_ Temperature : 16|8@0- (1,-40) [-40|215] "°C"
BO_ 512 BrakeData : 4 TCM
SG_ Pressure : 0|16@1+ (0.1,0) [0|1000] "bar"
Examples
Basic Parsing
use Dbc;
let dbc = parse?;
// Note: to_string() requires alloc feature
println!;
Finding Messages and Signals
use Dbc;
let dbc = parse?;
// Find message by ID
if let Some = dbc.messages.iter.find
Creating and Modifying DBC Files
use ;
// Create from scratch
let version = builder.major.minor.build?;
let nodes = builder.add_node.add_node.build;
let signal = builder
.name
.start_bit
.length
.byte_order
.unsigned
.factor
.offset
.min
.max
.unit
.receivers
.build?;
let message = builder
.id
.name
.dlc
.sender
.add_signal
.build?;
let dbc = builder
.version
.nodes
.add_message
.build?;
// Save to string
let dbc_string = dbc.to_dbc_string;
Parsing with Options
use ;
// Use lenient mode to allow signals that extend beyond message boundaries
// This is useful for parsing real-world DBC files that may have technically
// invalid but commonly used signal definitions
let options = lenient;
let dbc = parse_with_options?;
Modifying Existing DBC
use ;
let dbc = parse?;
// Extract current data
let version = dbc.version;
let nodes = dbc.nodes;
let mut messages: = dbc.messages.iter.cloned.collect;
// Add new message
let new_signal = builder
.name
.start_bit
.length
.byte_order
.unsigned
.factor
.offset
.min
.max
.receivers
.build?;
let new_message = builder
.id
.name
.dlc
.sender
.add_signal
.build?;
messages.push;
// Create modified DBC
let modified_dbc = builder
.version
.nodes
.messages
.build?;
no_std Usage (Parsing Only)
use Dbc;
// Parse from bytes (no file I/O needed)
let dbc_bytes = b"VERSION \"1.0\"\n\nBU_: ECM\n\nBO_ 256 Engine : 8 ECM\n SG_ RPM : 0|16@1+ (0.25,0) [0|8000] \"rpm\"";
let dbc = parse_bytes?;
// Access data (read-only)
let version = dbc.version;
let messages = dbc.messages;
// Note: to_dbc_string() requires alloc feature
// #[cfg(feature = "alloc")]
// let saved = dbc.to_dbc_string();
alloc Usage (With Builders)
use ;
// Parse existing DBC
let dbc = parse?;
// Create new message with builder
let signal = new
.name
.start_bit
.length
.byte_order
.unsigned
.factor
.offset
.min
.max
.unit
.receivers
.build?;
let message = new
.id
.name
.dlc
.sender
.add_signal
.build?;
// Format to string
let dbc_string = dbc.to_dbc_string;
std Usage (With File I/O)
use Dbc;
// Read from file
let dbc = from_file?;
// Or read from any std::io::Read source
let file = open?;
let dbc = from_reader?;
// All alloc features available
let dbc_string = dbc.to_dbc_string;
write?;
Error Handling
use ;
match parse
Security & Resource Limits
For security reasons (DoS protection), the library enforces the following limits:
- Maximum 256 nodes per DBC file
- Maximum 64 receiver nodes per signal
- Maximum 10,000 messages per DBC file
- Maximum 64 signals per message
- Maximum 256 characters for unit strings
Attempting to exceed these limits will result in a validation error. These limits accommodate typical DBC file sizes (typically < 1000 messages and < 10 nodes).
For a comprehensive security audit, see SECURITY_AUDIT.md.
Limitations
- Extended Features: Many advanced DBC features (attributes, value tables, structured comments, etc.) are not yet supported. Files containing these features will parse successfully but the extended data will be lost on save.
- Comments: Single-line
//comments are parsed but not preserved when saving. - Signal Multiplexing: Multiplexed signals are not yet supported.
- Feature Restrictions:
- Without
alloc: Cannot create/modify DBC files (builders unavailable) - Without
std: Cannot read from filesystem (useparse()orparse_bytes()instead)
- Without
Troubleshooting
Common Issues
"Message ID out of valid range"
- Standard 11-bit IDs: Use 0-0x7FF (0-2047)
- Extended 29-bit IDs: Use 0x800-0x1FFFFFFF (2048-536870911)
"Signal extends beyond CAN message"
- Ensure
start_bit + length <= DLC * 8
"Signal overlap detected"
- Ensure signals don't occupy overlapping bit ranges
"Sender not in nodes"
- Add the message sender to the nodes list
"Duplicate message ID"
- Use unique CAN IDs for each message
Architecture & Design
Design Principles
- Immutability: All data structures are immutable after creation
- Validation: Input validation occurs at construction time
- no_std First: Designed for
no_stdenvironments, with optionalallocandstdfeatures - Zero Dependencies: No external dependencies
- Memory Efficiency: Uses fixed arrays in
no_std,Box<[T]>withalloc
Error Handling
- Result-based: All fallible operations return
Result<T> - Categorized errors:
Error::Signal,Error::Message,Error::Dbc,Error::Version,Error::Nodes,Error::InvalidData - Internationalized: Error messages can be localized at build time
- Feature-dependent: With
alloc, errors include detailedStringmessages; without it, static&'static strmessages
Performance Notes
- Memory Usage:
no_std: Fixed-size arrays (stack-allocated)alloc:Box<[T]>(heap-allocated, dynamic sizing)
- Parsing: O(n) complexity, entire file parsed into memory
- Recommendations: For very large DBC files (>10MB), consider splitting into multiple files
Contributing
Contributions are welcome! Areas that need work:
- Value tables and enumerations (VAL_TABLE_, VAL_)
- Structured comments (CM_)
- Attributes (BA_DEF_, BA_, etc.)
- Environment variables (EV_)
- Signal multiplexing support
- Translation improvements - Help verify and improve error message translations
Adding a New Language
- Create a new file in
src/error/lang/(e.g.,it.rsfor Italian) - Copy the structure from
en.rsand translate all constants - Add the language module to
src/error/lang/mod.rs:use it as lang; - Add the feature flag to
Cargo.toml:lang-it = [] - Update this README with the new language
- Submit a pull request
Translation Guidelines:
- Maintain the same constant names across all language files
- Keep format placeholders (
{}) in the same positions - Ensure technical terms are accurately translated
License
dbc-rs is available under a dual-licensing model:
- Open Source: MIT OR Apache-2.0 (default) - See LICENSING.md for details
- Commercial: Available for proprietary use - See LICENSING.md for terms
For most users, the open-source license (MIT OR Apache-2.0) is sufficient.
References
- DBC Format Specification - Detailed format documentation
- Security Audit - Comprehensive security review
- Vector Informatik: "DBC File Format Documentation Version 01/2007"
- CAN Specification (ISO 11898)
Test DBC Files
The test suite includes several DBC files in tests/data/:
complete.dbc- Comprehensive test file with multiple messages and signalssimple.dbc- Basic 2-message filemultiplexed.dbc- Tests multiple sensors and actuatorsminimal.dbc- Minimal valid DBC fileextended_ids.dbc- Tests higher message IDsbroadcast_signals.dbc- Tests broadcast receivers
For additional DBC files, consider:
- commaai/opendbc - Open-source collection of DBC files
- CSS Electronics DBC Editor - Sample DBC files