Skip to main content

scratch_test_model/aux/
errors.rs

1use crate::aux::{AttrLocation, JsonCtx};
2
3/// General block parsing failed because of the json structure, this is not about [attributes](`crate::attrs`).
4#[derive(Debug, PartialEq, Clone, thiserror::Error)]
5pub enum BlockJsonStructureError {
6    /// The requested block [`Id`](`crate::Id`) wasn't found in the
7    /// [target](`crate::scopes::Target`)'s json mapping `blocks`
8    ///
9    /// This should rarely occur as multiple program parts only request blocks
10    /// that were previously found in the file by e. g. iterating over all
11    /// block `Id`s
12    #[error("the requested id doesn't exist in the current target")]
13    IdNotFound,
14    /// The found block data (for the requested [`Id`](`crate::Id`)) is not
15    /// a json mapping (`{ ... }`). This should never happen in a valid file.
16    #[error("block is not a json object/mapping, fields not found")]
17    BlockIsNoMapping,
18    /// Mapping is missing a needed key-value-pair, like `inputs` or `fields`.
19    ///
20    /// Regardless of the block's kind or opcode, some attributes need to be present.
21    /// Examples of such attributes are `opcode` or `inputs`.
22    /// For procedures the `mutation` key has to be present additionally.
23    #[error("block mapping doesn't contain mandatory '{0}' option")]
24    MissingMandatoryAttr(&'static str),
25    /// A block property is of invalid form, this is not about attributes like in [`crate::attrs`].
26    ///
27    /// `inputs`, `fields` and `mutation` need to be – if present – json mappings from
28    /// attribute names to their values. An opcode should be a string. This error
29    /// indicates that one of those expectations was violated.
30    #[error("the '{attr}' attribute is of the wrong type, it should be {correct_type}")]
31    AttrWrongType {
32        attr: &'static str,
33        correct_type: &'static str,
34    },
35}
36
37/// Specific error for the current block kind's requirements.
38///
39/// The most interesting one is [BlockKindError::AttrParsing] as this is produced
40/// by individual block attributes (the data associated with a particular block).
41#[derive(Debug, PartialEq, Clone, thiserror::Error)]
42pub enum BlockKindError<'a> {
43    /// The found opcode is no valid choice for the tried block kind.
44    ///
45    /// Either the wrong kind type was tried, the block opcode is not supported or it is
46    /// just invalid. Every opcode that is supported by a variant of
47    /// [`BlockKind`](crate::blocks::BlockKind) is valid.
48    #[error("the found opcode is no valid choice for the tried block kind: {0}")]
49    UnknownOpcode(svalue::ARc<str>),
50    #[error("json-repr of block: {0}")]
51    JsonStructure(#[from] BlockJsonStructureError),
52    #[error("missing block attr: {0}")]
53    MissingMandatoryAttr(#[from] MandatoryAttrMissingError),
54    #[error("parsing attribute {location}.'{key}': {error}")]
55    AttrParsing {
56        location: AttrLocation,
57        key: &'static str,
58        error: AttributeParseError<'a>,
59    },
60}
61
62/// Inner error indicating an attribute's content is invalid.
63///
64/// This is typically wrapped by [`AttributeParseError`] and focuses
65/// on errors of the type-specific format, when shadow information is
66/// already resolved.
67#[derive(derive_more::Debug, PartialEq, Clone, thiserror::Error)]
68pub enum AttributeContentError<'a> {
69    // Custom-Assoc-Type? / Subblock für alle?
70    #[error("{0}")]
71    #[debug("{_0:?}")]
72    Other(&'static str),
73
74    /// Some attributes can be one of multiple types. This is represented with [`either::Either`].
75    /// If the `Left` variant fails to parse, `Right` is tried with the same input.
76    /// If both fail the errors are returned.
77    #[error("'Either' attribute failed twice: first={first_err}, second={second_err}")]
78    BothEitherFailed {
79        first_err: Box<AttributeContentError<'a>>,
80        second_err: Box<AttributeContentError<'a>>,
81    },
82
83    #[error("expected an array (fixed-len={specified_length:?}): {value}")]
84    ExpectedArray {
85        value: &'a serde_json::Value,
86        specified_length: Option<usize>,
87    },
88
89    /// The found value is invalid, some attribute types provide a list with valid
90    /// alternatives/hints.
91    #[error("value {invalid:?} is invalid for dropdown, valid examples/hints: {hint_list}")]
92    InvalidOptionForDropdown {
93        invalid: String,
94        hint_list: &'static str,
95    },
96
97    #[error("this dropdown is expected to have a string id as reference to it's menu, not: {0}")]
98    ExternalDropdownMenuReferenceNotString(&'a serde_json::Value),
99
100    /// Some attributes don't contain the real data but only a reference to another block.
101    /// This variant means that such a block occured and wasn't totally valid.
102    #[error("there was an error parsing an indirection subblock: {0}")]
103    Subblock(Box<JsonCtx<'a, BlockKindError<'a>>>),
104}
105
106/// Main error for parsing of attributes.
107#[derive(Debug, PartialEq, Clone, thiserror::Error)]
108pub enum AttributeParseError<'a> {
109    /// The attribute's only value is a singleton array indicating that it contains shadow
110    /// information, but the array has no real data
111    #[error("attribute is not providing a real value, only shadow indication")]
112    ShadowWithoutValue,
113    /// The attribute has two nested shadow levels,
114    /// when the first is traversed (to the block hiding the possible shadow)
115    /// another shadow information was found. This is invalid
116    #[error("attribute contains two levels of shadow information, only one allowed")]
117    DuplicateShadow,
118    /// The attribute's value is invalid for the expected type.
119    #[error("content, shadowing={shadow_resolved}: {error}")]
120    Content {
121        /// If there was shadow information that was traversed to parse only the active value
122        ///
123        /// This can be useful to spot if an invalid value triggered shadow-resolving,
124        /// even though it shouldn't happen
125        shadow_resolved: bool,
126        /// The details about the error the content produced
127        error: AttributeContentError<'a>,
128    },
129}
130
131/// A mapping like `inputs` or `fields` misses an [attribute](`crate::attrs`) that is expected for the opcode.
132#[derive(Debug, PartialEq, PartialOrd, Clone, thiserror::Error)]
133#[error(
134    "the mandatory block attribute '{key}' is missing from the expected property set '{location}'"
135)]
136pub struct MandatoryAttrMissingError {
137    pub(super) location: AttrLocation,
138    pub(super) key: &'static str,
139}