#![allow(clippy::collapsible_match)]
pub mod cache;
pub mod error;
pub mod interner;
pub mod plugin;
pub mod registry;
pub mod strategy;
pub mod structured_merge;
pub mod types;
pub use cache::MergeCache;
pub use error::DriverError;
pub use interner::KeyInterner;
pub use plugin::{BuiltinDriverPlugin, DriverPlugin, PluginError, PluginRegistry};
pub use registry::DriverRegistry;
pub use strategy::{optimal_merge_strategy, MergeStrategy};
pub use types::{DiffHunk, DiffHunkType, DiffSummary, VisualDiff};
pub trait SutureDriver: Send + Sync {
fn name(&self) -> &str;
fn supported_extensions(&self) -> &[&str];
fn diff(
&self,
base_content: Option<&str>,
new_content: &str,
) -> Result<Vec<SemanticChange>, DriverError>;
fn format_diff(
&self,
base_content: Option<&str>,
new_content: &str,
) -> Result<String, DriverError>;
fn merge(
&self,
_base: &str,
_ours: &str,
_theirs: &str,
) -> Result<Option<String>, DriverError> {
Ok(None)
}
fn merge_raw(
&self,
base: &[u8],
ours: &[u8],
theirs: &[u8],
) -> Result<Option<Vec<u8>>, DriverError> {
let base_str = String::from_utf8_lossy(base);
let ours_str = String::from_utf8_lossy(ours);
let theirs_str = String::from_utf8_lossy(theirs);
match self.merge(&base_str, &ours_str, &theirs_str)? {
Some(s) => Ok(Some(s.into_bytes())),
None => Ok(None),
}
}
fn diff_raw(
&self,
base: Option<&[u8]>,
new_content: &[u8],
) -> Result<Vec<SemanticChange>, DriverError> {
let base_str = base.map(|b| String::from_utf8_lossy(b));
let new_str = String::from_utf8_lossy(new_content);
self.diff(base_str.as_deref(), &new_str)
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum SemanticChange {
Added { path: String, value: String },
Removed { path: String, old_value: String },
Modified {
path: String,
old_value: String,
new_value: String,
},
Moved {
old_path: String,
new_path: String,
value: String,
},
}