Compare commits

..

2 Commits

Author SHA1 Message Date
5201191261 add inspect mapper 2019-12-10 14:39:47 -08:00
197280fe3e Rename the type parameter from C to M for mappers. 2019-12-10 14:06:15 -08:00
4 changed files with 115 additions and 85 deletions

View File

@ -96,20 +96,20 @@ where
} }
/// Call Deref::deref() on the input and pass it to the next mapper. /// Call Deref::deref() on the input and pass it to the next mapper.
pub fn deref<C>(inner: C) -> Deref<C> { pub fn deref<M>(inner: M) -> Deref<M> {
Deref(inner) Deref(inner)
} }
/// The `Deref` mapper returned by [deref()](fn.deref.html) /// The `Deref` mapper returned by [deref()](fn.deref.html)
#[derive(Debug)] #[derive(Debug)]
pub struct Deref<C>(C); pub struct Deref<M>(M);
impl<C, IN> Mapper<IN> for Deref<C> impl<M, IN> Mapper<IN> for Deref<M>
where where
C: Mapper<IN::Target>, M: Mapper<IN::Target>,
IN: std::ops::Deref, IN: std::ops::Deref,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &IN) -> C::Out { fn map(&mut self, input: &IN) -> M::Out {
self.0.map(input.deref()) self.0.map(input.deref())
} }
} }
@ -162,14 +162,14 @@ where
} }
/// invert the result of the inner mapper. /// invert the result of the inner mapper.
pub fn not<C>(inner: C) -> Not<C> { pub fn not<M>(inner: M) -> Not<M> {
Not(inner) Not(inner)
} }
/// The `Not` mapper returned by [not()](fn.not.html) /// The `Not` mapper returned by [not()](fn.not.html)
pub struct Not<C>(C); pub struct Not<M>(M);
impl<C, IN> Mapper<IN> for Not<C> impl<M, IN> Mapper<IN> for Not<M>
where where
C: Mapper<IN, Out = bool>, M: Mapper<IN, Out = bool>,
IN: ?Sized, IN: ?Sized,
{ {
type Out = bool; type Out = bool;
@ -178,9 +178,9 @@ where
!self.0.map(input) !self.0.map(input)
} }
} }
impl<C> fmt::Debug for Not<C> impl<M> fmt::Debug for Not<M>
where where
C: fmt::Debug, M: fmt::Debug,
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Not({:?})", &self.0) write!(f, "Not({:?})", &self.0)
@ -237,20 +237,20 @@ where
} }
/// url decode the input and pass the resulting slice of key-value pairs to the next mapper. /// url decode the input and pass the resulting slice of key-value pairs to the next mapper.
pub fn url_decoded<C>(inner: C) -> UrlDecoded<C> { pub fn url_decoded<M>(inner: M) -> UrlDecoded<M> {
UrlDecoded(inner) UrlDecoded(inner)
} }
/// The `UrlDecoded` mapper returned by [url_decoded()](fn.url_decoded.html) /// The `UrlDecoded` mapper returned by [url_decoded()](fn.url_decoded.html)
#[derive(Debug)] #[derive(Debug)]
pub struct UrlDecoded<C>(C); pub struct UrlDecoded<M>(M);
impl<IN, C> Mapper<IN> for UrlDecoded<C> impl<IN, M> Mapper<IN> for UrlDecoded<M>
where where
IN: AsRef<[u8]> + ?Sized, IN: AsRef<[u8]> + ?Sized,
C: Mapper<[(String, String)]>, M: Mapper<[(String, String)]>,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &IN) -> C::Out { fn map(&mut self, input: &IN) -> M::Out {
let decoded: Vec<(String, String)> = url::form_urlencoded::parse(input.as_ref()) let decoded: Vec<(String, String)> = url::form_urlencoded::parse(input.as_ref())
.into_owned() .into_owned()
.collect(); .collect();
@ -263,20 +263,20 @@ where
/// ///
/// If the input can't be decoded a serde_json::Value::Null is passed to the next /// If the input can't be decoded a serde_json::Value::Null is passed to the next
/// mapper. /// mapper.
pub fn json_decoded<C>(inner: C) -> JsonDecoded<C> { pub fn json_decoded<M>(inner: M) -> JsonDecoded<M> {
JsonDecoded(inner) JsonDecoded(inner)
} }
/// The `JsonDecoded` mapper returned by [json_decoded()](fn.json_decoded.html) /// The `JsonDecoded` mapper returned by [json_decoded()](fn.json_decoded.html)
#[derive(Debug)] #[derive(Debug)]
pub struct JsonDecoded<C>(C); pub struct JsonDecoded<M>(M);
impl<IN, C> Mapper<IN> for JsonDecoded<C> impl<IN, M> Mapper<IN> for JsonDecoded<M>
where where
IN: AsRef<[u8]> + ?Sized, IN: AsRef<[u8]> + ?Sized,
C: Mapper<serde_json::Value>, M: Mapper<serde_json::Value>,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &IN) -> C::Out { fn map(&mut self, input: &IN) -> M::Out {
let json_value: serde_json::Value = let json_value: serde_json::Value =
serde_json::from_slice(input.as_ref()).unwrap_or(serde_json::Value::Null); serde_json::from_slice(input.as_ref()).unwrap_or(serde_json::Value::Null);
self.0.map(&json_value) self.0.map(&json_value)
@ -284,23 +284,20 @@ where
} }
/// lowercase the input and pass it to the next mapper. /// lowercase the input and pass it to the next mapper.
pub fn lowercase<C>(inner: C) -> Lowercase<C> pub fn lowercase<M>(inner: M) -> Lowercase<M> {
where
C: Mapper<[u8]>,
{
Lowercase(inner) Lowercase(inner)
} }
/// The `Lowercase` mapper returned by [lowercase()](fn.lowercase.html) /// The `Lowercase` mapper returned by [lowercase()](fn.lowercase.html)
#[derive(Debug)] #[derive(Debug)]
pub struct Lowercase<C>(C); pub struct Lowercase<M>(M);
impl<IN, C> Mapper<IN> for Lowercase<C> impl<IN, M> Mapper<IN> for Lowercase<M>
where where
IN: AsRef<[u8]> + ?Sized, IN: AsRef<[u8]> + ?Sized,
C: Mapper<[u8]>, M: Mapper<[u8]>,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &IN) -> C::Out { fn map(&mut self, input: &IN) -> M::Out {
use bstr::ByteSlice; use bstr::ByteSlice;
self.0.map(&input.as_ref().to_lowercase()) self.0.map(&input.as_ref().to_lowercase())
} }
@ -328,6 +325,31 @@ impl<F> fmt::Debug for MapFn<F> {
} }
} }
/// inspect the input and pass it to the next mapper.
///
/// This logs the value as it passes it to the next mapper unchanged. Can be
/// useful when troubleshooting why a matcher may not be working as intended.
pub fn inspect<M>(inner: M) -> Inspect<M> {
Inspect(inner)
}
/// The `Inspect` mapper returned by [inspect()](fn.inspect.html)
#[derive(Debug)]
pub struct Inspect<M>(M);
impl<IN, M> Mapper<IN> for Inspect<M>
where
IN: fmt::Debug + ?Sized,
M: Mapper<IN>,
M::Out: fmt::Debug,
{
type Out = M::Out;
fn map(&mut self, input: &IN) -> M::Out {
let output = self.0.map(input);
log::debug!("{:?}.map({:?}) == {:?}", self.0, input, output);
output
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -445,4 +467,12 @@ mod tests {
assert_eq!(true, c.map(&0)); assert_eq!(true, c.map(&0));
assert_eq!(false, c.map(&11)); assert_eq!(false, c.map(&11));
} }
#[test]
fn test_inspect() {
let _ = pretty_env_logger::try_init();
let mut c = inspect(lowercase(matches("^foobar$")));
assert_eq!(true, c.map("Foobar"));
assert_eq!(false, c.map("Foobar1"));
}
} }

View File

@ -3,74 +3,74 @@
use super::Mapper; use super::Mapper;
/// Extract the method from the HTTP request and pass it to the next mapper. /// Extract the method from the HTTP request and pass it to the next mapper.
pub fn method<C>(inner: C) -> Method<C> { pub fn method<M>(inner: M) -> Method<M> {
Method(inner) Method(inner)
} }
/// The `Method` mapper returned by [method()](fn.method.html) /// The `Method` mapper returned by [method()](fn.method.html)
#[derive(Debug)] #[derive(Debug)]
pub struct Method<C>(C); pub struct Method<M>(M);
impl<C, B> Mapper<hyper::Request<B>> for Method<C> impl<M, B> Mapper<hyper::Request<B>> for Method<M>
where where
C: Mapper<str>, M: Mapper<str>,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &hyper::Request<B>) -> C::Out { fn map(&mut self, input: &hyper::Request<B>) -> M::Out {
self.0.map(input.method().as_str()) self.0.map(input.method().as_str())
} }
} }
/// Extract the path from the HTTP request and pass it to the next mapper. /// Extract the path from the HTTP request and pass it to the next mapper.
pub fn path<C>(inner: C) -> Path<C> { pub fn path<M>(inner: M) -> Path<M> {
Path(inner) Path(inner)
} }
/// The `Path` mapper returned by [path()](fn.path.html) /// The `Path` mapper returned by [path()](fn.path.html)
#[derive(Debug)] #[derive(Debug)]
pub struct Path<C>(C); pub struct Path<M>(M);
impl<C, B> Mapper<hyper::Request<B>> for Path<C> impl<M, B> Mapper<hyper::Request<B>> for Path<M>
where where
C: Mapper<str>, M: Mapper<str>,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &hyper::Request<B>) -> C::Out { fn map(&mut self, input: &hyper::Request<B>) -> M::Out {
self.0.map(input.uri().path()) self.0.map(input.uri().path())
} }
} }
/// Extract the query from the HTTP request and pass it to the next mapper. /// Extract the query from the HTTP request and pass it to the next mapper.
pub fn query<C>(inner: C) -> Query<C> { pub fn query<M>(inner: M) -> Query<M> {
Query(inner) Query(inner)
} }
/// The `Query` mapper returned by [query()](fn.query.html) /// The `Query` mapper returned by [query()](fn.query.html)
#[derive(Debug)] #[derive(Debug)]
pub struct Query<C>(C); pub struct Query<M>(M);
impl<C, B> Mapper<hyper::Request<B>> for Query<C> impl<M, B> Mapper<hyper::Request<B>> for Query<M>
where where
C: Mapper<str>, M: Mapper<str>,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &hyper::Request<B>) -> C::Out { fn map(&mut self, input: &hyper::Request<B>) -> M::Out {
self.0.map(input.uri().query().unwrap_or("")) self.0.map(input.uri().query().unwrap_or(""))
} }
} }
/// Extract the headers from the HTTP request and pass the sequence to the next /// Extract the headers from the HTTP request and pass the sequence to the next
/// mapper. /// mapper.
pub fn headers<C>(inner: C) -> Headers<C> { pub fn headers<M>(inner: M) -> Headers<M> {
Headers(inner) Headers(inner)
} }
/// The `Headers` mapper returned by [headers()](fn.headers.html) /// The `Headers` mapper returned by [headers()](fn.headers.html)
#[derive(Debug)] #[derive(Debug)]
pub struct Headers<C>(C); pub struct Headers<M>(M);
impl<C, B> Mapper<hyper::Request<B>> for Headers<C> impl<M, B> Mapper<hyper::Request<B>> for Headers<M>
where where
C: Mapper<[(Vec<u8>, Vec<u8>)]>, M: Mapper<[(Vec<u8>, Vec<u8>)]>,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &hyper::Request<B>) -> C::Out { fn map(&mut self, input: &hyper::Request<B>) -> M::Out {
let headers: Vec<(Vec<u8>, Vec<u8>)> = input let headers: Vec<(Vec<u8>, Vec<u8>)> = input
.headers() .headers()
.iter() .iter()
@ -81,20 +81,20 @@ where
} }
/// Extract the body from the HTTP request and pass it to the next mapper. /// Extract the body from the HTTP request and pass it to the next mapper.
pub fn body<C>(inner: C) -> Body<C> { pub fn body<M>(inner: M) -> Body<M> {
Body(inner) Body(inner)
} }
/// The `Body` mapper returned by [body()](fn.body.html) /// The `Body` mapper returned by [body()](fn.body.html)
#[derive(Debug)] #[derive(Debug)]
pub struct Body<C>(C); pub struct Body<M>(M);
impl<C, B> Mapper<hyper::Request<B>> for Body<C> impl<M, B> Mapper<hyper::Request<B>> for Body<M>
where where
B: ToOwned, B: ToOwned,
C: Mapper<B::Owned>, M: Mapper<B::Owned>,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &hyper::Request<B>) -> C::Out { fn map(&mut self, input: &hyper::Request<B>) -> M::Out {
self.0.map(&input.body().to_owned()) self.0.map(&input.body().to_owned())
} }
} }

View File

@ -3,38 +3,38 @@
use super::Mapper; use super::Mapper;
/// Extract the status code from the HTTP response and pass it to the next mapper. /// Extract the status code from the HTTP response and pass it to the next mapper.
pub fn status_code<C>(inner: C) -> StatusCode<C> { pub fn status_code<M>(inner: M) -> StatusCode<M> {
StatusCode(inner) StatusCode(inner)
} }
/// The `StatusCode` mapper returned by [status_code()](fn.status_code.html) /// The `StatusCode` mapper returned by [status_code()](fn.status_code.html)
#[derive(Debug)] #[derive(Debug)]
pub struct StatusCode<C>(C); pub struct StatusCode<M>(M);
impl<C, B> Mapper<hyper::Response<B>> for StatusCode<C> impl<M, B> Mapper<hyper::Response<B>> for StatusCode<M>
where where
C: Mapper<u16>, M: Mapper<u16>,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &hyper::Response<B>) -> C::Out { fn map(&mut self, input: &hyper::Response<B>) -> M::Out {
self.0.map(&input.status().as_u16()) self.0.map(&input.status().as_u16())
} }
} }
/// Extract the headers from the HTTP response and pass the sequence to the next /// Extract the headers from the HTTP response and pass the sequence to the next
/// mapper. /// mapper.
pub fn headers<C>(inner: C) -> Headers<C> { pub fn headers<M>(inner: M) -> Headers<M> {
Headers(inner) Headers(inner)
} }
/// The `Headers` mapper returned by [headers()](fn.headers.html) /// The `Headers` mapper returned by [headers()](fn.headers.html)
#[derive(Debug)] #[derive(Debug)]
pub struct Headers<C>(C); pub struct Headers<M>(M);
impl<C, B> Mapper<hyper::Response<B>> for Headers<C> impl<M, B> Mapper<hyper::Response<B>> for Headers<M>
where where
C: Mapper<[(Vec<u8>, Vec<u8>)]>, M: Mapper<[(Vec<u8>, Vec<u8>)]>,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &hyper::Response<B>) -> C::Out { fn map(&mut self, input: &hyper::Response<B>) -> M::Out {
let headers: Vec<(Vec<u8>, Vec<u8>)> = input let headers: Vec<(Vec<u8>, Vec<u8>)> = input
.headers() .headers()
.iter() .iter()
@ -45,19 +45,19 @@ where
} }
/// Extract the body from the HTTP response and pass it to the next mapper. /// Extract the body from the HTTP response and pass it to the next mapper.
pub fn body<C>(inner: C) -> Body<C> { pub fn body<M>(inner: M) -> Body<M> {
Body(inner) Body(inner)
} }
/// The `Body` mapper returned by [body()](fn.body.html) /// The `Body` mapper returned by [body()](fn.body.html)
#[derive(Debug)] #[derive(Debug)]
pub struct Body<C>(C); pub struct Body<M>(M);
impl<C, B> Mapper<hyper::Response<B>> for Body<C> impl<M, B> Mapper<hyper::Response<B>> for Body<M>
where where
C: Mapper<B>, M: Mapper<B>,
{ {
type Out = C::Out; type Out = M::Out;
fn map(&mut self, input: &hyper::Response<B>) -> C::Out { fn map(&mut self, input: &hyper::Response<B>) -> M::Out {
self.0.map(input.body()) self.0.map(input.body())
} }
} }

View File

@ -4,15 +4,15 @@ use super::Mapper;
/// true if the provided mapper returns true for any of the elements in the /// true if the provided mapper returns true for any of the elements in the
/// sequence. /// sequence.
pub fn contains<C>(inner: C) -> Contains<C> { pub fn contains<M>(inner: M) -> Contains<M> {
Contains(inner) Contains(inner)
} }
/// The `Contains` mapper returned by [contains()](fn.contains.html) /// The `Contains` mapper returned by [contains()](fn.contains.html)
#[derive(Debug)] #[derive(Debug)]
pub struct Contains<C>(C); pub struct Contains<M>(M);
impl<C, E> Mapper<[E]> for Contains<C> impl<M, E> Mapper<[E]> for Contains<M>
where where
C: Mapper<E, Out = bool>, M: Mapper<E, Out = bool>,
{ {
type Out = bool; type Out = bool;