Skip to main content

json_schema_rs/code_gen/
error.rs

1//! Errors that can occur during code generation.
2
3use std::fmt;
4
5/// Result type for code generation operations.
6pub type CodeGenResult<T> = Result<T, CodeGenError>;
7
8/// Errors that can occur during code generation.
9#[derive(Debug)]
10pub enum CodeGenError {
11    /// Root schema is not an object with properties.
12    RootNotObject,
13    /// I/O error while writing output.
14    Io(std::io::Error),
15    /// One schema in a batch failed; index is the 0-based schema index.
16    Batch {
17        index: usize,
18        source: Box<CodeGenError>,
19    },
20    /// allOf is present but empty (no subschemas to merge).
21    AllOfMergeEmpty,
22    /// At least one subschema in allOf is not object-like (no type "object" and no non-empty properties).
23    AllOfMergeNonObjectSubschema { index: usize },
24    /// Same property appears in multiple subschemas with incompatible types (e.g. string vs integer).
25    AllOfMergeConflictingPropertyType {
26        property_key: String,
27        subschema_indices: Vec<usize>,
28    },
29    /// Same property has conflicting minimum/maximum (or minLength/maxLength, minItems/maxItems) across subschemas that cannot be merged.
30    AllOfMergeConflictingNumericBounds {
31        property_key: String,
32        keyword: String,
33    },
34    /// Same property has enum in more than one subschema with incompatible value sets.
35    AllOfMergeConflictingEnum { property_key: String },
36    /// Same property has const in more than one subschema with different values.
37    AllOfMergeConflictingConst { property_key: String },
38    /// Same property has pattern in more than one subschema with different values.
39    AllOfMergeConflictingPattern { property_key: String },
40    /// Subschema uses unsupported features for merge (e.g. $ref, non-object type).
41    AllOfMergeUnsupportedSubschema { index: usize, reason: String },
42    /// anyOf is present but empty (no subschemas).
43    AnyOfEmpty,
44    /// oneOf is present but empty (no subschemas).
45    OneOfEmpty,
46    /// `$ref` could not be resolved (or is unsupported in this crate).
47    RefResolution { ref_str: String, reason: String },
48}
49
50impl fmt::Display for CodeGenError {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        match self {
53            CodeGenError::RootNotObject => write!(
54                f,
55                "root schema must have type \"object\" and non-empty properties"
56            ),
57            CodeGenError::Io(e) => write!(f, "io error: {e}"),
58            CodeGenError::Batch { index, source } => {
59                write!(f, "schema at index {index}: {source}")
60            }
61            CodeGenError::AllOfMergeEmpty => {
62                write!(f, "allOf is present but empty (no subschemas to merge)")
63            }
64            CodeGenError::AllOfMergeNonObjectSubschema { index } => write!(
65                f,
66                "allOf subschema at index {index} is not object-like (need type \"object\" or non-empty properties)"
67            ),
68            CodeGenError::AllOfMergeConflictingPropertyType {
69                property_key,
70                subschema_indices,
71            } => write!(
72                f,
73                "allOf merge: property \"{property_key}\" has conflicting types in subschemas at indices {subschema_indices:?}"
74            ),
75            CodeGenError::AllOfMergeConflictingNumericBounds {
76                property_key,
77                keyword,
78            } => write!(
79                f,
80                "allOf merge: property \"{property_key}\" has conflicting {keyword} across subschemas"
81            ),
82            CodeGenError::AllOfMergeConflictingEnum { property_key } => write!(
83                f,
84                "allOf merge: property \"{property_key}\" has conflicting enum values across subschemas"
85            ),
86            CodeGenError::AllOfMergeConflictingConst { property_key } => write!(
87                f,
88                "allOf merge: property \"{property_key}\" has conflicting const values across subschemas"
89            ),
90            CodeGenError::AllOfMergeConflictingPattern { property_key } => write!(
91                f,
92                "allOf merge: property \"{property_key}\" has conflicting pattern across subschemas"
93            ),
94            CodeGenError::AllOfMergeUnsupportedSubschema { index, reason } => {
95                write!(
96                    f,
97                    "allOf subschema at index {index} is unsupported for merge: {reason}"
98                )
99            }
100            CodeGenError::AnyOfEmpty => {
101                write!(f, "anyOf is present but empty (no subschemas)")
102            }
103            CodeGenError::OneOfEmpty => {
104                write!(f, "oneOf is present but empty (no subschemas)")
105            }
106            CodeGenError::RefResolution { ref_str, reason } => {
107                write!(f, "could not resolve $ref \"{ref_str}\": {reason}")
108            }
109        }
110    }
111}
112
113impl std::error::Error for CodeGenError {
114    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
115        match self {
116            CodeGenError::Io(e) => Some(e),
117            CodeGenError::RootNotObject
118            | CodeGenError::AllOfMergeEmpty
119            | CodeGenError::AllOfMergeNonObjectSubschema { .. }
120            | CodeGenError::AllOfMergeConflictingPropertyType { .. }
121            | CodeGenError::AllOfMergeConflictingNumericBounds { .. }
122            | CodeGenError::AllOfMergeConflictingEnum { .. }
123            | CodeGenError::AllOfMergeConflictingConst { .. }
124            | CodeGenError::AllOfMergeConflictingPattern { .. }
125            | CodeGenError::AllOfMergeUnsupportedSubschema { .. }
126            | CodeGenError::AnyOfEmpty
127            | CodeGenError::OneOfEmpty
128            | CodeGenError::RefResolution { .. } => None,
129            CodeGenError::Batch { source, .. } => Some(source.as_ref()),
130        }
131    }
132}
133
134impl From<std::io::Error> for CodeGenError {
135    fn from(e: std::io::Error) -> Self {
136        CodeGenError::Io(e)
137    }
138}