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),
49 External(String),
69}
70
71impl<R: Routable> From<&str> for NavigationTarget<R> {
72 fn from(value: &str) -> Self {
73 value
74 .parse()
75 .unwrap_or_else(|_| Self::External(value.to_string()))
76 }
77}
78
79impl<R: Routable> From<&String> for NavigationTarget<R> {
80 fn from(value: &String) -> Self {
81 value.as_str().into()
82 }
83}
84
85impl<R: Routable> From<String> for NavigationTarget<R> {
86 fn from(value: String) -> Self {
87 value.as_str().into()
88 }
89}
90
91impl<R: Routable> From<R> for NavigationTarget<R> {
92 fn from(value: R) -> Self {
93 Self::Internal(value)
94 }
95}
96
97impl From<&str> for NavigationTarget {
98 fn from(value: &str) -> Self {
99 match try_router() {
100 Some(router) => match router.internal_route(value) {
101 true => NavigationTarget::Internal(value.to_string()),
102 false => NavigationTarget::External(value.to_string()),
103 },
104 None => NavigationTarget::External(value.to_string()),
105 }
106 }
107}
108
109impl From<String> for NavigationTarget {
110 fn from(value: String) -> Self {
111 match try_router() {
112 Some(router) => match router.internal_route(&value) {
113 true => NavigationTarget::Internal(value),
114 false => NavigationTarget::External(value),
115 },
116 None => NavigationTarget::External(value.to_string()),
117 }
118 }
119}
120
121impl<R: Routable> From<NavigationTarget<R>> for NavigationTarget {
122 fn from(value: NavigationTarget<R>) -> Self {
123 match value {
124 NavigationTarget::Internal(r) => r.into(),
125 NavigationTarget::External(s) => Self::External(s),
126 }
127 }
128}
129
130impl<R: Routable> Display for NavigationTarget<R> {
131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 match self {
133 NavigationTarget::Internal(r) => write!(f, "{}", r),
134 NavigationTarget::External(s) => write!(f, "{}", s),
135 }
136 }
137}
138
139pub enum NavigationTargetParseError<R: Routable> {
141 InvalidUrl(ParseError),
143 InvalidInternalURL(<R as FromStr>::Err),
145}
146
147impl<R: Routable> Debug for NavigationTargetParseError<R> {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 match self {
150 NavigationTargetParseError::InvalidUrl(e) => write!(f, "Invalid URL: {}", e),
151 NavigationTargetParseError::InvalidInternalURL(_) => {
152 write!(f, "Invalid internal URL")
153 }
154 }
155 }
156}
157
158impl<R: Routable> FromStr for NavigationTarget<R> {
159 type Err = NavigationTargetParseError<R>;
160
161 fn from_str(s: &str) -> Result<Self, Self::Err> {
162 match Url::parse(s) {
163 Ok(_) => Ok(Self::External(s.to_string())),
164 Err(ParseError::RelativeUrlWithoutBase) => {
165 Ok(Self::Internal(R::from_str(s).map_err(|e| {
166 NavigationTargetParseError::InvalidInternalURL(e)
167 })?))
168 }
169 Err(e) => Err(NavigationTargetParseError::InvalidUrl(e)),
170 }
171 }
172}