Skip to main content

yew_nav_link/
errors.rs

1// SPDX-FileCopyrightText: 2024-2026 RAprogramm <andrey.rozanov-vl@gmail.com>
2// SPDX-License-Identifier: MIT
3
4//! # NavError
5//!
6//! Error types returned by navigation operations. Use [`NavResult<T>`] as a
7//! convenience alias for `Result<T, NavError>`.
8//!
9//! # Example
10//!
11//! ```rust
12//! use yew_nav_link::NavError;
13//!
14//! fn handle_error(err: &NavError) {
15//!     match err {
16//!         NavError::RouteNotFound => { /* handle */ }
17//!         NavError::InvalidRoute(msg) => { /* handle */ }
18//!         NavError::NavigationCancelled => { /* handle */ }
19//!     }
20//! }
21//! ```
22//!
23//! # Variants
24//!
25//! | Variant | Description |
26//! |---------|-------------|
27//! | `RouteNotFound` | Target route does not match any registered route |
28//! | `InvalidRoute(String)` | Route string could not be parsed |
29//! | `NavigationCancelled` | Navigation was cancelled |
30
31use std::{
32    error::Error,
33    fmt::{Display, Formatter}
34};
35
36/// Errors that can occur during navigation operations.
37///
38/// Returned by navigation hooks and helper functions when something
39/// goes wrong while resolving or activating a route.
40#[derive(Debug, Clone, PartialEq, Eq)]
41#[must_use]
42pub enum NavError {
43    /// The target route does not match any registered route.
44    RouteNotFound,
45    /// A route string could not be parsed. Contains a diagnostic message.
46    InvalidRoute(String),
47    /// Navigation was cancelled before completion.
48    NavigationCancelled
49}
50
51impl Display for NavError {
52    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
53        match self {
54            Self::RouteNotFound => write!(f, "route not found"),
55            Self::InvalidRoute(msg) => write!(f, "invalid route: {msg}"),
56            Self::NavigationCancelled => write!(f, "navigation cancelled")
57        }
58    }
59}
60
61impl Error for NavError {}
62
63impl NavError {
64    /// Creates a [`NavError::RouteNotFound`] error.
65    pub const fn route_not_found() -> Self {
66        Self::RouteNotFound
67    }
68
69    /// Creates a [`NavError::InvalidRoute`] error with the given message.
70    pub fn invalid_route<S: Into<String>>(msg: S) -> Self {
71        Self::InvalidRoute(msg.into())
72    }
73
74    /// Creates a [`NavError::NavigationCancelled`] error.
75    pub const fn navigation_cancelled() -> Self {
76        Self::NavigationCancelled
77    }
78}
79
80/// A convenience alias for `Result<T, NavError>`.
81pub type NavResult<T> = Result<T, NavError>;
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn route_not_found() {
89        let err = NavError::route_not_found();
90        assert_eq!(err, NavError::RouteNotFound);
91    }
92
93    #[test]
94    fn invalid_route() {
95        let err = NavError::invalid_route("bad route");
96        assert_eq!(err, NavError::InvalidRoute("bad route".to_string()));
97    }
98
99    #[test]
100    fn navigation_cancelled() {
101        let err = NavError::navigation_cancelled();
102        assert_eq!(err, NavError::NavigationCancelled);
103    }
104
105    #[test]
106    fn nav_error_display() {
107        assert_eq!(
108            format!("{}", NavError::route_not_found()),
109            "route not found"
110        );
111        assert_eq!(
112            format!("{}", NavError::invalid_route("foo")),
113            "invalid route: foo"
114        );
115        assert_eq!(
116            format!("{}", NavError::navigation_cancelled()),
117            "navigation cancelled"
118        );
119    }
120
121    #[test]
122    fn nav_error_debug() {
123        let err = NavError::route_not_found();
124        let debug_str = format!("{err:?}");
125        assert!(debug_str.contains("RouteNotFound"));
126    }
127
128    #[test]
129    fn nav_error_clone() {
130        let err1 = NavError::route_not_found();
131        let err2 = err1.clone();
132        assert_eq!(err1, err2);
133    }
134
135    #[test]
136    fn nav_error_partial_eq() {
137        assert_eq!(NavError::route_not_found(), NavError::route_not_found());
138        assert_eq!(
139            NavError::navigation_cancelled(),
140            NavError::navigation_cancelled()
141        );
142    }
143
144    #[test]
145    fn nav_result_alias() {
146        let ok: NavResult<i32> = Ok(42);
147        let err: NavResult<i32> = Err(NavError::route_not_found());
148        assert!(ok.is_ok());
149        assert!(err.is_err());
150    }
151}