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