#[non_exhaustive]pub enum Reason {
Show 32 variants
Syntax(String),
NotAForm {
found: String,
},
Version,
FromTheFuture {
wanted: u64,
understood: u64,
},
Missing {
kind: String,
name: &'static str,
},
UnknownWidget {
found: String,
},
UnknownProperty {
kind: &'static str,
found: String,
accepted: &'static [Property],
},
UnknownFormProperty {
kind: &'static str,
found: String,
accepted: Vec<&'static str>,
},
WrongType {
kind: &'static str,
name: String,
wanted: &'static str,
},
NotAName {
name: String,
found: String,
accepted: &'static [&'static str],
},
UnexpectedChild {
parent: String,
found: String,
},
PlaceholderOutside {
kind: String,
found: String,
},
PayloadClash {
found: String,
first: &'static str,
then: &'static str,
},
NotAnIdentifier {
found: String,
because: &'static str,
},
Collides {
found: String,
with: String,
spelled: String,
},
UnknownMessage {
found: String,
},
WrongMessage {
found: String,
wanted: &'static str,
},
Asset {
path: String,
},
DuplicateName {
name: String,
},
TwoFocuses,
TreeRefused,
TooDeep {
limit: usize,
},
TooLarge {
limit: usize,
},
Unbalanced {
open: bool,
},
CommentedTooDeep {
limit: usize,
},
TooSlow {
limit: Duration,
},
NoThread {
abandoned: usize,
},
NotPreserved,
NoSuchNode {
path: Vec<usize>,
},
IntoItself {
path: Vec<usize>,
},
NoArgument,
WrongKind {
name: String,
holds: &'static str,
given: &'static str,
},
}Expand description
Everything that can be wrong with a form file.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Syntax(String)
The file is not KDL at all.
NotAForm
The top level is not a single form node.
Version
version is missing, or is not a number.
FromTheFuture
The file was written for a later version of this crate.
Missing
A required property is not there.
UnknownWidget
No widget goes by that name.
UnknownProperty
The widget has no such property.
Fields
UnknownFormProperty
A property the form node does not carry — often one that belongs to a
different kind of form.
Separate from Reason::UnknownProperty because what a form accepts
depends on its kind, so the list has to be built rather than pointed at.
Fields
WrongType
The property exists; the value was not the shape it takes.
Fields
NotAName
A name that should have been one of a fixed set was not.
Fields
UnexpectedChild
A child node that the parent has no use for.
PlaceholderOutside
A designer’s placeholder content written where the engine would load it.
A table’s rows and a timeline’s events belong in that node’s
design { … } block, where every build but a designer’s skips them. Left
outside, they would ship to a kiosk — so this is an error rather than a
thing quietly ignored, for the same reason an unknown property is.
PayloadClash
One message name is used with two different payload shapes, so no single enum variant can serve both.
Only codegen raises this. The engine is happy to
resolve one name twice, because the application’s match answers each
call separately; a generated enum cannot, because Greet is either a
variant or a fn(bool) -> M and not both.
Fields
NotAnIdentifier
A name in the file cannot be turned into a Rust identifier.
Only codegen. A form loads perfectly well with a node
called 2; a struct field cannot be called that.
Collides
Two names in the file become one Rust identifier.
Only codegen. full-name and full_name are two
nodes to a form file and one field to Rust.
Fields
UnknownMessage
The application’s resolver did not know a message name.
WrongMessage
The resolver knew the name but gave back the wrong shape of message.
Asset
A picture the application’s loader would not load.
DuplicateName
Two nodes claim the same name.
TwoFocuses
More than one node asked for the caret.
TreeRefused
The tree refused a node, which it does when its parent is gone.
TooDeep
The file nests deeper than this crate will follow.
TooLarge
The file is larger than this crate will read.
Unbalanced
A brace has no partner.
Refused by the same byte scan that counts depth, and for the same
reason: a file whose braces do not balance cannot parse whatever the
parser does with it, and kdl can spend an unbounded amount of time
discovering that. Saying it up front costs one pass and gives a better
position than the recovery would.
CommentedTooDeep
The file nests commented-out children blocks past what the parser can be asked to read.
kdl takes time that doubles with every commented-out block nested
inside another: a hundred bytes of them is twenty seconds, and three
hundred is longer than anyone will wait. So this is refused by a byte
scan before the parser is handed the file at all — the same treatment,
and for the same reason, as nesting past
MAX_DEPTH, which overflows its stack. See
MAX_COMMENTED_DEPTH.
TooSlow
The parse was still running when the caller’s deadline passed, so it was abandoned and the file was not read.
Only Form::parse_within raises this, and
only a caller who asked for a deadline can get it. It says nothing about
the file beyond how long it was taking: a hostile one that has found a
corner of kdl that takes exponential time looks exactly like a
legitimate one on a machine that is too slow for the number chosen. The
position is the top of the file, because nothing in it has been read.
NoThread
A bounded parse could not be started, so the file was not read at all.
Form::parse_within works on a thread it
can walk away from, and this says there was no such thread to be had:
either MAX_ABANDONED earlier parses are still
running past their deadlines — a wedged thread each, and the point of
the limit is that a machine does not fill up with them — or the system
refused a thread outright.
NotPreserved
The parser could not keep the file byte-for-byte.
Everything this crate does — undo, the designer’s save, a text editor
alongside — stands on Form::text reproducing what
was opened, and a file that cannot be reproduced would silently lose
bytes on the first save. Refusing it is the honest alternative.
The known causes are all one thing — kdl dropping the trivia between a
closing brace and the next node, whether that is trailing whitespace or
a comment written on the brace’s line — and all of it is put back before
this is ever raised. So reaching this means a shape nobody has seen yet,
which is what the fuzz target parse_form is hunting for.
NoSuchNode
An edit named a node that is not there.
IntoItself
A move would have put a node inside itself.
Or would have moved the form, which is the document rather than a node in it. Both are the same mistake — a tree cannot contain its own root — and both come from a drag that ended where it should not have been allowed to.
NoArgument
An edit set the positional argument of a node written without one.
An argument comes before every property, and no edit puts something at the front of a line without rewriting the line. Setting the property that argument stands for is what to do instead.
WrongKind
An edit would have put a number where a string lives, or the reverse.
Not a matter of reversibility — an edit’s inverse restores the text that
was there, so any value can be put back. It is a matter of what the file
would become: placeholder=70 parses and then will not build, and an
editor holding the widget’s own descriptor already knows better. So the
door refuses it rather than the loader, three steps later.
A number replacing a number is not this, whichever way it is written:
value=70 becoming value=70.5 is an ordinary edit.