rdom_core/error.rs
1//! Error types for arena operations.
2//!
3//! DOM spec defines hierarchy errors as throwable; in Rust we return
4//! `Result<_, DomError>` from any operation that can fail. Tests exercise
5//! every error variant.
6
7use crate::NodeId;
8use crate::node::NodeType;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11#[non_exhaustive]
12pub enum DomError {
13 /// NodeId doesn't exist in this arena (may have been freed).
14 InvalidNode(NodeId),
15
16 /// Would create a cycle: attempted to insert a node into its own
17 /// subtree (spec `HierarchyRequestError`).
18 HierarchyRequest,
19
20 /// `insert_before` / `replace_child` reference child does not belong
21 /// to the target parent (spec `NotFoundError`).
22 NotFound,
23
24 /// Operation requires a specific node type — e.g. `set_node_value`
25 /// only works on Text and Comment nodes, not Element / Fragment.
26 WrongNodeType {
27 expected: &'static str,
28 got: NodeType,
29 },
30
31 /// A byte offset supplied to a text-editing operation either
32 /// overshoots the node's data length or falls inside a multi-byte
33 /// UTF-8 codepoint (not on a `char` boundary). Callers should
34 /// derive offsets from `Position` or grapheme walks to avoid this.
35 InvalidOffset { node: NodeId, offset: usize },
36
37 /// The operation is not valid in the object's current state (spec
38 /// `InvalidStateError`) — e.g. dispatching an `Event` that is
39 /// already being dispatched.
40 InvalidState(&'static str),
41
42 /// An argument has the wrong kind — the web's `TypeError` (Web IDL
43 /// §3.14.1 simple exception, not a `DOMException`), named without
44 /// the `Error` suffix like the `DOMException` names above
45 /// (`InvalidStateError` → `InvalidState`). E.g.
46 /// `form.requestSubmit(submitter)` with a submitter that is not a
47 /// submit button.
48 Type(&'static str),
49
50 /// A string argument does not parse (spec `SyntaxError`) — e.g.
51 /// `el.contentEditable = "yes"`.
52 Syntax(&'static str),
53}
54
55impl std::fmt::Display for DomError {
56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 match self {
58 DomError::InvalidNode(id) => write!(f, "invalid node id: {id:?}"),
59 DomError::HierarchyRequest => write!(f, "hierarchy request error: would create cycle"),
60 DomError::NotFound => write!(f, "reference node not found in target"),
61 DomError::WrongNodeType { expected, got } => {
62 write!(f, "wrong node type: expected {expected}, got {got:?}")
63 }
64 DomError::InvalidOffset { node, offset } => {
65 write!(
66 f,
67 "invalid byte offset {offset} for node {node:?} (out of range or mid-codepoint)"
68 )
69 }
70 DomError::InvalidState(what) => write!(f, "invalid state: {what}"),
71 DomError::Type(what) => write!(f, "type error: {what}"),
72 DomError::Syntax(what) => write!(f, "syntax error: {what}"),
73 }
74 }
75}
76
77impl std::error::Error for DomError {}
78
79pub type Result<T> = std::result::Result<T, DomError>;