1use jsona::{
2 dom::{Keys, Node},
3 error::ErrorObject,
4 util::mapper::Mapper,
5};
6use thiserror::Error;
7
8pub type SchemaResult<T> = std::result::Result<T, Vec<SchemaError>>;
9
10pub const ERROR_SOURCE: &str = "schema";
11
12#[derive(Clone, Debug, Error)]
13pub enum SchemaError {
14 #[error("conflict def {name}")]
15 ConflictDef { keys: Keys, name: String },
16 #[error("unknown ref {name}")]
17 UnknownRef { keys: Keys, name: String },
18 #[error("the type is unexpected")]
19 UnexpectedType { keys: Keys },
20 #[error("the schema type is not match value type")]
21 UnmatchedSchemaType { keys: Keys },
22 #[error("invalid schema value, {error}")]
23 InvalidSchemaValue { keys: Keys, error: String },
24 #[error("invalid compound value")]
25 InvalidCompoundValue { keys: Keys },
26}
27
28impl SchemaError {
29 pub fn keys(&self) -> &Keys {
30 match self {
31 SchemaError::ConflictDef { keys, .. } => keys,
32 SchemaError::UnknownRef { keys, .. } => keys,
33 SchemaError::UnexpectedType { keys } => keys,
34 SchemaError::UnmatchedSchemaType { keys } => keys,
35 SchemaError::InvalidSchemaValue { keys, .. } => keys,
36 SchemaError::InvalidCompoundValue { keys } => keys,
37 }
38 }
39
40 pub fn append_keys(self, prefix_keys: &Keys) -> Self {
41 match self {
42 SchemaError::ConflictDef { keys, name } => SchemaError::ConflictDef {
43 keys: prefix_keys.extend(keys),
44 name,
45 },
46 SchemaError::UnknownRef { keys, name } => SchemaError::UnknownRef {
47 keys: prefix_keys.extend(keys),
48 name,
49 },
50 SchemaError::UnexpectedType { keys } => SchemaError::UnexpectedType {
51 keys: prefix_keys.extend(keys),
52 },
53 SchemaError::UnmatchedSchemaType { keys } => SchemaError::UnmatchedSchemaType {
54 keys: prefix_keys.extend(keys),
55 },
56 SchemaError::InvalidSchemaValue { keys, error } => SchemaError::InvalidSchemaValue {
57 keys: prefix_keys.extend(keys),
58 error,
59 },
60 SchemaError::InvalidCompoundValue { keys } => SchemaError::UnmatchedSchemaType {
61 keys: prefix_keys.extend(keys),
62 },
63 }
64 }
65
66 pub fn to_error_object(&self, node: &Node, mapper: &Mapper) -> ErrorObject {
67 let message = self.to_string();
68 let (kind, range) = match self {
69 SchemaError::ConflictDef { keys, .. } => {
70 ("ConflictDef", keys.mapper_range(node, mapper))
71 }
72 SchemaError::UnknownRef { keys, .. } => ("UnknownRef", keys.mapper_range(node, mapper)),
73 SchemaError::UnexpectedType { keys } => {
74 ("UnexpectedType", keys.mapper_range(node, mapper))
75 }
76 SchemaError::UnmatchedSchemaType { keys } => {
77 ("UnmatchedSchemaType", keys.mapper_range(node, mapper))
78 }
79 SchemaError::InvalidSchemaValue { keys, .. } => {
80 ("InvalidSchemaValue", keys.mapper_range(node, mapper))
81 }
82 SchemaError::InvalidCompoundValue { keys } => {
83 ("InvalidCompoundValue", keys.mapper_range(node, mapper))
84 }
85 };
86 ErrorObject::new(ERROR_SOURCE, kind, message, range)
87 }
88}