Skip to content
This repository has been archived by the owner on Jul 19, 2020. It is now read-only.

Commit

Permalink
Store state as a serialized string (#201)
Browse files Browse the repository at this point in the history
* remove AgentState

* use a json string to store and restore state in the history api.

* fix cargo format problem in warp server example
  • Loading branch information
hgzimmerman authored Dec 16, 2019
1 parent 80d0320 commit 20ef3be
Show file tree
Hide file tree
Showing 12 changed files with 66 additions and 59 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ yew-router-route-parser = {path = "crates/yew_router_route_parser", version = "0
yew-router-macro = {path = "crates/yew_router_macro", version = "0.8.0"}
nom = "5.0.1"
uuid = "0.8.1"
serde_json = "1.0.44"



Expand Down
5 changes: 4 additions & 1 deletion examples/servers/warp/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use std::path::PathBuf;

#[rustfmt::skip]
use warp::{
filters::BoxedFilter,
fs::File,
path::{self, Peek},
path::Peek,
path,
Filter, Reply,
};

Expand Down
15 changes: 6 additions & 9 deletions src/agent/bridge.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
//! Bridge to RouteAgent.
use crate::{
agent::{AgentState, RouteAgent},
route::Route,
};
use crate::{agent::{RouteAgent}, route::Route, RouteState};
use std::{
fmt::{Debug, Error as FmtError, Formatter},
ops::{Deref, DerefMut},
Expand All @@ -17,11 +14,11 @@ use yew::{
/// A component that owns this can send and receive messages from the agent.
pub struct RouteAgentBridge<T = ()>(Box<dyn Bridge<RouteAgent<T>>>)
where
for<'de> T: AgentState<'de>;
T: RouteState;

impl<T> RouteAgentBridge<T>
where
for<'de> T: AgentState<'de>,
T: RouteState,
{
/// Creates a new bridge.
pub fn new(callback: Callback<Route<T>>) -> Self {
Expand All @@ -39,20 +36,20 @@ where
}
}

impl<T: for<'de> AgentState<'de>> Debug for RouteAgentBridge<T> {
impl<T: RouteState> Debug for RouteAgentBridge<T> {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
f.debug_tuple("RouteAgentBridge").finish()
}
}

impl<T: for<'de> AgentState<'de>> Deref for RouteAgentBridge<T> {
impl<T: RouteState> Deref for RouteAgentBridge<T> {
type Target = Box<dyn Bridge<RouteAgent<T>>>;

fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: for<'de> AgentState<'de>> DerefMut for RouteAgentBridge<T> {
impl<T: RouteState> DerefMut for RouteAgentBridge<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
Expand Down
15 changes: 8 additions & 7 deletions src/agent/dispatcher.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
//! Dispatcher to RouteAgent.
use crate::agent::{AgentState, RouteAgent};
use crate::agent::{RouteAgent};
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.
///
/// A component that owns and instance of this can send messages to the RouteAgent, but not receive them.
pub struct RouteAgentDispatcher<T = ()>(Dispatcher<RouteAgent<T>>)
where
for<'de> T: AgentState<'de>;
T: RouteState;

impl<T> RouteAgentDispatcher<T>
where
for<'de> T: AgentState<'de>,
T: RouteState
{
/// Creates a new bridge.
pub fn new() -> Self {
Expand All @@ -26,27 +27,27 @@ where

impl<T> Default for RouteAgentDispatcher<T>
where
for<'de> T: AgentState<'de>,
T: RouteState
{
fn default() -> Self {
Self::new()
}
}

impl<T: for<'de> AgentState<'de>> Debug for RouteAgentDispatcher<T> {
impl<T: RouteState> Debug for RouteAgentDispatcher<T> {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
f.debug_tuple("RouteAgentDispatcher").finish()
}
}

impl<T: for<'de> AgentState<'de>> Deref for RouteAgentDispatcher<T> {
impl<T: RouteState> Deref for RouteAgentDispatcher<T> {
type Target = Dispatcher<RouteAgent<T>>;

fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: for<'de> AgentState<'de>> DerefMut for RouteAgentDispatcher<T> {
impl<T: RouteState> DerefMut for RouteAgentDispatcher<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
Expand Down
10 changes: 4 additions & 6 deletions src/agent/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ pub use bridge::RouteAgentBridge;
mod dispatcher;
pub use dispatcher::RouteAgentDispatcher;

/// Any state that can be used in the router agent must meet the criteria of this trait.
pub trait AgentState<'de>: RouteState + Serialize + Deserialize<'de> + Debug {}
impl<'de, T> AgentState<'de> for T where T: RouteState + Serialize + Deserialize<'de> + Debug {}


/// Internal Message used for the RouteAgent.
#[derive(Debug)]
Expand Down Expand Up @@ -61,7 +59,7 @@ pub enum RouteRequest<T = ()> {
/// each other and associated components may not work as intended.
pub struct RouteAgent<T = ()>
where
for<'de> T: AgentState<'de>,
T: RouteState,
{
// In order to have the AgentLink<Self> below, apparently T must be constrained like this.
// Unfortunately, this means that everything related to an agent requires this constraint.
Expand All @@ -74,7 +72,7 @@ where
subscribers: HashSet<HandlerId>,
}

impl<T: for<'de> AgentState<'de>> Debug for RouteAgent<T> {
impl<T: RouteState> Debug for RouteAgent<T> {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
f.debug_struct("RouteAgent")
.field("link", &"-")
Expand All @@ -86,7 +84,7 @@ impl<T: for<'de> AgentState<'de>> Debug for RouteAgent<T> {

impl<T> Agent for RouteAgent<T>
where
for<'de> T: AgentState<'de>,
T: RouteState,
{
type Input = RouteRequest<T>;
type Message = Msg<T>;
Expand Down
2 changes: 1 addition & 1 deletion src/components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::RouterState;
// TODO This should also be PartialEq and Clone. Its blocked on Children not supporting that.
/// Properties for `RouterButton` and `RouterLink`.
#[derive(Properties, Default, Debug)]
pub struct Props<T: for<'de> RouterState<'de>> {
pub struct Props<T: RouterState> {
/// The route that will be set when the component is clicked.
pub link: String,
/// The state to set when changing the route.
Expand Down
4 changes: 2 additions & 2 deletions src/components/router_button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ use yew::virtual_dom::VNode;

/// Changes the route when clicked.
#[derive(Debug)]
pub struct RouterButton<T: for<'de> RouterState<'de> = ()> {
pub struct RouterButton<T: RouterState = ()> {
link: ComponentLink<Self>,
router: RouteAgentDispatcher<T>,
props: Props<T>,
}

impl<T: for<'de> RouterState<'de>> Component for RouterButton<T> {
impl<T: RouterState> Component for RouterButton<T> {
type Message = Msg;
type Properties = Props<T>;

Expand Down
4 changes: 2 additions & 2 deletions src/components/router_link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ pub type RouterLink<T> = RouterAnchor<T>;

/// An anchor tag Component that when clicked, will navigate to the provided route.
#[derive(Debug)]
pub struct RouterAnchor<T: for<'de> RouterState<'de> = ()> {
pub struct RouterAnchor<T: RouterState = ()> {
link: ComponentLink<Self>,
router: RouteAgentDispatcher<T>,
props: Props<T>,
}

impl<T: for<'de> RouterState<'de>> Component for RouterAnchor<T> {
impl<T: RouterState> Component for RouterAnchor<T> {
type Message = Msg;
type Properties = Props<T>;

Expand Down
4 changes: 0 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ pub mod prelude {
pub use crate::switch::Switch;
pub use yew_router_macro::Switch;
// State restrictions
#[cfg(feature = "agent")]
pub use crate::agent::AgentState;
pub use crate::route::RouteState;
#[cfg(feature = "router")]
pub use crate::router::RouterState;
Expand All @@ -113,8 +111,6 @@ pub mod matcher;

pub use matcher::Captures;

#[cfg(feature = "agent")]
pub use crate::agent::AgentState;
pub use crate::route::RouteState;
#[cfg(feature = "router")]
pub use crate::router::RouterState;
Expand Down
12 changes: 7 additions & 5 deletions src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
use crate::service::RouteService;
use serde::{Deserialize, Serialize};
use std::{fmt, ops::Deref};
use stdweb::{unstable::TryFrom, JsSerialize, Value};
use stdweb::{unstable::TryFrom, Value};
use std::fmt::Debug;
use serde::de::DeserializeOwned;

/// Any state that can be stored by the History API must meet the criteria of this trait.
pub trait RouteState: Clone + Default + JsSerialize + TryFrom<Value> + 'static {}
impl<T> RouteState for T where T: Clone + Default + JsSerialize + TryFrom<Value> + 'static {}
/// Any state that can be used in the router agent must meet the criteria of this trait.
pub trait RouteState: Serialize + DeserializeOwned + Debug + Clone + Default + TryFrom<Value> + 'static {}
impl<T> RouteState for T where T: Serialize + DeserializeOwned + Debug + Clone + Default + TryFrom<Value> + 'static {}

/// The representation of a route, segmented into different sections for easy access.
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
Expand Down Expand Up @@ -48,7 +50,7 @@ impl<T> Route<T> {

impl<T> fmt::Display for Route<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.route.fmt(f)
std::fmt::Display::fmt(&self.route, f)
}
}

Expand Down
33 changes: 14 additions & 19 deletions src/router.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
//! Router Component.
use crate::{
agent::{RouteAgentBridge, RouteRequest},
route::Route,
Switch,
};
use crate::{agent::{RouteAgentBridge, RouteRequest}, route::Route, Switch, RouteState};
use std::{
fmt::{self, Debug, Error as FmtError, Formatter},
rc::Rc,
};
use yew::{html, virtual_dom::VNode, Component, ComponentLink, Html, Properties, ShouldRender};

use crate::agent::AgentState;

/// Any state that can be managed by the `Router` must meet the criteria of this trait.
pub trait RouterState<'de>: AgentState<'de> + PartialEq {}
impl<'de, T> RouterState<'de> for T where T: AgentState<'de> + PartialEq {}
pub trait RouterState: RouteState + PartialEq {}
impl<T> RouterState for T where T: RouteState + PartialEq {}

/// Rendering control flow component.
///
Expand Down Expand Up @@ -59,15 +54,15 @@ impl<'de, T> RouterState<'de> for T where T: AgentState<'de> + PartialEq {}
/// ```
// TODO, can M just be removed due to not having to explicitly deal with callbacks anymore? - Just get rid of M
#[derive(Debug)]
pub struct Router<SW: Switch + Clone + 'static, T: for<'de> RouterState<'de> = ()> {
pub struct Router<SW: Switch + Clone + 'static, T: RouterState = ()> {
switch: Option<SW>,
props: Props<T, SW>,
router_agent: RouteAgentBridge<T>,
}

impl<SW, T> Router<SW, T>
where
T: for<'de> RouterState<'de>,
T: RouterState,
SW: Switch + Clone + 'static,
{
// TODO render fn name is overloaded now with that of the trait: Renderable<_> this should be changed. Maybe: display, show, switch, inner...
Expand Down Expand Up @@ -114,16 +109,16 @@ pub trait RenderFn<CTX: Component, SW>: Fn(SW) -> Html {}
impl<T, CTX: Component, SW> RenderFn<CTX, SW> for T where T: Fn(SW) -> Html {}
/// Owned Render function.
#[derive(Clone)]
pub struct Render<SW: Switch + Clone + 'static, T: for<'de> RouterState<'de> = ()>(
pub struct Render<SW: Switch + Clone + 'static, T: RouterState = ()>(
pub(crate) Rc<dyn RenderFn<Router<SW, T>, SW>>,
);
impl<T: for<'de> RouterState<'de>, SW: Switch + Clone> Render<SW, T> {
impl<T: RouterState, SW: Switch + Clone> Render<SW, T> {
/// New render function
fn new<F: RenderFn<Router<SW, T>, SW> + 'static>(f: F) -> Self {
Render(Rc::new(f))
}
}
impl<T: for<'de> RouterState<'de>, SW: Switch + Clone> Debug for Render<SW, T> {
impl<T: RouterState, SW: Switch + Clone> Debug for Render<SW, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Render").finish()
}
Expand All @@ -135,23 +130,23 @@ pub trait RedirectFn<SW, STATE>: Fn(Route<STATE>) -> SW {}
impl<T, SW, STATE> RedirectFn<SW, STATE> for T where T: Fn(Route<STATE>) -> SW {}
/// Clonable Redirect function
#[derive(Clone)]
pub struct Redirect<SW: Switch + 'static, STATE: for<'de> RouterState<'de>>(
pub struct Redirect<SW: Switch + 'static, STATE: RouterState>(
pub(crate) Rc<dyn RedirectFn<SW, STATE>>,
);
impl<STATE: for<'de> RouterState<'de>, SW: Switch + 'static> Redirect<SW, STATE> {
impl<STATE: RouterState, SW: Switch + 'static> Redirect<SW, STATE> {
fn new<F: RedirectFn<SW, STATE> + 'static>(f: F) -> Self {
Redirect(Rc::new(f))
}
}
impl<STATE: for<'de> RouterState<'de>, SW: Switch> Debug for Redirect<SW, STATE> {
impl<STATE: RouterState, SW: Switch> Debug for Redirect<SW, STATE> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Redirect").finish()
}
}

/// Properties for Router.
#[derive(Properties, Clone)]
pub struct Props<T: for<'de> RouterState<'de>, SW: Switch + Clone + 'static> {
pub struct Props<T: RouterState, SW: Switch + Clone + 'static> {
/// Render function that takes a Switch and produces Html
#[props(required)]
pub render: Render<SW, T>,
Expand All @@ -161,15 +156,15 @@ pub struct Props<T: for<'de> RouterState<'de>, SW: Switch + Clone + 'static> {
pub redirect: Option<Redirect<SW, T>>,
}

impl<T: for<'de> RouterState<'de>, SW: Switch + Clone> Debug for Props<T, SW> {
impl<T: RouterState, SW: Switch + Clone> Debug for Props<T, SW> {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
f.debug_struct("Props").finish()
}
}

impl<T, SW> Component for Router<SW, T>
where
T: for<'de> RouterState<'de>,
T: RouterState,
SW: Switch + Clone + 'static,
{
type Message = Msg<T>;
Expand Down
Loading

0 comments on commit 20ef3be

Please sign in to comment.