memory.rs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. use std::str::FromStr;
  2. use crate::routable::Routable;
  3. use super::HistoryProvider;
  4. /// A [`HistoryProvider`] that stores all navigation information in memory.
  5. pub struct MemoryHistory<R: Routable> {
  6. current: R,
  7. history: Vec<R>,
  8. future: Vec<R>,
  9. }
  10. impl<R: Routable> MemoryHistory<R>
  11. where
  12. <R as FromStr>::Err: std::fmt::Display,
  13. {
  14. /// Create a [`MemoryHistory`] starting at `path`.
  15. ///
  16. /// ```rust
  17. /// # use dioxus_router_core::history::{HistoryProvider, MemoryHistory};
  18. /// let mut history = MemoryHistory::with_initial_path("/some/path").unwrap();
  19. /// assert_eq!(history.current_path(), "/some/path");
  20. /// assert_eq!(history.can_go_back(), false);
  21. /// ```
  22. pub fn with_initial_path(path: impl Into<String>) -> Result<Self, <R as FromStr>::Err> {
  23. let path = path.into();
  24. Ok(Self {
  25. current: R::from_str(&path)?,
  26. ..Default::default()
  27. })
  28. }
  29. }
  30. impl<R: Routable> Default for MemoryHistory<R>
  31. where
  32. <R as FromStr>::Err: std::fmt::Display,
  33. {
  34. fn default() -> Self {
  35. Self {
  36. current: "/".parse().unwrap_or_else(|err| panic!("{}", err)),
  37. history: Vec::new(),
  38. future: Vec::new(),
  39. }
  40. }
  41. }
  42. impl<R: Routable> HistoryProvider<R> for MemoryHistory<R> {
  43. fn current_route(&self) -> R {
  44. self.current.clone()
  45. }
  46. fn can_go_back(&self) -> bool {
  47. !self.history.is_empty()
  48. }
  49. fn go_back(&mut self) {
  50. if let Some(last) = self.history.pop() {
  51. let old = std::mem::replace(&mut self.current, last);
  52. self.future.push(old);
  53. }
  54. }
  55. fn can_go_forward(&self) -> bool {
  56. !self.future.is_empty()
  57. }
  58. fn go_forward(&mut self) {
  59. if let Some(next) = self.future.pop() {
  60. let old = std::mem::replace(&mut self.current, next);
  61. self.history.push(old);
  62. }
  63. }
  64. fn push(&mut self, new: R) {
  65. let old = std::mem::replace(&mut self.current, new);
  66. self.history.push(old);
  67. self.future.clear();
  68. }
  69. fn replace(&mut self, path: R) {
  70. self.current = path;
  71. }
  72. }
  73. // #[cfg(test)]
  74. // mod tests {
  75. // use super::*;
  76. // #[test]
  77. // fn default() {
  78. // let mem = MemoryHistory::default();
  79. // assert_eq!(mem.current, Url::parse(INITIAL_URL).unwrap());
  80. // assert_eq!(mem.history, Vec::<String>::new());
  81. // assert_eq!(mem.future, Vec::<String>::new());
  82. // }
  83. // #[test]
  84. // fn with_initial_path() {
  85. // let mem = MemoryHistory::with_initial_path("something").unwrap();
  86. // assert_eq!(
  87. // mem.current,
  88. // Url::parse(&format!("{INITIAL_URL}something")).unwrap()
  89. // );
  90. // assert_eq!(mem.history, Vec::<String>::new());
  91. // assert_eq!(mem.future, Vec::<String>::new());
  92. // }
  93. // #[test]
  94. // fn with_initial_path_with_leading_slash() {
  95. // let mem = MemoryHistory::with_initial_path("/something").unwrap();
  96. // assert_eq!(
  97. // mem.current,
  98. // Url::parse(&format!("{INITIAL_URL}something")).unwrap()
  99. // );
  100. // assert_eq!(mem.history, Vec::<String>::new());
  101. // assert_eq!(mem.future, Vec::<String>::new());
  102. // }
  103. // #[test]
  104. // fn can_go_back() {
  105. // let mut mem = MemoryHistory::default();
  106. // assert!(!mem.can_go_back());
  107. // mem.push(String::from("/test"));
  108. // assert!(mem.can_go_back());
  109. // }
  110. // #[test]
  111. // fn go_back() {
  112. // let mut mem = MemoryHistory::default();
  113. // mem.push(String::from("/test"));
  114. // mem.go_back();
  115. // assert_eq!(mem.current, Url::parse(INITIAL_URL).unwrap());
  116. // assert!(mem.history.is_empty());
  117. // assert_eq!(mem.future, vec![format!("{INITIAL_URL}test")]);
  118. // }
  119. // #[test]
  120. // fn can_go_forward() {
  121. // let mut mem = MemoryHistory::default();
  122. // assert!(!mem.can_go_forward());
  123. // mem.push(String::from("/test"));
  124. // mem.go_back();
  125. // assert!(mem.can_go_forward());
  126. // }
  127. // #[test]
  128. // fn go_forward() {
  129. // let mut mem = MemoryHistory::default();
  130. // mem.push(String::from("/test"));
  131. // mem.go_back();
  132. // mem.go_forward();
  133. // assert_eq!(
  134. // mem.current,
  135. // Url::parse(&format!("{INITIAL_URL}test")).unwrap()
  136. // );
  137. // assert_eq!(mem.history, vec![INITIAL_URL.to_string()]);
  138. // assert!(mem.future.is_empty());
  139. // }
  140. // #[test]
  141. // fn push() {
  142. // let mut mem = MemoryHistory::default();
  143. // mem.push(String::from("/test"));
  144. // assert_eq!(
  145. // mem.current,
  146. // Url::parse(&format!("{INITIAL_URL}test")).unwrap()
  147. // );
  148. // assert_eq!(mem.history, vec![INITIAL_URL.to_string()]);
  149. // assert!(mem.future.is_empty());
  150. // }
  151. // #[test]
  152. // #[should_panic = r#"cannot navigate to paths starting with "//": //test"#]
  153. // #[cfg(debug_assertions)]
  154. // fn push_debug() {
  155. // let mut mem = MemoryHistory::default();
  156. // mem.push(String::from("//test"));
  157. // }
  158. // #[test]
  159. // #[cfg(not(debug_assertions))]
  160. // fn push_release() {
  161. // let mut mem = MemoryHistory::default();
  162. // mem.push(String::from("//test"));
  163. // assert_eq!(mem.current, Url::parse(INITIAL_URL).unwrap());
  164. // assert!(mem.history.is_empty())
  165. // }
  166. // #[test]
  167. // fn replace() {
  168. // let mut mem = MemoryHistory::default();
  169. // mem.push(String::from("/test"));
  170. // mem.push(String::from("/other"));
  171. // mem.go_back();
  172. // mem.replace(String::from("/replace"));
  173. // assert_eq!(
  174. // mem.current,
  175. // Url::parse(&format!("{INITIAL_URL}replace")).unwrap()
  176. // );
  177. // assert_eq!(mem.history, vec![INITIAL_URL.to_string()]);
  178. // assert_eq!(mem.future, vec![format!("{INITIAL_URL}other")]);
  179. // }
  180. // #[test]
  181. // #[should_panic = r#"cannot navigate to paths starting with "//": //test"#]
  182. // #[cfg(debug_assertions)]
  183. // fn replace_debug() {
  184. // let mut mem = MemoryHistory::default();
  185. // mem.replace(String::from("//test"));
  186. // }
  187. // #[test]
  188. // #[cfg(not(debug_assertions))]
  189. // fn replace_release() {
  190. // let mut mem = MemoryHistory::default();
  191. // mem.replace(String::from("//test"));
  192. // assert_eq!(mem.current, Url::parse(INITIAL_URL).unwrap());
  193. // }
  194. // }