blockworx/schema/
error.rs1use miette::{Diagnostic, NamedSource, SourceSpan};
9use thiserror::Error;
10
11#[derive(Debug, Error, Diagnostic)]
12pub enum SchemaError {
13 #[error("{message}")]
15 Json {
16 message: String,
17 #[label("here")]
18 span: SourceSpan,
19 #[source_code]
20 src: NamedSource<String>,
21 },
22
23 #[error("invalid {kind} id {value:?}: {reason}")]
24 Id {
25 kind: &'static str,
26 value: String,
27 reason: String,
28 },
29
30 #[error("document `top` id {value:?} is invalid: {reason}")]
31 BadTop { value: String, reason: String },
32
33 #[error("block {block:?}: route anchor {value:?} is invalid: {reason}")]
34 Anchor {
35 block: String,
36 value: String,
37 reason: String,
38 },
39
40 #[error("block {block:?}: pin {pin:?} is missing its `loc`")]
41 MissingPinSide { block: String, pin: String },
42
43 #[error("block {block:?}: pin {pin:?} has invalid `loc` {value:?}: {reason}")]
44 BadLoc {
45 block: String,
46 pin: String,
47 value: String,
48 reason: String,
49 },
50
51 #[error("asset {asset:?} has invalid base64 png: {reason}")]
52 AssetPng { asset: String, reason: String },
53
54 #[error("asset {asset:?} is defined more than once")]
55 DuplicateAsset { asset: String },
56
57 #[error("block {block:?} places image {asset:?}, which no `asset` node defines")]
58 UnknownAsset { block: String, asset: String },
59
60 #[error("block {block:?} lists child {child:?}, which is not present in the document")]
61 DanglingChild { block: String, child: String },
62}
63
64impl SchemaError {
65 pub(super) fn json(src: &str, src_name: &str, error: &serde_json::Error) -> Self {
70 let offset = byte_offset(src, error.line(), error.column());
71 SchemaError::Json {
72 message: error.to_string(),
73 span: (offset, 1.min(src.len().saturating_sub(offset))).into(),
74 src: NamedSource::new(src_name, src.to_owned()),
75 }
76 }
77}
78
79fn byte_offset(src: &str, line: usize, column: usize) -> usize {
82 let start: usize = src
83 .split_inclusive('\n')
84 .take(line.saturating_sub(1))
85 .map(str::len)
86 .sum();
87 (start + column.saturating_sub(1)).min(src.len())
88}