diff --git a/src/main.rs b/src/main.rs index d999002..cdb1cc6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ extern crate percent_encoding; extern crate pulldown_cmark; extern crate r2d2; extern crate r2d2_diesel; +extern crate serde; extern crate serde_json; extern crate serde_urlencoded; extern crate slug; diff --git a/src/resources/changes_resource.rs b/src/resources/changes_resource.rs index 82d211e..e50a38f 100644 --- a/src/resources/changes_resource.rs +++ b/src/resources/changes_resource.rs @@ -9,14 +9,16 @@ use site::Layout; use state::State; use web::{Resource, ResponseFuture}; +use super::pagination::Pagination; + pub struct ChangesResource { state: State, before: Option, } impl ChangesResource { - pub fn new(state: State, before: Option) -> Self { - Self { state, before } + pub fn new(state: State, pagination: Pagination) -> Self { + Self { state, before: match pagination { Pagination::Before(x) => Some(x), _ => None } } } } diff --git a/src/resources/mod.rs b/src/resources/mod.rs index 16d481c..097b909 100644 --- a/src/resources/mod.rs +++ b/src/resources/mod.rs @@ -1,3 +1,5 @@ +pub mod pagination; + mod article_redirect_resource; mod article_resource; mod changes_resource; diff --git a/src/resources/pagination.rs b/src/resources/pagination.rs new file mode 100644 index 0000000..6d78c20 --- /dev/null +++ b/src/resources/pagination.rs @@ -0,0 +1,29 @@ +use serde; +use serde_urlencoded; + +#[derive(Deserialize)] +struct PaginationStruct { + after: Option, + before: Option, +} + +pub enum Pagination { + After(T), + Before(T), + None, +} + +impl PaginationStruct { + fn into_enum(self) -> Pagination { + match (self.after, self.before) { + (Some(x), _) => Pagination::After(x), + (None, Some(x)) => Pagination::Before(x), + _ => Pagination::None, + } + } +} + +pub fn from_str<'a, T: serde::Deserialize<'a>>(s: &'a str) -> Result, serde::de::value::Error> { + let pagination: PaginationStruct = serde_urlencoded::from_str(s)?; + Ok(pagination.into_enum()) +} diff --git a/src/wiki_lookup.rs b/src/wiki_lookup.rs index 804684a..5d5397b 100644 --- a/src/wiki_lookup.rs +++ b/src/wiki_lookup.rs @@ -2,10 +2,9 @@ use std::borrow::Cow; use std::collections::HashMap; use std::str::Utf8Error; -use futures::{Future, finished, failed}; +use futures::{Future, finished, failed, done}; use futures::future::FutureResult; use percent_encoding::percent_decode; -use serde_urlencoded; use slug::slugify; use resources::*; @@ -84,17 +83,12 @@ impl WikiLookup { ("_assets", Some(asset)) => Box::new(asset_lookup(asset)), ("_changes", None) => { - #[derive(Deserialize)] - struct Query { - before: Option, - } - - let query: Query = match serde_urlencoded::from_str(query.unwrap_or("")) { - Ok(x) => x, - Err(x) => return Box::new(failed(x.into())), - }; - - Box::new(finished(Some(Box::new(ChangesResource::new(self.state.clone(), query.before)) as BoxResource))) + Box::new(done( + pagination::from_str(query.unwrap_or("")).map_err(Into::into) + .and_then(|pagination| Ok(Some( + Box::new(ChangesResource::new(self.state.clone(), pagination)) as BoxResource + ))) + )) }, ("_new", None) => Box::new(finished(Some(Box::new(NewArticleResource::new(self.state.clone(), None)) as BoxResource))),