1use chrono::{DateTime, Utc};
2use faultline_core::{ChangeEvent, DatasetSnapshot};
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
7pub struct DiffRequest {
8 pub left: String,
9 pub right: String,
10 pub layer: Option<String>,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
14pub struct DiffSummary {
15 pub diff_id: Uuid,
16 pub added: u64,
17 pub removed: u64,
18 pub changed: u64,
19}
20
21impl DiffSummary {
22 pub fn empty() -> Self {
23 Self {
24 diff_id: Uuid::new_v4(),
25 added: 0,
26 removed: 0,
27 changed: 0,
28 }
29 }
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
33pub enum DiffClassification {
34 Deterministic,
35 NoChanges,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
39pub struct SnapshotState {
40 pub snapshot: DatasetSnapshot,
41 pub features: Vec<faultline_core::FeatureRef>,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
45pub struct DiffArtifact {
46 pub artifact_id: Uuid,
47 pub generated_at: DateTime<Utc>,
48 pub classification: DiffClassification,
49 pub left_snapshot_id: Uuid,
50 pub right_snapshot_id: Uuid,
51 pub summary: DiffSummary,
52 pub change_events: Vec<ChangeEvent>,
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn summary_empty_starts_at_zero() {
61 let summary = DiffSummary::empty();
62
63 assert_eq!(summary.added, 0);
64 assert_eq!(summary.removed, 0);
65 assert_eq!(summary.changed, 0);
66 }
67
68 #[test]
69 fn diff_artifact_round_trip_serialization() {
70 let snapshot = DatasetSnapshot::new("roads");
71 let summary = DiffSummary::empty();
72 let artifact = DiffArtifact {
73 artifact_id: Uuid::new_v4(),
74 generated_at: Utc::now(),
75 classification: DiffClassification::NoChanges,
76 left_snapshot_id: snapshot.snapshot_id,
77 right_snapshot_id: snapshot.snapshot_id,
78 summary,
79 change_events: Vec::new(),
80 };
81
82 let json = serde_json::to_string(&artifact).expect("serialize artifact");
83 let restored: DiffArtifact = serde_json::from_str(&json).expect("deserialize artifact");
84
85 assert_eq!(restored.classification, DiffClassification::NoChanges);
86 assert!(restored.change_events.is_empty());
87 }
88}