use serde::{Deserialize, Serialize};
use crate::render::TokenSpan;
use crate::traits::core::PluginResult;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiffRequest {
pub old_content: Option<String>,
pub new_content: Option<String>,
pub language: Option<String>,
pub view: DiffView,
pub max_lines: usize,
pub word_diff: bool,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum DiffView {
Unified,
Split,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiffResponse {
pub lines: Vec<DiffLine>,
pub truncated: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiffLine {
pub kind: DiffLineKind,
pub old_lineno: Option<u32>,
pub new_lineno: Option<u32>,
pub spans: Vec<TokenSpan>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum DiffLineKind {
Context,
Added,
Removed,
Modified,
HunkHeader,
}
pub trait DiffRenderer {
fn provider_name(&self) -> &str;
fn supported_languages(&self) -> Vec<String>;
fn render(&mut self, request: &DiffRequest) -> PluginResult<DiffResponse>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn diff_view_round_trips_through_serde() {
let s = serde_json::to_string(&DiffView::Split).unwrap();
assert_eq!(s, "\"split\"");
let v: DiffView = serde_json::from_str("\"unified\"").unwrap();
assert_eq!(v, DiffView::Unified);
}
#[test]
fn diff_line_kind_round_trips_through_serde() {
let s = serde_json::to_string(&DiffLineKind::HunkHeader).unwrap();
assert_eq!(s, "\"hunk_header\"");
}
#[test]
fn diff_response_serializes_empty() {
let resp = DiffResponse { lines: vec![], truncated: false };
let s = serde_json::to_string(&resp).unwrap();
assert!(s.contains("\"lines\":[]"));
assert!(s.contains("\"truncated\":false"));
}
}