dioxus_router/
navigation.rs1use std::{
4 fmt::{Debug, Display},
5 str::FromStr,
6};
7
8use url::{ParseError, Url};
9
10use crate::{
11 components::child_router::consume_child_route_mapping, hooks::try_router, routable::Routable,
12};
13
14impl<R: Routable> From<R> for NavigationTarget {
15 fn from(value: R) -> Self {
16 let mapping = consume_child_route_mapping();
18 match mapping.as_ref() {
19 Some(mapping) => NavigationTarget::Internal(mapping.format_route_as_root_route(value)),
20 None => NavigationTarget::Internal(value.to_string()),
22 }
23 }
24}
25
26#[derive(Clone, PartialEq, Eq, Debug)]
28pub enum NavigationTarget<R = String> {
29 Internal(R),
48 External(String),
67}
68
69impl<R: Routable> From<&str> for NavigationTarget<R> {
70 fn from(value: &str) -> Self {
71 value
72 .parse()
73 .unwrap_or_else(|_| Self::External(value.to_string()))
74 }
75}
76
77impl<R: Routable> From<&String> for NavigationTarget<R> {
78 fn from(value: &String) -> Self {
79 value.as_str().into()
80 }
81}
82
83impl<R: Routable> From<String> for NavigationTarget<R> {
84 fn from(value: String) -> Self {
85 value.as_str().into()
86 }
87}
88
89impl<R: Routable> From<R> for NavigationTarget<R> {
90 fn from(value: R) -> Self {
91 Self::Internal(value)
92 }
93}
94
95impl From<&str> for NavigationTarget {
96 fn from(value: &str) -> Self {
97 match try_router() {
98 Some(router) => match router.internal_route(value) {
99 true => NavigationTarget::Internal(value.to_string()),
100 false => NavigationTarget::External(value.to_string()),
101 },
102 None => NavigationTarget::External(value.to_string()),
103 }
104 }
105}
106
107impl From<String> for NavigationTarget {
108 fn from(value: String) -> Self {
109 match try_router() {
110 Some(router) => match router.internal_route(&value) {
111 true => NavigationTarget::Internal(value),
112 false => NavigationTarget::External(value),
113 },
114 None => NavigationTarget::External(value.to_string()),
115 }
116 }
117}
118
119impl<R: Routable> From<NavigationTarget<R>> for NavigationTarget {
120 fn from(value: NavigationTarget<R>) -> Self {
121 match value {
122 NavigationTarget::Internal(r) => r.into(),
123 NavigationTarget::External(s) => Self::External(s),
124 }
125 }
126}
127
128impl<R: Routable> Display for NavigationTarget<R> {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 match self {
131 NavigationTarget::Internal(r) => write!(f, "{}", r),
132 NavigationTarget::External(s) => write!(f, "{}", s),
133 }
134 }
135}
136
137pub enum NavigationTargetParseError<R: Routable> {
139 InvalidUrl(ParseError),
141 InvalidInternalURL(<R as FromStr>::Err),
143}
144
145impl<R: Routable> Debug for NavigationTargetParseError<R> {
146 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147 match self {
148 NavigationTargetParseError::InvalidUrl(e) => write!(f, "Invalid URL: {}", e),
149 NavigationTargetParseError::InvalidInternalURL(_) => {
150 write!(f, "Invalid internal URL")
151 }
152 }
153 }
154}
155
156impl<R: Routable> FromStr for NavigationTarget<R> {
157 type Err = NavigationTargetParseError<R>;
158
159 fn from_str(s: &str) -> Result<Self, Self::Err> {
160 match Url::parse(s) {
161 Ok(_) => Ok(Self::External(s.to_string())),
162 Err(ParseError::RelativeUrlWithoutBase) => {
163 Ok(Self::Internal(R::from_str(s).map_err(|e| {
164 NavigationTargetParseError::InvalidInternalURL(e)
165 })?))
166 }
167 Err(e) => Err(NavigationTargetParseError::InvalidUrl(e)),
168 }
169 }
170}