Repository navigation
dbc: add semantic DBC round-tripping and database edits - #111
Conversation
Comments were dropped in #9 for lack of a consumer. A DBC written back out (for example, one embedded in an MF4 trace) now needs them, so Database, Node, Message and Signal carry CM_ text again. Comments on unknown objects and environment variables are reported as diagnostics; a repeated comment for one object replaces the earlier one, as cantools and canmatrix do, with a diagnostic. Quoted strings now unescape only \". cantools and canmatrix keep every other backslash literal, including \\, so "C:\temp" no longer becomes a tab.
Database.Write writes the resolved model as UTF-8 DBC text. Parsing the text gives a database equal to the original apart from Diagnostics and Source, including its derived lookups, frame formats and codecs; writing that again gives the same bytes. Records Parse dropped are not written, and formatting, number spelling and encoding are not kept. Write reads only exported fields, so an edited copy can be written and parsed into a new resolved database. Names that would not lex as one identifier, non-finite numbers, invalid UTF-8 and strings ending in a backslash are rejected before anything is written. Windows-1252 output is available by wrapping the writer with golang.org/x/text's charmap encoder. Choices made for interoperability: - Enum BA_ values are written as indexes (cantools rejects labels there); enum defaults use the label unless a repeated label would resolve to another index. - Numbers use the shortest exact form, with an exponent only where Python's repr uses one. - Multiplexing stays in simple mN form when it means "one root, one value", and otherwise lists every condition in SG_MUL_VAL_. Checked once by hand: cantools 45.1.2 and canmatrix load the written text of every fixture and of the GIC3 interface DBCs (25 and 400 messages) to the same messages, signals, choices, comments and attributes as the originals.
A parsed Database is read-only: its lookups and codecs are built by Parse, so changing Message.ID or a name in place leaves them stale, and Source still returns the original text. Edit hands a callback an independent copy, then writes and parses the result. The returned database is validated like any parsed one: colliding or out-of-range identifiers and unwritable names are errors. Its lookups follow the edits, and Source is the DBC text that describes it, ready to embed in a trace. The original is never touched. This covers deriving a per-device database from a single-device interface DBC (shifting identifier bits and renaming messages) and expanding one DBC to every device, as the GIC3 release tooling does with cantools. The test drives both through a synthetic device fixture, encodes frames on the derived IDs, and writes a Windows-1252 file that ParseFile reads back.
Keep numeric enum -1 values distinct from empty labels, including defaults. Validate resolved CAN identifiers before adding the extended DBC marker, so invalid edits cannot change frame identity. Document frame format as derived from DBC attributes and exercise a CAN FD attribute edit through encoding and generated-source reparsing.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHub8000 Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Pre-merge checks complete for HEAD |
Why
Device-specific DBCs need identifier and name edits without stale lookups, codecs or source attachments. Add generic DBC writing and validated database derivation so the resulting database can also be embedded in a trace.
What changed
Database.Editto derive an independent, reparsed database. Reject out-of-range identifiers before serialization and preserve numeric enum-1values, including defaults with an empty choice label.Scope
Round-trips preserve supported model semantics. Source formatting, original encoding and records already dropped by parsing are not preserved. Windows-1252 output uses the existing charmap encoder; no dependencies are added.
Decisions
Message.Formatremains derived from DBC declarations, includingVFrameFormatandProtocolType. The API documentation explains editing those declarations, and the device lifecycle test verifies a CAN FD edit through encoding and generated-source reparsing.Risks
String parsing changes for existing callers that relied on C-style escapes: backslash-n, backslash-r, backslash-t and doubled backslashes now remain literal.
Verification
go test -race ./...andgo vet ./...passed;gofmt -l .and diff checks were clean.