router.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. use crate::history::HistoryProvider;
  2. use dioxus::prelude::*;
  3. use std::str::FromStr;
  4. #[derive(Debug, PartialEq)]
  5. pub struct RouteParseError<E: std::fmt::Display> {
  6. pub attempted_routes: Vec<E>,
  7. }
  8. impl<E: std::fmt::Display> std::fmt::Display for RouteParseError<E> {
  9. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  10. write!(f, "Route did not match:\nAttempted Matches:\n")?;
  11. for (i, route) in self.attempted_routes.iter().enumerate() {
  12. writeln!(f, "{}) {route}", i + 1)?;
  13. }
  14. Ok(())
  15. }
  16. }
  17. struct Router<R: Routable, H: HistoryProvider>
  18. where
  19. <R as FromStr>::Err: std::fmt::Display,
  20. {
  21. history: H,
  22. route: R,
  23. }
  24. impl<R: Routable, H: HistoryProvider> Router<R, H>
  25. where
  26. <R as FromStr>::Err: std::fmt::Display,
  27. {
  28. fn new(history: H) -> Result<Self, R::Err> {
  29. let path = history.current_path();
  30. Ok(Self {
  31. history,
  32. route: R::from_str(path.as_str())?,
  33. })
  34. }
  35. }
  36. pub trait FromQuery {
  37. fn from_query(query: &str) -> Self;
  38. }
  39. impl<T: for<'a> From<&'a str>> FromQuery for T {
  40. fn from_query(query: &str) -> Self {
  41. T::from(query)
  42. }
  43. }
  44. pub trait FromRouteSegment: Sized {
  45. type Err;
  46. fn from_route_segment(route: &str) -> Result<Self, Self::Err>;
  47. }
  48. impl<T: FromStr> FromRouteSegment for T
  49. where
  50. <T as FromStr>::Err: std::fmt::Display,
  51. {
  52. type Err = <T as FromStr>::Err;
  53. fn from_route_segment(route: &str) -> Result<Self, Self::Err> {
  54. T::from_str(route)
  55. }
  56. }
  57. pub trait ToRouteSegments {
  58. fn display_route_segements(self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
  59. }
  60. impl<I, T: std::fmt::Display> ToRouteSegments for I
  61. where
  62. I: IntoIterator<Item = T>,
  63. {
  64. fn display_route_segements(self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  65. for segment in self {
  66. write!(f, "/")?;
  67. write!(f, "{}", segment)?;
  68. }
  69. Ok(())
  70. }
  71. }
  72. pub trait FromRouteSegments: Sized {
  73. type Err;
  74. fn from_route_segments(segments: &[&str]) -> Result<Self, Self::Err>;
  75. }
  76. impl<I: std::iter::FromIterator<String>> FromRouteSegments for I {
  77. type Err = <String as FromRouteSegment>::Err;
  78. fn from_route_segments(segments: &[&str]) -> Result<Self, Self::Err> {
  79. segments
  80. .iter()
  81. .map(|s| String::from_route_segment(s))
  82. .collect()
  83. }
  84. }
  85. #[derive(Props, PartialEq)]
  86. pub struct RouterProps {
  87. pub current_route: String,
  88. }
  89. pub trait Routable: FromStr + std::fmt::Display + Clone
  90. where
  91. <Self as FromStr>::Err: std::fmt::Display,
  92. {
  93. fn render(self, cx: &ScopeState) -> Element;
  94. fn comp(cx: Scope<RouterProps>) -> Element
  95. where
  96. Self: 'static,
  97. {
  98. let router = Self::from_str(&cx.props.current_route);
  99. match router {
  100. Ok(router) => router.render(cx),
  101. Err(err) => {
  102. render! {
  103. pre {
  104. "{err}"
  105. }
  106. }
  107. }
  108. }
  109. }
  110. }