icydb_core/patch/merge/
error.rs1use thiserror::Error as ThisError;
7
8#[derive(Clone, Debug, Eq, PartialEq, ThisError)]
15pub enum MergePatchError {
16 #[error("invalid patch shape: expected {expected}, found {actual}")]
17 InvalidShape {
18 expected: &'static str,
19 actual: &'static str,
20 },
21
22 #[error("invalid patch cardinality: expected {expected}, found {actual}")]
23 CardinalityViolation { expected: usize, actual: usize },
24
25 #[error("patch merge failed at {path}: {source}")]
26 Context {
27 path: String,
28 #[source]
29 source: Box<Self>,
30 },
31}
32
33impl MergePatchError {
34 #[must_use]
36 pub fn with_field(self, field: impl AsRef<str>) -> Self {
37 self.with_path_segment(field.as_ref())
38 }
39
40 #[must_use]
42 pub fn with_index(self, index: usize) -> Self {
43 self.with_path_segment(format!("[{index}]"))
44 }
45
46 #[must_use]
48 pub const fn path(&self) -> Option<&str> {
49 match self {
50 Self::Context { path, .. } => Some(path.as_str()),
51 _ => None,
52 }
53 }
54
55 #[must_use]
57 pub fn leaf(&self) -> &Self {
58 match self {
59 Self::Context { source, .. } => source.leaf(),
60 _ => self,
61 }
62 }
63
64 #[must_use]
65 fn with_path_segment(self, segment: impl Into<String>) -> Self {
66 let segment = segment.into();
67 match self {
68 Self::Context { path, source } => Self::Context {
69 path: Self::join_segments(segment.as_str(), path.as_str()),
70 source,
71 },
72 source => Self::Context {
73 path: segment,
74 source: Box::new(source),
75 },
76 }
77 }
78
79 #[must_use]
80 fn join_segments(prefix: &str, suffix: &str) -> String {
81 if suffix.starts_with('[') {
82 format!("{prefix}{suffix}")
83 } else {
84 format!("{prefix}.{suffix}")
85 }
86 }
87}