From 2bc0a4178e9ea458ad6c30fc43d534cb4f86caf2 Mon Sep 17 00:00:00 2001 From: Henry Zimmerman Date: Thu, 19 Dec 2019 11:37:40 -0500 Subject: [PATCH 1/3] Relax capture rules in Fragment sections in route syntax parser --- .../yew_router_route_parser/src/optimizer.rs | 22 ++++++++--- crates/yew_router_route_parser/src/parser.rs | 6 +-- src/matcher/matcher_impl.rs | 2 +- tests/macro_test/src/lib.rs | 37 +++++++++++++++++++ 4 files changed, 57 insertions(+), 10 deletions(-) diff --git a/crates/yew_router_route_parser/src/optimizer.rs b/crates/yew_router_route_parser/src/optimizer.rs index 7a30a26..af620dd 100644 --- a/crates/yew_router_route_parser/src/optimizer.rs +++ b/crates/yew_router_route_parser/src/optimizer.rs @@ -62,14 +62,18 @@ pub fn parse_str_and_optimize_tokens( /// In the process of converting the tokens, this function will condense multiple RouteParserTokens /// that represent literals into one Exact variant if multiple reducible tokens happen to occur in a row. pub fn convert_tokens(tokens: &[RouteParserToken]) -> Vec { - let mut new_tokens = vec![]; + let mut new_tokens: Vec = vec![]; let mut run: Vec = vec![]; - fn empty_run(run: &mut Vec) -> MatcherToken { + fn empty_run(run: &mut Vec) -> Option { let segment = run.iter().map(RouteParserToken::as_str).collect::(); run.clear(); - MatcherToken::Exact(segment) + if !segment.is_empty() { + Some(MatcherToken::Exact(segment)) + } else { + None + } } fn empty_run_with_query_cap_at_end( @@ -95,7 +99,9 @@ pub fn convert_tokens(tokens: &[RouteParserToken]) -> Vec { | RouteParserToken::QuerySeparator | RouteParserToken::Exact(_) => run.push(*token), RouteParserToken::Capture(cap) => { - new_tokens.push(empty_run(&mut run)); + if let Some(current_run) = empty_run(&mut run) { + new_tokens.push(current_run); + } new_tokens.push(MatcherToken::Capture(CaptureVariant::from(*cap))) } RouteParserToken::Query { @@ -113,7 +119,9 @@ pub fn convert_tokens(tokens: &[RouteParserToken]) -> Vec { } }, RouteParserToken::End => { - new_tokens.push(empty_run(&mut run)); + if let Some(current_run) = empty_run(&mut run) { + new_tokens.push(current_run); + } new_tokens.push(MatcherToken::End); } RouteParserToken::Nothing => {} @@ -122,7 +130,9 @@ pub fn convert_tokens(tokens: &[RouteParserToken]) -> Vec { // Empty the run at the end. if !run.is_empty() { - new_tokens.push(empty_run(&mut run)); + if let Some(current_run) = empty_run(&mut run) { + new_tokens.push(current_run); + } } new_tokens diff --git a/crates/yew_router_route_parser/src/parser.rs b/crates/yew_router_route_parser/src/parser.rs index ff8ee9d..83fde58 100644 --- a/crates/yew_router_route_parser/src/parser.rs +++ b/crates/yew_router_route_parser/src/parser.rs @@ -388,10 +388,10 @@ fn parse_impl<'a>( }, ParserState::Fragment { prev_token } => match prev_token { RouteParserToken::FragmentBegin => { - alt((fragment_exact, capture_single(field_naming_scheme), get_end))(i) + alt((fragment_exact, capture(field_naming_scheme), get_end))(i) } - RouteParserToken::Exact(_) => alt((capture_single(field_naming_scheme), get_end))(i), - RouteParserToken::Capture(_) => alt((fragment_exact, get_end))(i), + RouteParserToken::Exact(_) => alt((capture(field_naming_scheme), get_end))(i), + RouteParserToken::Capture(_)=> alt((fragment_exact, get_end))(i), _ => Err(nom::Err::Failure(ParseError { reason: Some(ParserErrorReason::InvalidState), expected: vec![], diff --git a/src/matcher/matcher_impl.rs b/src/matcher/matcher_impl.rs index 4bacf1b..3165063 100644 --- a/src/matcher/matcher_impl.rs +++ b/src/matcher/matcher_impl.rs @@ -69,7 +69,7 @@ fn matcher_impl<'a, 'b: 'a, CAP: CaptureCollection<'b>>( settings: MatcherSettings, mut i: &'a str, ) -> IResult<&'a str, CAP> { - trace!("Attempting to match path: {:?} using: {:?}", i, tokens); + trace!("Attempting to match route: {:?} using: {:?}", i, tokens); let mut iter = tokens.iter().peekable(); diff --git a/tests/macro_test/src/lib.rs b/tests/macro_test/src/lib.rs index 9543636..9a18532 100644 --- a/tests/macro_test/src/lib.rs +++ b/tests/macro_test/src/lib.rs @@ -453,5 +453,42 @@ mod tests { } ) } + + mod fragment { + use super::*; + + #[derive(Switch, Debug, Clone, PartialEq)] + #[to = "{*:path}#{*:route}"] + pub struct FragmentAdapter { + path: String, + route: W, + } + + #[test] + fn fragment_is_ignored() { + #[derive(Debug, Switch, Clone, PartialEq)] + pub enum Test { + #[to = "/hello"] + Variant, + } + + let route = Route::new_no_state("/hello"); + let switched = Test::switch(route).expect("Should produce item - test"); + assert_eq!( + switched, + Test::Variant + ); + + let route = Route::new_no_state("/some/garbage#/hello"); + let switched = FragmentAdapter::::switch(route).expect("Should produce item"); + assert_eq!( + switched, + FragmentAdapter { + path: "/some/garbage".to_string(), + route: Test::Variant + } + ) + } + } } } From 0c83782cb0c9da6f80089b2540a71f3c711dc2ba Mon Sep 17 00:00:00 2001 From: Henry Zimmerman Date: Thu, 19 Dec 2019 11:57:49 -0500 Subject: [PATCH 2/3] remove dead code for single_capture- only parser --- crates/yew_router_route_parser/src/core.rs | 8 -------- crates/yew_router_route_parser/src/parser.rs | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/crates/yew_router_route_parser/src/core.rs b/crates/yew_router_route_parser/src/core.rs index 2e4314d..a46c6f5 100644 --- a/crates/yew_router_route_parser/src/core.rs +++ b/crates/yew_router_route_parser/src/core.rs @@ -184,14 +184,6 @@ pub fn capture<'a>( map(capture_impl(field_naming_scheme), RouteParserToken::Capture) } -pub fn capture_single<'a>( - field_naming_scheme: FieldNamingScheme, -) -> impl Fn(&'a str) -> IResult<&'a str, RouteParserToken<'a>, ParseError> { - map( - capture_single_impl(field_naming_scheme), - RouteParserToken::Capture, - ) -} fn capture_single_impl<'a>( field_naming_scheme: FieldNamingScheme, diff --git a/crates/yew_router_route_parser/src/parser.rs b/crates/yew_router_route_parser/src/parser.rs index 83fde58..e530bbe 100644 --- a/crates/yew_router_route_parser/src/parser.rs +++ b/crates/yew_router_route_parser/src/parser.rs @@ -1,7 +1,7 @@ //! Parser that consumes a string and produces the first representation of the matcher. use crate::{ core::{ - capture, capture_single, exact, fragment_exact, get_and, get_end, get_hash, get_question, + capture, exact, fragment_exact, get_and, get_end, get_hash, get_question, get_slash, nothing, query, }, error::{get_reason, ParseError, ParserErrorReason, PrettyParseError}, From d97ffbf85d69f2475878713b267f7887f34ddd26 Mon Sep 17 00:00:00 2001 From: Henry Zimmerman Date: Thu, 19 Dec 2019 11:59:17 -0500 Subject: [PATCH 3/3] cargo fmt --- crates/yew_router_route_parser/src/parser.rs | 6 +-- examples/minimal/src/main.rs | 2 +- examples/router_component/src/a_component.rs | 44 ++++++++++---------- examples/router_component/src/main.rs | 1 - examples/switch/src/main.rs | 3 +- src/agent/bridge.rs | 2 +- src/agent/dispatcher.rs | 7 ++-- src/agent/mod.rs | 13 ++---- src/components/mod.rs | 7 +++- src/components/router_button.rs | 8 +++- src/components/router_link.rs | 38 +++++++++-------- src/lib.rs | 10 +++-- src/route.rs | 22 ++++++---- src/router.rs | 10 +++-- src/service.rs | 21 +++++----- src/switch.rs | 20 +++------ tests/macro_test/src/lib.rs | 8 +--- 17 files changed, 113 insertions(+), 109 deletions(-) diff --git a/crates/yew_router_route_parser/src/parser.rs b/crates/yew_router_route_parser/src/parser.rs index e530bbe..d1a2096 100644 --- a/crates/yew_router_route_parser/src/parser.rs +++ b/crates/yew_router_route_parser/src/parser.rs @@ -1,8 +1,8 @@ //! Parser that consumes a string and produces the first representation of the matcher. use crate::{ core::{ - capture, exact, fragment_exact, get_and, get_end, get_hash, get_question, - get_slash, nothing, query, + capture, exact, fragment_exact, get_and, get_end, get_hash, get_question, get_slash, + nothing, query, }, error::{get_reason, ParseError, ParserErrorReason, PrettyParseError}, FieldNamingScheme, @@ -391,7 +391,7 @@ fn parse_impl<'a>( alt((fragment_exact, capture(field_naming_scheme), get_end))(i) } RouteParserToken::Exact(_) => alt((capture(field_naming_scheme), get_end))(i), - RouteParserToken::Capture(_)=> alt((fragment_exact, get_end))(i), + RouteParserToken::Capture(_) => alt((fragment_exact, get_end))(i), _ => Err(nom::Err::Failure(ParseError { reason: Some(ParserErrorReason::InvalidState), expected: vec![], diff --git a/examples/minimal/src/main.rs b/examples/minimal/src/main.rs index 19cea31..ca398dc 100644 --- a/examples/minimal/src/main.rs +++ b/examples/minimal/src/main.rs @@ -73,7 +73,7 @@ impl Component for Model { AppRoute::C => format!("/c"), }; self.route_service.set_route(&route_string, ()); - self.route = Route{ + self.route = Route { route: route_string, state: (), }; diff --git a/examples/router_component/src/a_component.rs b/examples/router_component/src/a_component.rs index a74480d..37e4f0a 100644 --- a/examples/router_component/src/a_component.rs +++ b/examples/router_component/src/a_component.rs @@ -1,8 +1,6 @@ -use crate::{c_component::CModel, ARoute}; +use crate::{c_component::CModel, ARoute, AppRoute}; use yew::{prelude::*, virtual_dom::VNode, Properties}; -use yew_router::prelude::*; -use yew_router::switch::AllowMissing; -use crate::AppRoute; +use yew_router::{prelude::*, switch::AllowMissing}; pub struct AModel { props: Props, @@ -35,25 +33,25 @@ impl Component for AModel { fn view(&self) -> VNode { html! { -
- { "I am the A component"} -
- route=AppRoute::A(AllowMissing(Some(ARoute)))> - {"Go to a/c"} - -// -// {"Go to a/d (route does not exist)"} -// -
-
- { - match self.props.route { - Some(_) => html!{}, - None => html!{} - } +
+ { "I am the A component"} +
+ route=AppRoute::A(AllowMissing(Some(ARoute)))> + {"Go to a/c"} + + // + // {"Go to a/d (route does not exist)"} + // +
+
+ { + match self.props.route { + Some(_) => html!{}, + None => html!{} + } + } +
+
} -
-
- } } } diff --git a/examples/router_component/src/main.rs b/examples/router_component/src/main.rs index 915378c..0ed283b 100644 --- a/examples/router_component/src/main.rs +++ b/examples/router_component/src/main.rs @@ -93,4 +93,3 @@ pub enum AppRoute { #[derive(Debug, Switch, PartialEq, Clone, Copy)] #[to = "/c"] pub struct ARoute; - diff --git a/examples/switch/src/main.rs b/examples/switch/src/main.rs index 04607ca..2f7a252 100644 --- a/examples/switch/src/main.rs +++ b/examples/switch/src/main.rs @@ -1,5 +1,4 @@ -use yew_router::{route::Route, Switch}; -use yew_router::switch::Permissive; +use yew_router::{route::Route, switch::Permissive, Switch}; fn main() { let route = Route::new_no_state("/some/route"); diff --git a/src/agent/bridge.rs b/src/agent/bridge.rs index c31dbc0..4f3253a 100644 --- a/src/agent/bridge.rs +++ b/src/agent/bridge.rs @@ -1,5 +1,5 @@ //! Bridge to RouteAgent. -use crate::{agent::{RouteAgent}, route::Route, RouteState}; +use crate::{agent::RouteAgent, route::Route, RouteState}; use std::{ fmt::{Debug, Error as FmtError, Formatter}, ops::{Deref, DerefMut}, diff --git a/src/agent/dispatcher.rs b/src/agent/dispatcher.rs index 5e35f97..bb67a9a 100644 --- a/src/agent/dispatcher.rs +++ b/src/agent/dispatcher.rs @@ -1,11 +1,10 @@ //! Dispatcher to RouteAgent. -use crate::agent::{RouteAgent}; +use crate::{agent::RouteAgent, RouteState}; use std::{ fmt::{Debug, Error as FmtError, Formatter}, ops::{Deref, DerefMut}, }; use yew::agent::{Dispatched, Dispatcher}; -use crate::RouteState; /// A wrapped dispatcher to the route agent. /// @@ -16,7 +15,7 @@ where impl RouteAgentDispatcher where - STATE: RouteState + STATE: RouteState, { /// Creates a new bridge. pub fn new() -> Self { @@ -27,7 +26,7 @@ where impl Default for RouteAgentDispatcher where - STATE: RouteState + STATE: RouteState, { fn default() -> Self { Self::new() diff --git a/src/agent/mod.rs b/src/agent/mod.rs index e92dcab..c5ff736 100644 --- a/src/agent/mod.rs +++ b/src/agent/mod.rs @@ -21,7 +21,6 @@ mod dispatcher; pub use dispatcher::RouteAgentDispatcher; - /// Internal Message used for the RouteAgent. #[derive(Debug)] pub enum Msg { @@ -122,8 +121,7 @@ where match msg { RouteRequest::ReplaceRoute(route) => { let route_string: String = route.to_string(); - self.route_service - .replace_route(&route_string, route.state); + self.route_service.replace_route(&route_string, route.state); let route = self.route_service.get_route(); for sub in &self.subscribers { self.link.respond(*sub, route.clone()); @@ -131,14 +129,12 @@ where } RouteRequest::ReplaceRouteNoBroadcast(route) => { let route_string: String = route.to_string(); - self.route_service - .replace_route(&route_string, route.state); + self.route_service.replace_route(&route_string, route.state); } RouteRequest::ChangeRoute(route) => { let route_string: String = route.to_string(); // set the route - self.route_service - .set_route(&route_string, route.state); + self.route_service.set_route(&route_string, route.state); // get the new route. let route = self.route_service.get_route(); // broadcast it to all listening components @@ -148,8 +144,7 @@ where } RouteRequest::ChangeRouteNoBroadcast(route) => { let route_string: String = route.to_string(); - self.route_service - .set_route(&route_string, route.state); + self.route_service.set_route(&route_string, route.state); } RouteRequest::GetCurrentRoute => { let route = self.route_service.get_route(); diff --git a/src/components/mod.rs b/src/components/mod.rs index c634b94..136d992 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -10,13 +10,16 @@ use yew::{Children, Properties}; #[allow(deprecated)] pub use self::{router_button::RouterButton, router_link::RouterAnchor, router_link::RouterLink}; -use crate::{Switch}; +use crate::Switch; // TODO This should also be PartialEq and Clone. Its blocked on Children not supporting that. // TODO This should no longer take link & String, and instead take a route: SW implementing Switch /// Properties for `RouterButton` and `RouterLink`. #[derive(Properties, Default, Debug)] -pub struct Props where SW: Switch { +pub struct Props +where + SW: Switch, +{ /// The Switched item representing the route. #[props(required)] pub route: SW, diff --git a/src/components/router_button.rs b/src/components/router_button.rs index 68a0646..1726f4e 100644 --- a/src/components/router_button.rs +++ b/src/components/router_button.rs @@ -1,5 +1,9 @@ //! A component wrapping a `