Driver SDK
Concept
A SutureDriver translates between file formats (OTIO, XLSX, DOCX) and Suture's internal patch model. Each driver is responsible for:
- Parsing a file format into a structured intermediate representation
- Computing touch sets — determining which elements are affected by edits
- Serializing patches — encoding the operation payload for storage
- Visual diff — producing human-readable diffs between two file versions
Drivers do not manage repository state; they only translate between format- specific representations and Suture's patch algebra.
Reference Drivers
OTIO
The suture-driver-otio crate demonstrates the driver pattern for OpenTimelineIO (.otio) files.
Properties (Example)
The suture-driver-example crate provides a minimal, self-contained example of implementing the SutureDriver trait for Java .properties files. It covers parsing, semantic diffing, and three-way merge — making it the recommended starting point for anyone writing a custom driver.
Parsing
use suture_driver_otio::OtioDriver;
let mut driver = OtioDriver::new();
driver.parse_otio(&otio_json)?;
for elem in driver.elements() {
println!("[{}] {} ({})", elem.element_type(), elem.name(), elem.id());
}
Computing Touch Sets
When a user edits a timeline, the driver computes which timeline elements are affected:
use suture_driver_otio::{OtioDriver, ChangeDescription};
let mut driver = OtioDriver::new();
driver.parse_otio(&otio_json)?;
let changes = vec![ChangeDescription {
element_id: "timeline/track".to_string(),
field_path: "name".to_string(),
old_value: Some("Video".to_string()),
new_value: Some("Audio".to_string()),
}];
let touch_set = driver.compute_touch_set(&changes);
// Returns affected element IDs, cascading to children
Visual Diff
let diff = driver.serialize_diff(&old_json, &new_json)?;
println!("{}", diff);
Implementing a Custom Driver
See crates/suture-driver-example/ for a minimal working driver. The general steps are:
- Create a new crate:
crates/suture-driver-<format>/ - Depend on
suture-driverand implement theSutureDrivertrait - Implement
diff()to produceSemanticChangevalues between two file versions - Implement
format_diff()for human-readable output - Implement
merge()for three-way semantic merge (returnNoneon conflict) - Return supported extensions from
supported_extensions()
Element ID Convention
Use slash-delimited paths that reflect the document hierarchy:
timeline/track/clip, timeline/stackworkbook/sheet/rows/3/cols/Adoc/body/paragraphs/5/runs/2Commutativity
Two patches commute when their touch sets are disjoint. For OTIO, editing clip A and clip B commute because they touch different elements. Editing the same clip twice does not commute.
This property is format-agnostic — the driver only needs to compute correct touch sets. Suture's patch algebra handles the rest.