Skip to main content

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>;