<commit_before>use std::cmp;
use std::io;
use std::ops::Deref;

pub use self::Doc::{
    Nil,
    Append,
    Group,
    Nest,
    Newline,
    Text,
};

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
enum Mode {
    Break,
    Flat,
}

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Doc<'a, B> {
    Nil,
    Append(B, B),
    Group(B),
    Nest(usize, B),
    Newline,
    Text(::std::borrow::Cow<'a, str>),
}

impl<'a, B> Doc<'a, B> {
    #[inline]
    pub fn render<'b, W: io::Write>(&'b self, width: usize, out: &mut W) -> io::Result<()>
    where B: Deref<Target = Doc<'b, B>>
    {
        best(self, width, out).and_then(|()| out.write_all(b"\n"))
    }
}

type Cmd<'a, B> = (usize, Mode, &'a Doc<'a, B>);

#[inline]
fn fitting<'a, B>(
    next: Cmd<'a, B>,
    bcmds: &Vec<Cmd<'a, B>>,
    fcmds: &mut Vec<Cmd<'a, B>>,
    mut rem: isize,
) -> bool
where B: Deref<Target = Doc<'a, B>>
{
    let mut bidx = bcmds.len();
    let mut fits = true;
    fcmds.clear(); // clear from previous calls from best
    fcmds.push(next);
    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match fcmds.pop() {
            None => {
                if bidx == 0 {
                    break;
                } else {
                    fcmds.push(bcmds[ bidx - 1 ]);
                    bidx -= 1;
                }
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(ref ldoc, ref rdoc) => {
                    fcmds.push((ind, mode, rdoc));
                    fcmds.push((ind, mode, ldoc));
                },
                &Group(ref doc) => {
                    fcmds.push((ind, mode, doc));
                },
                &Nest(off, ref doc) => {
                    fcmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    fits = true;
                },
                &Text(ref str) => {
                    rem -= str.len() as isize;
                },
            }
        }
    }
    fits
}

#[inline]
pub fn best<'a, W: io::Write, B>(
    doc: &'a Doc<'a, B>,
    width: usize,
    out: &mut W,
) -> io::Result<()>
where B: Deref<Target = Doc<'a, B>>
{
    let mut pos = 0usize;
    let mut bcmds = vec![(0usize, Mode::Break, doc)];
    let mut fcmds = vec![];
    while let Some((ind, mode, doc)) = bcmds.pop() {
        match doc {
            &Nil => {
            },
            &Append(ref ldoc, ref rdoc) => {
                bcmds.push((ind, mode, rdoc));
                bcmds.push((ind, mode, ldoc));
            },
            &Group(ref doc) => match mode {
                Mode::Flat => {
                    bcmds.push((ind, Mode::Flat, doc));
                },
                Mode::Break => {
                    let next = (ind, Mode::Flat, &**doc);
                    let rem = width as isize - pos as isize;
                    if fitting(next, &bcmds, &mut fcmds, rem) {
                        bcmds.push(next);
                    } else {
                        bcmds.push((ind, Mode::Break, doc));
                    }
                }
            },
            &Nest(off, ref doc) => {
                bcmds.push((ind + off, mode, doc));
            },
            &Newline => {
                match mode {
                    Mode::Flat => {
                        try!(out.write_all(b" "));
                    },
                    Mode::Break => {
                        const SPACES: [u8; 100] = [b' '; 100];
                        try!(out.write_all(b"\n"));
                        let mut inserted = 0;
                        while inserted < ind {
                            let insert = cmp::min(100, ind - inserted);
                            inserted += insert;
                            try!(out.write_all(&SPACES[..insert]));
                        }
                    },
                }
                pos = ind;
            },
            &Text(ref s) => {
                try!(out.write_all(&s.as_bytes()));
                pos += s.len();
            },
        }
    }
    Ok(())
}
<commit_msg>Add impl<S: Into<Cow<str>>> From<S> for Doc<commit_after>use std::borrow::Cow;
use std::cmp;
use std::io;
use std::ops::Deref;

pub use self::Doc::{
    Nil,
    Append,
    Group,
    Nest,
    Newline,
    Text,
};

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
enum Mode {
    Break,
    Flat,
}

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Doc<'a, B> {
    Nil,
    Append(B, B),
    Group(B),
    Nest(usize, B),
    Newline,
    Text(Cow<'a, str>),
}

impl<'a, B, S> From<S> for Doc<'a, B> where S: Into<Cow<'a, str>> {
    fn from(s: S) -> Doc<'a, B> {
        Doc::Text(s.into())
    }
}

impl<'a, B> Doc<'a, B> {
    #[inline]
    pub fn render<'b, W: io::Write>(&'b self, width: usize, out: &mut W) -> io::Result<()>
    where B: Deref<Target = Doc<'b, B>>
    {
        best(self, width, out).and_then(|()| out.write_all(b"\n"))
    }
}

type Cmd<'a, B> = (usize, Mode, &'a Doc<'a, B>);

#[inline]
fn fitting<'a, B>(
    next: Cmd<'a, B>,
    bcmds: &Vec<Cmd<'a, B>>,
    fcmds: &mut Vec<Cmd<'a, B>>,
    mut rem: isize,
) -> bool
where B: Deref<Target = Doc<'a, B>>
{
    let mut bidx = bcmds.len();
    let mut fits = true;
    fcmds.clear(); // clear from previous calls from best
    fcmds.push(next);
    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match fcmds.pop() {
            None => {
                if bidx == 0 {
                    break;
                } else {
                    fcmds.push(bcmds[ bidx - 1 ]);
                    bidx -= 1;
                }
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(ref ldoc, ref rdoc) => {
                    fcmds.push((ind, mode, rdoc));
                    fcmds.push((ind, mode, ldoc));
                },
                &Group(ref doc) => {
                    fcmds.push((ind, mode, doc));
                },
                &Nest(off, ref doc) => {
                    fcmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    fits = true;
                },
                &Text(ref str) => {
                    rem -= str.len() as isize;
                },
            }
        }
    }
    fits
}

#[inline]
pub fn best<'a, W: io::Write, B>(
    doc: &'a Doc<'a, B>,
    width: usize,
    out: &mut W,
) -> io::Result<()>
where B: Deref<Target = Doc<'a, B>>
{
    let mut pos = 0usize;
    let mut bcmds = vec![(0usize, Mode::Break, doc)];
    let mut fcmds = vec![];
    while let Some((ind, mode, doc)) = bcmds.pop() {
        match doc {
            &Nil => {
            },
            &Append(ref ldoc, ref rdoc) => {
                bcmds.push((ind, mode, rdoc));
                bcmds.push((ind, mode, ldoc));
            },
            &Group(ref doc) => match mode {
                Mode::Flat => {
                    bcmds.push((ind, Mode::Flat, doc));
                },
                Mode::Break => {
                    let next = (ind, Mode::Flat, &**doc);
                    let rem = width as isize - pos as isize;
                    if fitting(next, &bcmds, &mut fcmds, rem) {
                        bcmds.push(next);
                    } else {
                        bcmds.push((ind, Mode::Break, doc));
                    }
                }
            },
            &Nest(off, ref doc) => {
                bcmds.push((ind + off, mode, doc));
            },
            &Newline => {
                match mode {
                    Mode::Flat => {
                        try!(out.write_all(b" "));
                    },
                    Mode::Break => {
                        const SPACES: [u8; 100] = [b' '; 100];
                        try!(out.write_all(b"\n"));
                        let mut inserted = 0;
                        while inserted < ind {
                            let insert = cmp::min(100, ind - inserted);
                            inserted += insert;
                            try!(out.write_all(&SPACES[..insert]));
                        }
                    },
                }
                pos = ind;
            },
            &Text(ref s) => {
                try!(out.write_all(&s.as_bytes()));
                pos += s.len();
            },
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use super::mode;
use super::string_utils;

#[deriving(Clone)]
#[deriving(Show)]
enum DOC {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Nest(uint, Box<Doc>),
    Text(String),
    Break(uint, uint),
    Newline,
    Group(Box<Doc>)
}

pub type Doc = DOC;

fn fitting(xs:&Vec<(uint,mode::Mode,Doc)>, left:uint) -> bool {
    if left as int >= 0 {
        match xs.as_slice() {
            [] => true,
            [(ref i, ref mode, ref doc), ref rest..] => match *doc {
                Nil => fitting(&rest.to_vec(), left),
                Append(ref x, ref y) => {
                    let mut ys = [(*i, *mode, *x.clone()), (*i, *mode, *y.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(&ys, left)
                },
                Nest(j, ref x) => {
                    let mut ys = [(*i + j, *mode, *x.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(&ys, left)
                },
                Text(ref str) => fitting(&rest.to_vec(), left - str.len()),
                Break(sp, _) => match *mode {
                    mode::Flat => fitting(&rest.to_vec(), left - sp),
                    mode::Break => true
                },
                Newline => true,
                Group(ref x) => {
                    let mut ys = [(*i, *mode, *x.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(&ys, left)
                }
            }
        }
    }
    else {
        false
    }
}

fn prepend<A:Clone>(v: Vec<A>, x:A) -> Vec<A> {
    let mut res = v;
    res.insert(0, x);
    res
}

fn best(w:uint, s:Vec<String>, x:Doc) -> Vec<String> {
    fn go(w:uint, s:Vec<String>, k:uint, xs:Vec<(uint,mode::Mode,Doc)>) -> Vec<String> {
        match xs.as_slice() {
            [] => s.clone(),
            [(ref i, ref mode, ref doc), ref rest..] => match *doc {
                Nil => go(w, s, k, rest.to_vec()),
                Append(ref x, ref y) => {
                    let mut zs = [(*i, *mode, *x.clone()), (*i, *mode, *y.clone())].to_vec();
                    zs.push_all(*rest);
                    go(w, s, k, zs)
                },
                Nest(j, ref x) => {
                    let mut zs = [(*i + j, *mode, *x.clone())].to_vec();
                    zs.push_all(*rest);
                    go(w, s, k, zs)
                },
                Text(ref str) => go(w, prepend(s, str.clone()), k + str.len(), rest.to_vec()),
                Newline => go(w, prepend(s, string_utils::nl_space(*i)), *i, rest.to_vec()),
                Break(sp, off) => {
                    match *mode {
                        mode::Flat => go(w, prepend(s.clone(), string_utils::spaces(sp)), k + sp, rest.to_vec()),
                        mode::Break => go(w, prepend(s.clone(), string_utils::nl_space(i + off)), i + off, rest.to_vec())
                    }
                },
                Group(ref x) => {
                    match *mode {
                        mode::Flat => {
                            let mut zs = [(*i, mode::Flat, *x.clone())].to_vec();
                            zs.push_all(*rest);
                            go(w, s, k, zs)
                        },
                        mode::Break => {
                            let mut ys = [(*i, mode::Flat, *x.clone())].to_vec();
                            ys.push_all(*rest);
                            if fitting(&ys, w - k) {
                                go(w, s, k, ys)
                            } else {
                                let mut zs = [(*i, mode::Break, *x.clone())].to_vec();
                                zs.push_all(*rest);
                                go(w, s, k, zs)
                            }
                        }
                    }
                }
            }
        }
    }
    go(w, s, 0, [(0, mode::Break, x)].to_vec())
}

impl Doc {

    pub fn nil() -> Doc {
        Nil
    }

    pub fn append(&self, e:Doc) -> Doc {
        match *self {
            Nil => e,
            ref x => match e {
                Nil => x.clone(),
                y => Append(box x.clone(), box y)
            }
        }
    }

    pub fn nest(&self, i:uint) -> Doc {
        Nest(i, box self.clone())
    }

    pub fn text(str:String) -> Doc {
        Text(str)
    }

    pub fn str(str:&str) -> Doc {
        Text(String::from_str(str))
    }

    pub fn brk(space:uint, offset:uint) -> Doc {
        Break(space, offset)
    }

    pub fn newline() -> Doc {
        Newline
    }

    pub fn group(&self) -> Doc {
        Group(box self.clone())
    }

    pub fn concat(ds:&[Doc]) -> Doc {
        ds.iter().fold(Nil, |a, b| a.append(b.clone()))
    }

    pub fn int(i:int) -> Doc {
        Text(format!("{}", i))
    }

    pub fn char(c:char) -> Doc {
        Text(format!("{}", c))
    }

    pub fn bool(b:bool) -> Doc {
        let res = if b { "true" } else { "false" };
        Text(String::from_str(res))
    }

    pub fn to_string(&self, w:uint) -> String {
        let mut strs = best(w, Vec::new(), self.clone());
        strs.reverse();
        strs.push(String::from_str("\n"));
        strs.concat()
    }
}
<commit_msg>Vec should generally be passed by-value<commit_after>use super::mode;
use super::string_utils;

#[deriving(Clone)]
#[deriving(Show)]
enum DOC {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Nest(uint, Box<Doc>),
    Text(String),
    Break(uint, uint),
    Newline,
    Group(Box<Doc>)
}

pub type Doc = DOC;

fn fitting(xs:Vec<(uint,mode::Mode,Doc)>, left:uint) -> bool {
    if left as int >= 0 {
        match xs.as_slice() {
            [] => true,
            [(ref i, ref mode, ref doc), ref rest..] => match *doc {
                Nil => fitting(rest.to_vec(), left),
                Append(ref x, ref y) => {
                    let mut ys = [(*i, *mode, *x.clone()), (*i, *mode, *y.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(ys, left)
                },
                Nest(j, ref x) => {
                    let mut ys = [(*i + j, *mode, *x.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(ys, left)
                },
                Text(ref str) => fitting(rest.to_vec(), left - str.len()),
                Break(sp, _) => match *mode {
                    mode::Flat => fitting(rest.to_vec(), left - sp),
                    mode::Break => true
                },
                Newline => true,
                Group(ref x) => {
                    let mut ys = [(*i, *mode, *x.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(ys, left)
                }
            }
        }
    }
    else {
        false
    }
}

fn prepend<A:Clone>(v: Vec<A>, x:A) -> Vec<A> {
    let mut res = v;
    res.insert(0, x);
    res
}

fn best(w:uint, s:Vec<String>, x:Doc) -> Vec<String> {
    fn go(w:uint, s:Vec<String>, k:uint, xs:Vec<(uint,mode::Mode,Doc)>) -> Vec<String> {
        match xs.as_slice() {
            [] => s.clone(),
            [(ref i, ref mode, ref doc), ref rest..] => match *doc {
                Nil => go(w, s, k, rest.to_vec()),
                Append(ref x, ref y) => {
                    let mut zs = [(*i, *mode, *x.clone()), (*i, *mode, *y.clone())].to_vec();
                    zs.push_all(*rest);
                    go(w, s, k, zs)
                },
                Nest(j, ref x) => {
                    let mut zs = [(*i + j, *mode, *x.clone())].to_vec();
                    zs.push_all(*rest);
                    go(w, s, k, zs)
                },
                Text(ref str) => go(w, prepend(s, str.clone()), k + str.len(), rest.to_vec()),
                Newline => go(w, prepend(s, string_utils::nl_space(*i)), *i, rest.to_vec()),
                Break(sp, off) => {
                    match *mode {
                        mode::Flat => go(w, prepend(s.clone(), string_utils::spaces(sp)), k + sp, rest.to_vec()),
                        mode::Break => go(w, prepend(s.clone(), string_utils::nl_space(i + off)), i + off, rest.to_vec())
                    }
                },
                Group(ref x) => {
                    match *mode {
                        mode::Flat => {
                            let mut zs = [(*i, mode::Flat, *x.clone())].to_vec();
                            zs.push_all(*rest);
                            go(w, s, k, zs)
                        },
                        mode::Break => {
                            let mut ys = [(*i, mode::Flat, *x.clone())].to_vec();
                            ys.push_all(*rest);
                            if fitting(ys.clone(), w - k) {
                                go(w, s, k, ys)
                            } else {
                                let mut zs = [(*i, mode::Break, *x.clone())].to_vec();
                                zs.push_all(*rest);
                                go(w, s, k, zs)
                            }
                        }
                    }
                }
            }
        }
    }
    go(w, s, 0, [(0, mode::Break, x)].to_vec())
}

impl Doc {

    pub fn nil() -> Doc {
        Nil
    }

    pub fn append(&self, e:Doc) -> Doc {
        match *self {
            Nil => e,
            ref x => match e {
                Nil => x.clone(),
                y => Append(box x.clone(), box y)
            }
        }
    }

    pub fn nest(&self, i:uint) -> Doc {
        Nest(i, box self.clone())
    }

    pub fn text(str:String) -> Doc {
        Text(str)
    }

    pub fn str(str:&str) -> Doc {
        Text(String::from_str(str))
    }

    pub fn brk(space:uint, offset:uint) -> Doc {
        Break(space, offset)
    }

    pub fn newline() -> Doc {
        Newline
    }

    pub fn group(&self) -> Doc {
        Group(box self.clone())
    }

    pub fn concat(ds:&[Doc]) -> Doc {
        ds.iter().fold(Nil, |a, b| a.append(b.clone()))
    }

    pub fn int(i:int) -> Doc {
        Text(format!("{}", i))
    }

    pub fn char(c:char) -> Doc {
        Text(format!("{}", c))
    }

    pub fn bool(b:bool) -> Doc {
        let res = if b { "true" } else { "false" };
        Text(String::from_str(res))
    }

    pub fn to_string(&self, w:uint) -> String {
        let mut strs = best(w, Vec::new(), self.clone());
        strs.reverse();
        strs.push(String::from_str("\n"));
        strs.concat()
    }
}
<|endoftext|>


<commit_before>use std::net::{SocketAddr, ToSocketAddrs};
use std::iter::Iterator;
use std::io::Result as IoResult;
use std::sync::Arc;
use mioco;
use mioco::tcp::TcpListener;
use request::Request;
use response::Response;
use connection::{Connection, ConnResult};

macro_rules! try_com {
    ($com: expr, err => $errexpr: expr) => {
        match $com {
            ConnResult::Ok(x) => x,
            ConnResult::ZeroPacket => return Ok(()),
            ConnResult::ParseErr(_) => $errexpr,
            ConnResult::IoError(_) => $errexpr,
        }
    }
}

///
/// HTTP Proxy Server implemenation
///
pub struct RainyProxy {
    pub addr: SocketAddr,
}

impl RainyProxy {
    pub fn new<T: ToSocketAddrs>(addr: &T) -> RainyProxy {
        let sock = addr.to_socket_addrs().unwrap().next().unwrap();

        RainyProxy { addr: sock }
    }

    pub fn serve(&self) -> IoResult<()> {
        self.serve_custom(|_| None, |_| {})
    }

    pub fn serve_custom<RQ, RS>(&self, on_request: RQ, on_response: RS) -> IoResult<()>
        where RQ: Fn(&mut Request) -> Option<Response> + 'static + Send + Sync,
              RS: Fn(&mut Response) + 'static + Send + Sync
    {
        let listener = try!(TcpListener::bind(&self.addr));
        debug!("Proxy server listen at {}", &self.addr);

        let handlers = Arc::new((on_request, on_response));
        mioco::start(move || -> IoResult<()> {
            for _ in 0..mioco::thread_num() {
                let _handlers = handlers.clone();
                let listener: TcpListener = try!(listener.try_clone());

                mioco::spawn(move || -> IoResult<()> {
                    loop {
                        let __handlers = _handlers.clone();
                        let mut src_conn = Connection::new(try!(listener.accept()));

                        mioco::spawn(move || -> IoResult<()> {
                            let (on_request, on_response) = (&__handlers.0, &__handlers.1);

                            // recieve source request
                            let mut request = try_com!(src_conn.recieve::<Request>(), err=>return
                            Ok(()));
                            debug!("receive from client.");

                            // connect to the server
                            let mut dest_conn: Connection = {
                                let (protocol, host, port, path) = request.disassembly_path();
                                match Connection::from(host, &port) {
                                    Some(conn) => conn,
                                    None => return Ok(()),
                                }
                            };
                            debug!("connect to server.");

                            let mut user_res = on_request(&mut request);

                            // send request to destination host
                            try_com!(dest_conn.send(&request), err=>return Ok(()));

                            debug!("send to server.");

                            // recieve destination response
                            let mut response = match user_res {
                                Some(r) => r,
                                None => {
                                    try_com!(dest_conn.recieve::<Response>(), err=>return Ok(()))
                                }
                            };

                            debug!("recieved from server.");

                            on_response(&mut response);

                            // send response to source host
                            try_com!(src_conn.send(&response), err=>return Ok(()));

                            debug!("send to client");

                            Ok(())
                        });
                    }
                });
            }

            Ok(())
        });
        Ok(())
    }
}
<commit_msg>modify the flow of getting response.<commit_after>use std::net::{SocketAddr, ToSocketAddrs};
use std::iter::Iterator;
use std::io::Result as IoResult;
use std::sync::Arc;
use mioco;
use mioco::tcp::TcpListener;
use request::Request;
use response::Response;
use connection::{Connection, ConnResult};

macro_rules! try_com {
    ($com: expr, err => $errexpr: expr) => {
        match $com {
            ConnResult::Ok(x) => x,
            ConnResult::ZeroPacket => return Ok(()),
            ConnResult::ParseErr(_) => $errexpr,
            ConnResult::IoError(_) => $errexpr,
        }
    }
}

///
/// HTTP Proxy Server implemenation
///
pub struct RainyProxy {
    pub addr: SocketAddr,
}

impl RainyProxy {
    pub fn new<T: ToSocketAddrs>(addr: &T) -> RainyProxy {
        let sock = addr.to_socket_addrs().unwrap().next().unwrap();

        RainyProxy { addr: sock }
    }

    pub fn serve(&self) -> IoResult<()> {
        self.serve_custom(|_| None, |_| {})
    }

    pub fn serve_custom<RQ, RS>(&self, on_request: RQ, on_response: RS) -> IoResult<()>
        where RQ: Fn(&mut Request) -> Option<Response> + 'static + Send + Sync,
              RS: Fn(&mut Response) + 'static + Send + Sync
    {
        let listener = try!(TcpListener::bind(&self.addr));
        debug!("Proxy server listen at {}", &self.addr);

        let handlers = Arc::new((on_request, on_response));
        mioco::start(move || -> IoResult<()> {
            for _ in 0..mioco::thread_num() {
                let _handlers = handlers.clone();
                let listener: TcpListener = try!(listener.try_clone());

                mioco::spawn(move || -> IoResult<()> {
                    loop {
                        let __handlers = _handlers.clone();
                        let mut src_conn = Connection::new(try!(listener.accept()));

                        mioco::spawn(move || -> IoResult<()> {
                            let (on_request, on_response) = (&__handlers.0, &__handlers.1);

                            debug!("receive from the source host.");
                            let mut request = try_com!(src_conn.recieve::<Request>(), err=>return
                            Ok(()));

                            let mut response = match on_request(&mut request) {
                                Some(usr_req) => usr_req,
                                None => {
                                    debug!("connect to the destination host.");
                                    let mut dest_conn: Connection = {
                                        let (protocol, host, port, path) =
                                            request.disassembly_path();
                                        match Connection::from(host, &port) {
                                            Some(conn) => conn,
                                            None => return Ok(()),
                                        }
                                    };

                                    debug!("send to the destination host.");
                                    try_com!(dest_conn.send(&request), err=>return Ok(()));

                                    debug!("recieved from the destination host.");
                                    try_com!(dest_conn.recieve::<Response>(), err=>return Ok(()))
                                }
                            };

                            on_response(&mut response);

                            debug!("send to the surce host.");
                            try_com!(src_conn.send(&response), err=>return Ok(()));

                            Ok(())
                        });
                    }
                });
            }

            Ok(())
        });
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::hash::BuildHasherDefault;
use std::io::Read;
use std::iter::Peekable;
use std::time::{Duration, UNIX_EPOCH};
use chrono::DateTime;
use fnv::FnvHasher;
use rustc_serialize::base64::FromBase64;
use xml::reader::{EventReader, ParserConfig, Result as XmlResult, XmlEvent};

use plist::Plist;
use result::{Result, Error};

fn xml_event<R: Iterator<Item = XmlResult<XmlEvent>>, P>(input: &mut Peekable<R>,
                                                         mut predicate: P)
                                                         -> Result<()>
    where P: FnMut(&XmlEvent) -> Option<bool>
{
    match input.next() {
        Some(Ok(e)) => {
            match predicate(&e) {
                Some(true) => Ok(()),
                Some(false) => Err(Error::UnexpectedXmlEvent(e)),
                None => xml_event(input, predicate),
            }
        }
        Some(Err(e)) => Err(Error::from(e)),
        None => Err(Error::UnexpectedXmlEof),
    }
}

fn xml_start<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>,
                                                      local_name: &str)
                                                      -> Result<()> {
    xml_event(input, |e| {
        match *e {
            XmlEvent::StartElement { ref name, .. } => {
                Some(if &name.local_name[..] == local_name {
                    true
                } else {
                    false
                })
            }
            XmlEvent::Characters(ref _string) => None,
            _ => Some(false),
        }
    })
}

fn xml_end<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>,
                                                    local_name: &str)
                                                    -> Result<String> {
    let mut string = None;
    try!(xml_event(input, |e| {
        match *e {
            XmlEvent::EndElement { ref name } => {
                Some(if &name.local_name[..] == local_name {
                    true
                } else {
                    false
                })
            }
            XmlEvent::Characters(ref s) => {
                // TODO: Don't clone
                string = Some(s.clone());
                None
            }
            _ => Some(false),
        }
    }));

    match string {
        Some(s) => Ok(s),
        None => Ok("".to_string()),
    }
}

fn xml_content<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>,
                                                        local_name: &str)
                                                        -> Result<String> {
    try!(xml_start(input, local_name));
    xml_end(input, local_name)
}

fn xml_boolean<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    match input.next() {
        Some(Ok(e)) => {
            match e {
                XmlEvent::StartElement { ref name, .. } => {
                    match &name.local_name[..] {
                        "true" => {
                            try!(xml_end(input, "true"));
                            return Ok(Plist::Boolean(true));
                        }
                        "false" => {
                            try!(xml_end(input, "false"));
                            return Ok(Plist::Boolean(false));
                        }
                        _ => (),
                    }
                }
                XmlEvent::Characters(ref _string) => return xml_boolean(input),
                _ => (),
            };
            Err(Error::UnexpectedXmlEvent(e))
        }
        Some(Err(e)) => Err(Error::from(e)),
        None => Err(Error::UnexpectedXmlEof),
    }
}

fn xml_integer<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    let string = try!(xml_content(input, "integer"));
    let integer = try!(i64::from_str_radix(string.as_ref(), 10));
    Ok(Plist::Integer(integer))
}

fn xml_real<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    let string = try!(xml_content(input, "real"));
    let real = try!(string.parse());
    Ok(Plist::Real(real))
}

fn xml_date<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    let string = try!(xml_content(input, "date"));
    let secs = try!(DateTime::parse_from_rfc3339(string.as_ref())).timestamp() as u64;
    Ok(Plist::DateTime(UNIX_EPOCH + Duration::from_secs(secs)))
}

fn xml_data<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    let string = try!(xml_content(input, "data"));
    let stripped = string.split_whitespace()
        .fold(String::with_capacity(string.len()), |mut x, y| {
            x.push_str(y);
            x
        });
    Ok(Plist::Data(try!(stripped.from_base64())))
}

fn xml_string<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    Ok(Plist::String(try!(xml_content(input, "string"))))
}

fn xml_array<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    try!(xml_start(input, "array"));

    let mut array = Vec::new();
    loop {
        match xml_object(input) {
            Ok(o) => array.push(o),
            Err(Error::UnexpectedXmlEvent(e)) => {
                let valid = if let XmlEvent::EndElement { ref name } = e {
                    &name.local_name[..] == "array"
                } else {
                    false
                };
                if valid {
                    break;
                } else {
                    return Err(Error::UnexpectedXmlEvent(e));
                }
            }
            Err(e) => return Err(e),
        };
    }

    Ok(Plist::Array(array))
}

fn xml_dict<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    try!(xml_start(input, "dict"));

    let fnv = BuildHasherDefault::<FnvHasher>::default();
    let mut dict = HashMap::with_hasher(fnv);
    loop {
        match xml_content(input, "key") {
            Ok(key) => {
                let value = try!(xml_object(input));
                dict.insert(key, value);
            }
            Err(Error::UnexpectedXmlEvent(e)) => {
                let valid = if let XmlEvent::EndElement { ref name } = e {
                    &name.local_name[..] == "dict"
                } else {
                    false
                };
                if valid {
                    break;
                } else {
                    return Err(Error::UnexpectedXmlEvent(e));
                }
            }
            Err(e) => return Err(e),
        };
    }

    Ok(Plist::Dict(dict))
}

fn xml_object<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    let object_func: Option<fn(&mut Peekable<R>) -> Result<Plist>> = match input.peek() {
        Some(&Ok(XmlEvent::StartElement { ref name, .. })) => {
            Some(match &name.local_name[..] {
                "true" => xml_boolean,
                "false" => xml_boolean,
                "integer" => xml_integer,
                "real" => xml_real,
                "date" => xml_date,
                "data" => xml_data,
                "string" => xml_string,
                "array" => xml_array,
                "dict" => xml_dict,
                s => return Err(Error::XmlObjectNotSupported(s.to_string())),
            })
        }
        _ => None,
    };

    if let Some(func) = object_func {
        return func(input);
    }

    match input.next() {
        Some(Ok(XmlEvent::Characters(_string))) => xml_object(input),
        Some(Ok(e)) => Err(Error::UnexpectedXmlEvent(e)),
        Some(Err(e)) => Err(Error::from(e)),
        None => Err(Error::UnexpectedXmlEof),
    }
}

pub fn from_xml_reader<R: Read>(input: &mut R) -> Result<Plist> {
    let config = ParserConfig {
        trim_whitespace: false,
        whitespace_to_characters: true,
        cdata_to_characters: false,
        ignore_comments: true,
        coalesce_characters: true,
    };
    let mut events = EventReader::new_with_config(input, config).into_iter().peekable();

    try!(xml_event(&mut events, |e| {
        Some(if let &XmlEvent::StartDocument { .. } = e {
            true
        } else {
            false
        })
    }));
    try!(xml_start(&mut events, "plist"));
    let object = try!(xml_object(&mut events));
    try!(xml_end(&mut events, "plist"));
    Ok(object)
}
<commit_msg>Remove superfluous code<commit_after>use std::collections::HashMap;
use std::hash::BuildHasherDefault;
use std::io::Read;
use std::iter::Peekable;
use std::time::{Duration, UNIX_EPOCH};
use chrono::DateTime;
use fnv::FnvHasher;
use rustc_serialize::base64::FromBase64;
use xml::reader::{EventReader, ParserConfig, Result as XmlResult, XmlEvent};

use plist::Plist;
use result::{Result, Error};

fn xml_event<R: Iterator<Item = XmlResult<XmlEvent>>, P>(input: &mut Peekable<R>,
                                                         mut predicate: P)
                                                         -> Result<()>
    where P: FnMut(&XmlEvent) -> Option<bool>
{
    match input.next() {
        Some(Ok(e)) => {
            match predicate(&e) {
                Some(true) => Ok(()),
                Some(false) => Err(Error::UnexpectedXmlEvent(e)),
                None => xml_event(input, predicate),
            }
        }
        Some(Err(e)) => Err(Error::from(e)),
        None => Err(Error::UnexpectedXmlEof),
    }
}

fn xml_start<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>,
                                                      local_name: &str)
                                                      -> Result<()> {
    xml_event(input, |e| {
        match *e {
            XmlEvent::StartElement { ref name, .. } => Some(&name.local_name[..] == local_name),
            XmlEvent::Characters(ref _string) => None,
            _ => Some(false),
        }
    })
}

fn xml_end<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>,
                                                    local_name: &str)
                                                    -> Result<String> {
    let mut string = None;
    try!(xml_event(input, |e| {
        match *e {
            XmlEvent::EndElement { ref name } => Some(&name.local_name[..] == local_name),
            XmlEvent::Characters(ref s) => {
                // TODO: Don't clone
                string = Some(s.clone());
                None
            }
            _ => Some(false),
        }
    }));

    match string {
        Some(s) => Ok(s),
        None => Ok("".to_string()),
    }
}

fn xml_content<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>,
                                                        local_name: &str)
                                                        -> Result<String> {
    try!(xml_start(input, local_name));
    xml_end(input, local_name)
}

fn xml_boolean<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    match input.next() {
        Some(Ok(e)) => {
            match e {
                XmlEvent::StartElement { ref name, .. } => {
                    match &name.local_name[..] {
                        "true" => {
                            try!(xml_end(input, "true"));
                            return Ok(Plist::Boolean(true));
                        }
                        "false" => {
                            try!(xml_end(input, "false"));
                            return Ok(Plist::Boolean(false));
                        }
                        _ => (),
                    }
                }
                XmlEvent::Characters(ref _string) => return xml_boolean(input),
                _ => (),
            };
            Err(Error::UnexpectedXmlEvent(e))
        }
        Some(Err(e)) => Err(Error::from(e)),
        None => Err(Error::UnexpectedXmlEof),
    }
}

fn xml_integer<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    let string = try!(xml_content(input, "integer"));
    let integer = try!(i64::from_str_radix(string.as_ref(), 10));
    Ok(Plist::Integer(integer))
}

fn xml_real<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    let string = try!(xml_content(input, "real"));
    let real = try!(string.parse());
    Ok(Plist::Real(real))
}

fn xml_date<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    let string = try!(xml_content(input, "date"));
    let secs = try!(DateTime::parse_from_rfc3339(string.as_ref())).timestamp() as u64;
    Ok(Plist::DateTime(UNIX_EPOCH + Duration::from_secs(secs)))
}

fn xml_data<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    let string = try!(xml_content(input, "data"));
    let stripped = string.split_whitespace()
        .fold(String::with_capacity(string.len()), |mut x, y| {
            x.push_str(y);
            x
        });
    Ok(Plist::Data(try!(stripped.from_base64())))
}

fn xml_string<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    Ok(Plist::String(try!(xml_content(input, "string"))))
}

fn xml_array<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    try!(xml_start(input, "array"));

    let mut array = Vec::new();
    loop {
        match xml_object(input) {
            Ok(o) => array.push(o),
            Err(Error::UnexpectedXmlEvent(e)) => {
                let valid = if let XmlEvent::EndElement { ref name } = e {
                    &name.local_name[..] == "array"
                } else {
                    false
                };
                if valid {
                    break;
                } else {
                    return Err(Error::UnexpectedXmlEvent(e));
                }
            }
            Err(e) => return Err(e),
        };
    }

    Ok(Plist::Array(array))
}

fn xml_dict<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    try!(xml_start(input, "dict"));

    let fnv = BuildHasherDefault::<FnvHasher>::default();
    let mut dict = HashMap::with_hasher(fnv);
    loop {
        match xml_content(input, "key") {
            Ok(key) => {
                let value = try!(xml_object(input));
                dict.insert(key, value);
            }
            Err(Error::UnexpectedXmlEvent(e)) => {
                let valid = if let XmlEvent::EndElement { ref name } = e {
                    &name.local_name[..] == "dict"
                } else {
                    false
                };
                if valid {
                    break;
                } else {
                    return Err(Error::UnexpectedXmlEvent(e));
                }
            }
            Err(e) => return Err(e),
        };
    }

    Ok(Plist::Dict(dict))
}

fn xml_object<R: Iterator<Item = XmlResult<XmlEvent>>>(input: &mut Peekable<R>) -> Result<Plist> {
    let object_func: Option<fn(&mut Peekable<R>) -> Result<Plist>> = match input.peek() {
        Some(&Ok(XmlEvent::StartElement { ref name, .. })) => {
            Some(match &name.local_name[..] {
                "true" => xml_boolean,
                "false" => xml_boolean,
                "integer" => xml_integer,
                "real" => xml_real,
                "date" => xml_date,
                "data" => xml_data,
                "string" => xml_string,
                "array" => xml_array,
                "dict" => xml_dict,
                s => return Err(Error::XmlObjectNotSupported(s.to_string())),
            })
        }
        _ => None,
    };

    if let Some(func) = object_func {
        return func(input);
    }

    match input.next() {
        Some(Ok(XmlEvent::Characters(_string))) => xml_object(input),
        Some(Ok(e)) => Err(Error::UnexpectedXmlEvent(e)),
        Some(Err(e)) => Err(Error::from(e)),
        None => Err(Error::UnexpectedXmlEof),
    }
}

pub fn from_xml_reader<R: Read>(input: &mut R) -> Result<Plist> {
    let config = ParserConfig {
        trim_whitespace: false,
        whitespace_to_characters: true,
        cdata_to_characters: false,
        ignore_comments: true,
        coalesce_characters: true,
    };
    let mut events = EventReader::new_with_config(input, config).into_iter().peekable();

    try!(xml_event(&mut events, |e| {
        Some(if let &XmlEvent::StartDocument { .. } = e {
            true
        } else {
            false
        })
    }));
    try!(xml_start(&mut events, "plist"));
    let object = try!(xml_object(&mut events));
    try!(xml_end(&mut events, "plist"));
    Ok(object)
}
<|endoftext|>


<commit_before>/* Copyright (c) 2016
 * Jeff Nettleton
 *
 * Licensed under the MIT license (http://opensource.org/licenses/MIT). This
 * file may not be copied, modified, or distributed except according to those
 * terms
 */

extern crate regex;

use std::collections::HashMap;
use regex::Regex;

use request::*;
use response::*;

// The various types of parameters that can be contained in a URI.
#[derive(PartialEq, Eq, Hash, Debug)]
enum ParamType {
    Integer,
    Unsigned,
    String,
    Float,
    Path,
}

/// This struct represents a route definition. It is only necessary for
/// use internally.
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub struct RouteDef {
    pub pathdef: String,
    pub method:  Method,
}

/// This struct defines a route or endpoint.
pub struct Route {
    matcher:     Regex,
    method:      Method,
    params:      HashMap<String, ParamType>,
    pub handler: fn(&Request) -> Response,
}

impl Route {
    /// Create a new Route. This function is called by the Canteen struct.
    pub fn new(path: &str, method: Method, handler: fn(&Request) -> Response) -> Route {
        let re = Regex::new(r"^<(?:(int|uint|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$").unwrap();
        let parts: Vec<&str> = path.split('/').filter(|&s| s != "").collect();
        let mut matcher: String = String::from(r"^");
        let mut params: HashMap<String, ParamType> = HashMap::new();

        for part in parts {
            let chunk: String = match re.is_match(part) {
                true  => {
                    let mut rc = String::new();
                    let caps = re.captures(part).unwrap();
                    let param = caps.at(2).unwrap().clone();
                    let ptype: ParamType = match caps.at(1) {
                        Some(x)     => {
                            match x.as_ref() {
                                "int"   => ParamType::Integer,
                                "uint"  => ParamType::Unsigned,
                                "float" => ParamType::Float,
                                "path"  => ParamType::Path,
                                "str"   => ParamType::String,
                                _       => ParamType::String,

                            }
                        }
                        None        => ParamType::String,
                    };

                    let mstr: String = match ptype {
                        ParamType::String   => String::from(r"(?:[^/])+"),
                        ParamType::Integer  => String::from(r"-*[0-9]+"),
                        ParamType::Unsigned => String::from(r"[0-9]+"),
                        ParamType::Float    => String::from(r"-*[0-9]*[.]?[0-9]+"),
                        ParamType::Path     => String::from(r".+"),
                    };

                    rc.push_str("/(?P<");
                    rc.push_str(&param);
                    rc.push_str(">");
                    rc.push_str(&mstr);
                    rc.push_str(")");
                    params.insert(String::from(param), ptype);

                    rc
                },
                false => String::from("/") + part,
            };

            matcher.push_str(&chunk);
        }

        /* end the regex with an optional final slash and a string terminator */
        matcher.push_str("/?$");

        Route {
            matcher: Regex::new(&matcher).unwrap(),
            params:  params,
            method:  method,
            handler: handler,
        }
    }

    /// Check if this Route matches a given URI.
    pub fn is_match(&self, req: &Request) -> bool {
        self.matcher.is_match(&req.path) && self.method == req.method
    }

    /// Parse and extract the variables from a URI based on this Route's definition.
    pub fn parse(&self, path: &str) -> HashMap<String, String> {
        let mut params: HashMap<String, String> = HashMap::new();

        if self.matcher.is_match(&path) {
            let caps = self.matcher.captures(path).unwrap();
            for (param, _) in &self.params {
                params.insert(param.clone(), String::from(caps.name(&param).unwrap()));
            }
        }

        params
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use request::*;
    use utils;

    #[test]
    fn test_route_match_fail() {
        let rt = Route::new("/api/v1/foo/<int:foo_id>", Method::Get, utils::err_404);
        let mut req = Request::new();

        req.path = String::from("/api/v1/bar");
        req.method = Method::Get;

        assert_eq!(false, rt.is_match(&req));

        req.path = String::from("/api/v1/foo");
        req.method = Method::Post;

        assert_eq!(false, rt.is_match(&req));

        req.path = String::from("/api/v1/foo/asdf");
        req.method = Method::Get;

        assert_eq!(false, rt.is_match(&req));

        req.path = String::from("/api/v1/foo/123");
        req.method = Method::Get;

        assert_eq!(true, rt.is_match(&req));
    }

    #[test]
    fn test_route_match_simple() {
        let route = Route::new("/api/v1/foo/<foo_stuff>", Method::Get, utils::err_404);
        let parsed = route.parse("/api/v1/foo/blahblahblah");

        assert_eq!("blahblahblah", parsed.get("foo_stuff").unwrap());
    }

    #[test]
    fn test_route_match_single_int() {
        let route = Route::new("/api/v1/foo/<int:foo_id>", Method::Get, utils::err_404);
        let parsed = route.parse("/api/v1/foo/123");

        assert_eq!("123", parsed.get("foo_id").unwrap());
    }

    #[test]
    fn test_route_match_single_uint() {
        let route = Route::new("/api/v1/foo/<uint:foo_id>", Method::Get, utils::err_404);
        let parsed = route.parse("/api/v1/foo/123");
        let mut badreq = Request::new();

        badreq.method = Method::Get;
        badreq.path = String::from("/api/v1/foo/-123");

        assert_eq!("123", parsed.get("foo_id").unwrap());
        assert_eq!(false, route.is_match(&badreq));
    }

    #[test]
    fn test_route_match_single_str() {
        let rt = Route::new("/api/v1/foo/<str:foo_stuff>", Method::Get, utils::err_404);
        assert_eq!("blahblahblah", rt.parse("/api/v1/foo/blahblahblah").get("foo_stuff").unwrap());
    }

    #[test]
    fn test_route_match_many() {
        let rt = Route::new("/api/v1/foo/<int:foo_id>/bar/<str:bar>/baz/<int:baz_id>", Method::Get, utils::err_404);
        let rm = rt.parse("/api/v1/foo/123/bar/bar/baz/456");

        assert_eq!("123", rm.get("foo_id").unwrap());
        assert_eq!("bar", rm.get("bar").unwrap());
        assert_eq!("456", rm.get("baz_id").unwrap());
    }

    #[test]
    fn test_find_route_native_types() {
        let mut request = Request::new();
        let routes = vec![Route::new("/api/v1/foo/<int:foo_id>", Method::Get, utils::err_404),
                          Route::new("/api/v1/foo/<int:foo_id>/bar/<int:bar_id>", Method::Get, utils::err_404)];

        request.method = Method::Get;
        request.path = String::from("/api/v1/foo/42/bar/1234");

        for route in routes {
            match route.is_match(&request) {
                false => continue,
                true  => {
                    request.params = route.parse(&request.path);
                    break;
                },
            }
        }

        let foo_id: i32 = request.get("foo_id");
        let bar_id: i32 = request.get("bar_id");

        assert_eq!(42, foo_id);
        assert_eq!(1234, bar_id);
    }
}
<commit_msg>build our path match string components a little more sensibly<commit_after>/* Copyright (c) 2016
 * Jeff Nettleton
 *
 * Licensed under the MIT license (http://opensource.org/licenses/MIT). This
 * file may not be copied, modified, or distributed except according to those
 * terms
 */

extern crate regex;

use std::collections::HashMap;
use regex::Regex;

use request::*;
use response::*;

// The various types of parameters that can be contained in a URI.
#[derive(PartialEq, Eq, Hash, Debug)]
enum ParamType {
    Integer,
    Unsigned,
    String,
    Float,
    Path,
}

/// This struct represents a route definition. It is only necessary for
/// use internally.
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub struct RouteDef {
    pub pathdef: String,
    pub method:  Method,
}

/// This struct defines a route or endpoint.
pub struct Route {
    matcher:     Regex,
    method:      Method,
    params:      HashMap<String, ParamType>,
    pub handler: fn(&Request) -> Response,
}

impl Route {
    /// Create a new Route. This function is called by the Canteen struct.
    pub fn new(path: &str, method: Method, handler: fn(&Request) -> Response) -> Route {
        let re = Regex::new(r"^<(?:(int|uint|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$").unwrap();
        let parts: Vec<&str> = path.split('/').filter(|&s| s != "").collect();
        let mut matcher: String = String::from(r"^");
        let mut params: HashMap<String, ParamType> = HashMap::new();

        for part in parts {
            let chunk: String = match re.is_match(part) {
                true  => {
                    let caps = re.captures(part).unwrap();
                    let param = caps.at(2).unwrap().clone();
                    let ptype: ParamType = match caps.at(1) {
                        Some(x)     => {
                            match x.as_ref() {
                                "int"   => ParamType::Integer,
                                "uint"  => ParamType::Unsigned,
                                "float" => ParamType::Float,
                                "path"  => ParamType::Path,
                                "str"   => ParamType::String,
                                _       => ParamType::String,

                            }
                        }
                        None        => ParamType::String,
                    };

                    let mstr: String = match ptype {
                        ParamType::String   => String::from(r"(?:[^/])+"),
                        ParamType::Integer  => String::from(r"-*[0-9]+"),
                        ParamType::Unsigned => String::from(r"[0-9]+"),
                        ParamType::Float    => String::from(r"-*[0-9]*[.]?[0-9]+"),
                        ParamType::Path     => String::from(r".+"),
                    };

                    params.insert(String::from(param), ptype);

                    format!("/(?P<{}>{})", &param, &mstr)
                },
                false => String::from("/") + part,
            };

            matcher.push_str(&chunk);
        }

        /* end the regex with an optional final slash and a string terminator */
        matcher.push_str("/?$");

        Route {
            matcher: Regex::new(&matcher).unwrap(),
            params:  params,
            method:  method,
            handler: handler,
        }
    }

    /// Check if this Route matches a given URI.
    pub fn is_match(&self, req: &Request) -> bool {
        self.matcher.is_match(&req.path) && self.method == req.method
    }

    /// Parse and extract the variables from a URI based on this Route's definition.
    pub fn parse(&self, path: &str) -> HashMap<String, String> {
        let mut params: HashMap<String, String> = HashMap::new();

        if self.matcher.is_match(&path) {
            let caps = self.matcher.captures(path).unwrap();
            for (param, _) in &self.params {
                params.insert(param.clone(), String::from(caps.name(&param).unwrap()));
            }
        }

        params
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use request::*;
    use utils;

    #[test]
    fn test_route_match_fail() {
        let rt = Route::new("/api/v1/foo/<int:foo_id>", Method::Get, utils::err_404);
        let mut req = Request::new();

        req.path = String::from("/api/v1/bar");
        req.method = Method::Get;

        assert_eq!(false, rt.is_match(&req));

        req.path = String::from("/api/v1/foo");
        req.method = Method::Post;

        assert_eq!(false, rt.is_match(&req));

        req.path = String::from("/api/v1/foo/asdf");
        req.method = Method::Get;

        assert_eq!(false, rt.is_match(&req));

        req.path = String::from("/api/v1/foo/123");
        req.method = Method::Get;

        assert_eq!(true, rt.is_match(&req));
    }

    #[test]
    fn test_route_match_simple() {
        let route = Route::new("/api/v1/foo/<foo_stuff>", Method::Get, utils::err_404);
        let parsed = route.parse("/api/v1/foo/blahblahblah");

        assert_eq!("blahblahblah", parsed.get("foo_stuff").unwrap());
    }

    #[test]
    fn test_route_match_single_int() {
        let route = Route::new("/api/v1/foo/<int:foo_id>", Method::Get, utils::err_404);
        let parsed = route.parse("/api/v1/foo/123");

        assert_eq!("123", parsed.get("foo_id").unwrap());
    }

    #[test]
    fn test_route_match_single_uint() {
        let route = Route::new("/api/v1/foo/<uint:foo_id>", Method::Get, utils::err_404);
        let parsed = route.parse("/api/v1/foo/123");
        let mut badreq = Request::new();

        badreq.method = Method::Get;
        badreq.path = String::from("/api/v1/foo/-123");

        assert_eq!("123", parsed.get("foo_id").unwrap());
        assert_eq!(false, route.is_match(&badreq));
    }

    #[test]
    fn test_route_match_single_str() {
        let rt = Route::new("/api/v1/foo/<str:foo_stuff>", Method::Get, utils::err_404);
        assert_eq!("blahblahblah", rt.parse("/api/v1/foo/blahblahblah").get("foo_stuff").unwrap());
    }

    #[test]
    fn test_route_match_many() {
        let rt = Route::new("/api/v1/foo/<int:foo_id>/bar/<str:bar>/baz/<int:baz_id>", Method::Get, utils::err_404);
        let rm = rt.parse("/api/v1/foo/123/bar/bar/baz/456");

        assert_eq!("123", rm.get("foo_id").unwrap());
        assert_eq!("bar", rm.get("bar").unwrap());
        assert_eq!("456", rm.get("baz_id").unwrap());
    }

    #[test]
    fn test_find_route_native_types() {
        let mut request = Request::new();
        let routes = vec![Route::new("/api/v1/foo/<int:foo_id>", Method::Get, utils::err_404),
                          Route::new("/api/v1/foo/<int:foo_id>/bar/<int:bar_id>", Method::Get, utils::err_404)];

        request.method = Method::Get;
        request.path = String::from("/api/v1/foo/42/bar/1234");

        for route in routes {
            match route.is_match(&request) {
                false => continue,
                true  => {
                    request.params = route.parse(&request.path);
                    break;
                },
            }
        }

        let foo_id: i32 = request.get("foo_id");
        let bar_id: i32 = request.get("bar_id");

        assert_eq!(42, foo_id);
        assert_eq!(1234, bar_id);
    }
}
<|endoftext|>


<commit_before>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{decode, Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use token::{Token, ReservedWord};

pub struct ExpectPass {
    source: String,
    expected: Json,
    options: Option<Json>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

pub fn read_tests(path: &str) -> Vec<TestCase> {
    let mut f: File = File::open(path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s);
    parse_tests(&s)
}

pub fn parse_tests(src: &str) -> Vec<TestCase> {
    let data: Json = src.parse().unwrap();
    unimplemented!()
}
<commit_msg>huh. Vec doesn't have a map method?<commit_after>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{decode, Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use token::{Token, ReservedWord};

pub struct ExpectPass {
    source: String,
    expected: Json,
    options: Option<Json>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

fn parse_test(mut test: Json) -> TestCase {
    unimplemented!()
}

pub fn read_tests(path: &str) -> Vec<TestCase> {
    let mut f: File = File::open(path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s);
    parse_tests(&s)
}

pub fn parse_tests(src: &str) -> Vec<TestCase> {
    let data: Json = src.parse().unwrap();
    data.into_array()
        .map(parse_test)
}
<|endoftext|>


<commit_before>use std::io;
use std::iter::Map;
use std::io::BufReader;
use std::fs::File;

use serde_json;

use cgmath::*;
use shape::*;
use vec3d::Vec3d;
use vec3d::Rotatable;
use light::Light;

use color;
use color::Color;

#[derive(Serialize, Deserialize)]
pub struct Scene {
    shapes: Vec<Shape>,
    lights: Vec<Light>,
    camera_pos: Vec3d,
    camera_dir: Vec3d,
    camera_up: Vec3d,
    max_reflection: i32,
}

#[derive(Debug)]
pub enum CraycrayError {
    Io(io::Error),
    Serde(serde_json::Error),
}

impl Scene {
    pub fn new(camera_pos: Vec3d, camera_dir: Vec3d, camera_up: Vec3d) -> Scene {
        Scene {
            shapes: Vec::new(),
            lights: Vec::new(),
            camera_pos: camera_pos,
            camera_dir: camera_dir,
            camera_up: camera_up,
            max_reflection: 4,
        }
    }

    pub fn from_file(filename: &str) -> Result<Scene, CraycrayError> {
        File::open(filename)
            .map_err(CraycrayError::Io)
            .and_then(|f| serde_json::from_reader(BufReader::new(f)).map_err(CraycrayError::Serde))
    }

    pub fn add_shape(&mut self, s: Shape) {
        self.shapes.push(s);
    }

    pub fn step(&mut self) {
        // self.light.translate(&[1.0, 0.0, 0.0]);
    }

    pub fn mv_camera_fwd(&mut self) {
        self.camera_pos = self.camera_pos + self.camera_dir;
    }

    pub fn mv_camera_back(&mut self) {
        self.camera_pos = self.camera_pos - self.camera_dir;
    }

    pub fn rot_camera(&mut self, x_rot: f64, y_rot: f64) {
        // project camera_dir to X plane
        let mut x_proj = self.camera_dir;
        x_proj.y = 0.0;
        x_proj = x_proj.normalize();

        let angle = if x_proj.x < 0.0 {
            -Vec3d::new(0.0, 0.0, 1.0).dot(x_proj).acos()
        } else {
            Vec3d::new(0.0, 0.0, 1.0).dot(x_proj).acos()
        };

        self.camera_dir = self.camera_dir
            .rot_y(x_rot)
            .rot_y(-angle)
            .rot_x(y_rot)
            .rot_y(angle)
            .normalize();
    }

    /// Returns an iterator for a line at given resolution
    pub fn line_iter(&self, h: usize, v: usize, l: usize) -> LineIter {
        LineIter::new(self, h, v, l)
    }

    /// line_iter converted to (u8, u8, u8)
    pub fn line_iter_u8(&self,
                        h: usize,
                        v: usize,
                        l: usize)
                        -> Map<LineIter, fn(Color) -> (u8, u8, u8)> {
        self.line_iter(h, v, l).map(Color::col_to_u8)
    }

    // Recursively trace lines
    fn trace(&self, point: Vec3d, dir: Vec3d, depth: i32) -> Color {
        if depth >= self.max_reflection {
            return color::BLACK;
        }

        if let Some(intersect) = self.closest_q(point, dir) {
            let local = self.lights
                .iter()
                .map(|l| {
                         let (f_unit, dist) = l.feeler(intersect.point);
                         let direct_light = self.is_direct_light(intersect.point, f_unit, dist);
                         if direct_light {
                             phong(point, &intersect, l)
                         } else {
                             color::BLACK
                         }
                     })
                .sum::<Color>() + intersect.material.ambient_color;

            let tmp = (intersect.point - point).normalize();
            let reflection_dir = tmp - (intersect.normal * 2.0 * tmp.dot(intersect.normal));

            let reflected = self.trace(intersect.point, reflection_dir, depth + 1);

            local + (reflected * intersect.material.reflectivity)
        } else {
            color::BLACK
        }
    }

    // Is there anything on the path to the light
    fn is_direct_light(&self, point: Vec3d, dir: Vec3d, dl: f64) -> bool {
        !self.shapes
             .iter()
             .map(|&ref x| x.intersect_dist(point, dir))
             .any(|dist_opt| dist_opt.map_or(false, |i| i < dl))
    }

    // Checks against all objects and returns closest intersection
    fn closest_q(&self, point: Vec3d, dir: Vec3d) -> Option<Intersection> {
        let find_min_opt = |min, (s, op_val)| {
            match (min, op_val) {
                (Some((_, min_val)), Some(val)) if val < min_val => Some((s, val)),
                (None, Some(val)) => Some((s, val)),
                _ => min,
            }
        };

        self.shapes
            .iter()
            .map(|x| (x, x.intersect_dist(point, dir)))
            .fold(None, find_min_opt)
            .and_then(|(s, _)| s.intersect(point, dir))
    }
}

/// Iterator that iterates over a single line
pub struct LineIter<'a> {
    h_res: usize,
    x: usize,
    right_step: Vec3d,
    point: Vec3d,
    scene: &'a Scene,
}

impl<'a> LineIter<'a> {
    fn new(scene: &Scene, h: usize, v: usize, l: usize) -> LineIter {
        let left = scene.camera_dir.cross(scene.camera_up).normalize();
        let up = left.cross(scene.camera_dir).normalize();
        let mut point = left + up + scene.camera_dir;
        let right_step = left * (-2.0 / h as f64);
        let down_step = up * (-2.0 / v as f64);

        point = point + down_step * (l as f64);
        LineIter {
            h_res: h,
            x: 0,
            point: point,
            right_step: right_step,
            scene: scene,
        }
    }
}

impl<'a> Iterator for LineIter<'a> {
    type Item = Color;

    fn next(&mut self) -> Option<Self::Item> {
        if self.x >= self.h_res {
            return None;
        }
        self.x += 1;

        self.point = self.point + self.right_step;

        let c = self.scene
            .trace(self.scene.camera_pos, self.point.normalize(), 0);

        Some(c)
    }
}

// Calculate color with Phong model
fn phong(view_point: Vec3d, intersection: &Intersection, light: &Light) -> Color {
    let point_material = intersection.material;
    let light_pos = light.get_pos();
    let light_color = light.get_color();

    let mut d = (light_pos - intersection.point)
        .normalize()
        .dot(intersection.normal);

    if d < 0.0 {
        d = 0.0;
    }

    let v = (view_point - intersection.point).normalize();
    let lt = (light_pos - intersection.point).normalize();
    let r = intersection.normal * (2.0 * intersection.normal.dot(lt)) - lt;

    let mut s = r.dot(v).powf(point_material.shininess);
    if s < 0.0 {
        s = 0.0;
    }

    let diffuse = light_color * point_material.diffuse_color * d;
    let specular = light_color * point_material.specular_color * s;

    diffuse + specular
}
<commit_msg>Remove unnecessary ref<commit_after>use std::io;
use std::iter::Map;
use std::io::BufReader;
use std::fs::File;

use serde_json;

use cgmath::*;
use shape::*;
use vec3d::Vec3d;
use vec3d::Rotatable;
use light::Light;

use color;
use color::Color;

#[derive(Serialize, Deserialize)]
pub struct Scene {
    shapes: Vec<Shape>,
    lights: Vec<Light>,
    camera_pos: Vec3d,
    camera_dir: Vec3d,
    camera_up: Vec3d,
    max_reflection: i32,
}

#[derive(Debug)]
pub enum CraycrayError {
    Io(io::Error),
    Serde(serde_json::Error),
}

impl Scene {
    pub fn new(camera_pos: Vec3d, camera_dir: Vec3d, camera_up: Vec3d) -> Scene {
        Scene {
            shapes: Vec::new(),
            lights: Vec::new(),
            camera_pos: camera_pos,
            camera_dir: camera_dir,
            camera_up: camera_up,
            max_reflection: 4,
        }
    }

    pub fn from_file(filename: &str) -> Result<Scene, CraycrayError> {
        File::open(filename)
            .map_err(CraycrayError::Io)
            .and_then(|f| serde_json::from_reader(BufReader::new(f)).map_err(CraycrayError::Serde))
    }

    pub fn add_shape(&mut self, s: Shape) {
        self.shapes.push(s);
    }

    pub fn step(&mut self) {
        // self.light.translate(&[1.0, 0.0, 0.0]);
    }

    pub fn mv_camera_fwd(&mut self) {
        self.camera_pos = self.camera_pos + self.camera_dir;
    }

    pub fn mv_camera_back(&mut self) {
        self.camera_pos = self.camera_pos - self.camera_dir;
    }

    pub fn rot_camera(&mut self, x_rot: f64, y_rot: f64) {
        // project camera_dir to X plane
        let mut x_proj = self.camera_dir;
        x_proj.y = 0.0;
        x_proj = x_proj.normalize();

        let angle = if x_proj.x < 0.0 {
            -Vec3d::new(0.0, 0.0, 1.0).dot(x_proj).acos()
        } else {
            Vec3d::new(0.0, 0.0, 1.0).dot(x_proj).acos()
        };

        self.camera_dir = self.camera_dir
            .rot_y(x_rot)
            .rot_y(-angle)
            .rot_x(y_rot)
            .rot_y(angle)
            .normalize();
    }

    /// Returns an iterator for a line at given resolution
    pub fn line_iter(&self, h: usize, v: usize, l: usize) -> LineIter {
        LineIter::new(self, h, v, l)
    }

    /// line_iter converted to (u8, u8, u8)
    pub fn line_iter_u8(&self,
                        h: usize,
                        v: usize,
                        l: usize)
                        -> Map<LineIter, fn(Color) -> (u8, u8, u8)> {
        self.line_iter(h, v, l).map(Color::col_to_u8)
    }

    // Recursively trace lines
    fn trace(&self, point: Vec3d, dir: Vec3d, depth: i32) -> Color {
        if depth >= self.max_reflection {
            return color::BLACK;
        }

        if let Some(intersect) = self.closest_q(point, dir) {
            let local = self.lights
                .iter()
                .map(|l| {
                         let (f_unit, dist) = l.feeler(intersect.point);
                         let direct_light = self.is_direct_light(intersect.point, f_unit, dist);
                         if direct_light {
                             phong(point, &intersect, l)
                         } else {
                             color::BLACK
                         }
                     })
                .sum::<Color>() + intersect.material.ambient_color;

            let tmp = (intersect.point - point).normalize();
            let reflection_dir = tmp - (intersect.normal * 2.0 * tmp.dot(intersect.normal));

            let reflected = self.trace(intersect.point, reflection_dir, depth + 1);

            local + (reflected * intersect.material.reflectivity)
        } else {
            color::BLACK
        }
    }

    // Is there anything on the path to the light
    fn is_direct_light(&self, point: Vec3d, dir: Vec3d, dl: f64) -> bool {
        !self.shapes
             .iter()
             .map(|x| x.intersect_dist(point, dir))
             .any(|dist_opt| dist_opt.map_or(false, |i| i < dl))
    }

    // Checks against all objects and returns closest intersection
    fn closest_q(&self, point: Vec3d, dir: Vec3d) -> Option<Intersection> {
        let find_min_opt = |min, (s, op_val)| {
            match (min, op_val) {
                (Some((_, min_val)), Some(val)) if val < min_val => Some((s, val)),
                (None, Some(val)) => Some((s, val)),
                _ => min,
            }
        };

        self.shapes
            .iter()
            .map(|x| (x, x.intersect_dist(point, dir)))
            .fold(None, find_min_opt)
            .and_then(|(s, _)| s.intersect(point, dir))
    }
}

/// Iterator that iterates over a single line
pub struct LineIter<'a> {
    h_res: usize,
    x: usize,
    right_step: Vec3d,
    point: Vec3d,
    scene: &'a Scene,
}

impl<'a> LineIter<'a> {
    fn new(scene: &Scene, h: usize, v: usize, l: usize) -> LineIter {
        let left = scene.camera_dir.cross(scene.camera_up).normalize();
        let up = left.cross(scene.camera_dir).normalize();
        let mut point = left + up + scene.camera_dir;
        let right_step = left * (-2.0 / h as f64);
        let down_step = up * (-2.0 / v as f64);

        point = point + down_step * (l as f64);
        LineIter {
            h_res: h,
            x: 0,
            point: point,
            right_step: right_step,
            scene: scene,
        }
    }
}

impl<'a> Iterator for LineIter<'a> {
    type Item = Color;

    fn next(&mut self) -> Option<Self::Item> {
        if self.x >= self.h_res {
            return None;
        }
        self.x += 1;

        self.point = self.point + self.right_step;

        let c = self.scene
            .trace(self.scene.camera_pos, self.point.normalize(), 0);

        Some(c)
    }
}

// Calculate color with Phong model
fn phong(view_point: Vec3d, intersection: &Intersection, light: &Light) -> Color {
    let point_material = intersection.material;
    let light_pos = light.get_pos();
    let light_color = light.get_color();

    let mut d = (light_pos - intersection.point)
        .normalize()
        .dot(intersection.normal);

    if d < 0.0 {
        d = 0.0;
    }

    let v = (view_point - intersection.point).normalize();
    let lt = (light_pos - intersection.point).normalize();
    let r = intersection.normal * (2.0 * intersection.normal.dot(lt)) - lt;

    let mut s = r.dot(v).powf(point_material.shininess);
    if s < 0.0 {
        s = 0.0;
    }

    let diffuse = light_color * point_material.diffuse_color * d;
    let specular = light_color * point_material.specular_color * s;

    diffuse + specular
}
<|endoftext|>


<commit_before>use std::borrow::IntoCow;
use syntax::ast::{Expr, Ident, Stmt};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::ptr::P;

use maud;

#[derive(Copy, PartialEq, Show)]
pub enum Escape {
    PassThru,
    Escape,
}

pub struct Renderer<'cx, 's: 'cx, 'o> {
    pub cx: &'cx mut ExtCtxt<'s>,
    stmts: &'o mut Vec<P<Stmt>>,
    w: Ident,
}

impl<'cx, 's, 'o> Renderer<'cx, 's, 'o> {
    pub fn with<F>(cx: &'cx mut ExtCtxt<'s>, f: F) -> P<Expr> where
        F: for<'o_> FnOnce(&mut Renderer<'cx, 's, 'o_>)
    {
        let mut stmts = vec![];
        let w = Ident::new(token::intern("w"));
        let cx = {
            let mut render = Renderer {
                cx: cx,
                stmts: &mut stmts,
                w: w,
            };
            f(&mut render);
            render.cx
        };
        quote_expr!(cx,
            ::maud::rt::make_markup(|&: $w: &mut ::std::fmt::Writer| -> Result<(), ::std::fmt::Error> {
                $stmts
                Ok(())
            }))
    }

    /// Push an expression statement, also wrapping it with `try!`.
    fn push(&mut self, expr: P<Expr>) {
        let stmt = self.make_stmt(expr);
        self.stmts.push(stmt);
    }

    /// Create an expression statement, also wrapping it with `try!`.
    fn make_stmt(&mut self, expr: P<Expr>) -> P<Stmt> {
        self.cx.stmt_expr(self.cx.expr_try(expr.span, expr))
    }

    /// Append a literal pre-escaped string.
    fn write(&mut self, s: &str) {
        let w = self.w;
        let expr = quote_expr!(self.cx, $w.write_str($s));
        self.push(expr);
    }

    /// Append a literal string, with the specified escaping method.
    pub fn string(&mut self, s: &str, escape: Escape) {
        let s = match escape {
            Escape::PassThru => s.into_cow(),
            Escape::Escape => maud::escape(s).into_cow(),
        };
        self.write(s.as_slice());
    }

    /// Append the result of an expression, with the specified escaping method.
    pub fn splice(&mut self, expr: P<Expr>, escape: Escape) {
        let w = self.w;
        let expr = match escape {
            Escape::PassThru =>
                quote_expr!(self.cx, ::maud::rt::write_fmt($w, $expr)),
            Escape::Escape =>
                quote_expr!(self.cx,
                    ::maud::rt::write_fmt(
                        &mut ::maud::rt::Escaper { inner: $w },
                        $expr)),
        };
        self.push(expr);
    }

    pub fn element_open_start(&mut self, name: &str) {
        self.write("<");
        self.write(name);
    }

    pub fn attribute_start(&mut self, name: &str) {
        self.write(" ");
        self.write(name);
        self.write("=\"");
    }

    pub fn attribute_empty(&mut self, name: &str) {
        self.write(" ");
        self.write(name);
    }

    pub fn attribute_empty_if(&mut self, name: &str, expr: P<Expr>) {
        let s: String = [" ", name].concat();
        let s = &s[];
        let w = self.w;
        let expr = quote_expr!(self.cx,
            if $expr {
                $w.write_str($s)
            } else {
                Ok(())
            });
        self.push(expr);
    }

    pub fn attribute_end(&mut self) {
        self.write("\"");
    }

    pub fn element_open_end(&mut self) {
        self.write(">");
    }

    pub fn element_close(&mut self, name: &str) {
        self.write("</");
        self.write(name);
        self.write(">");
    }
}
<commit_msg>Silence "unnecessary parentheses" warnings<commit_after>use std::borrow::IntoCow;
use syntax::ast::{Expr, ExprParen, Ident, Stmt};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::ptr::P;

use maud;

#[derive(Copy, PartialEq, Show)]
pub enum Escape {
    PassThru,
    Escape,
}

pub struct Renderer<'cx, 's: 'cx, 'o> {
    pub cx: &'cx mut ExtCtxt<'s>,
    stmts: &'o mut Vec<P<Stmt>>,
    w: Ident,
}

impl<'cx, 's, 'o> Renderer<'cx, 's, 'o> {
    pub fn with<F>(cx: &'cx mut ExtCtxt<'s>, f: F) -> P<Expr> where
        F: for<'o_> FnOnce(&mut Renderer<'cx, 's, 'o_>)
    {
        let mut stmts = vec![];
        let w = Ident::new(token::intern("w"));
        let cx = {
            let mut render = Renderer {
                cx: cx,
                stmts: &mut stmts,
                w: w,
            };
            f(&mut render);
            render.cx
        };
        quote_expr!(cx,
            ::maud::rt::make_markup(|&: $w: &mut ::std::fmt::Writer| -> Result<(), ::std::fmt::Error> {
                $stmts
                Ok(())
            }))
    }

    /// Push an expression statement, also wrapping it with `try!`.
    fn push(&mut self, expr: P<Expr>) {
        let stmt = self.make_stmt(expr);
        self.stmts.push(stmt);
    }

    /// Create an expression statement, also wrapping it with `try!`.
    fn make_stmt(&mut self, expr: P<Expr>) -> P<Stmt> {
        self.cx.stmt_expr(self.cx.expr_try(expr.span, expr))
    }

    /// Append a literal pre-escaped string.
    fn write(&mut self, s: &str) {
        let w = self.w;
        let expr = quote_expr!(self.cx, $w.write_str($s));
        self.push(expr);
    }

    /// Append a literal string, with the specified escaping method.
    pub fn string(&mut self, s: &str, escape: Escape) {
        let s = match escape {
            Escape::PassThru => s.into_cow(),
            Escape::Escape => maud::escape(s).into_cow(),
        };
        self.write(s.as_slice());
    }

    /// Append the result of an expression, with the specified escaping method.
    pub fn splice(&mut self, expr: P<Expr>, escape: Escape) {
        let w = self.w;
        let expr = match escape {
            Escape::PassThru =>
                quote_expr!(self.cx, ::maud::rt::write_fmt($w, $expr)),
            Escape::Escape =>
                quote_expr!(self.cx,
                    ::maud::rt::write_fmt(
                        &mut ::maud::rt::Escaper { inner: $w },
                        $expr)),
        };
        self.push(expr);
    }

    pub fn element_open_start(&mut self, name: &str) {
        self.write("<");
        self.write(name);
    }

    pub fn attribute_start(&mut self, name: &str) {
        self.write(" ");
        self.write(name);
        self.write("=\"");
    }

    pub fn attribute_empty(&mut self, name: &str) {
        self.write(" ");
        self.write(name);
    }

    pub fn attribute_empty_if(&mut self, name: &str, expr: P<Expr>) {
        let s: String = [" ", name].concat();
        let s = &s[];
        let w = self.w;
        // Silence "unnecessary parentheses" warnings
        let expr = match expr.node {
            ExprParen(ref inner) => inner.clone(),
            _ => expr.clone(),
        };
        let expr = quote_expr!(self.cx,
            if $expr {
                $w.write_str($s)
            } else {
                Ok(())
            });
        self.push(expr);
    }

    pub fn attribute_end(&mut self) {
        self.write("\"");
    }

    pub fn element_open_end(&mut self) {
        self.write(">");
    }

    pub fn element_close(&mut self, name: &str) {
        self.write("</");
        self.write(name);
        self.write(">");
    }
}
<|endoftext|>


<commit_before>//! Module for the dynamic state of the game.
//!
//! This module defines the `State` type and its entourage. The data needed to
//! run an RBattle game is split into three categories:
//!
//! - `State` holds all the significant varying state of a game. What changes as the game proceeds
//!   are the amount of goop in each node, and the outflows the user has chosen;
//!   these are the `State`.
//!
//! - The positions of nodes and their boundaries and the locations of goop
//!   sources are all fixed, and are part of the `Map`.
//!
//! - Interface elements enter hover and active states as the user mouses
//!   around, but those states are ephemeral; they are part of the `Mouse` type.
//!   When the user actually completes an interaction with an interface element,
//!   only then is the `State` affected.

use graph::Node;
use visible_graph::VisibleGraph;
use map::{Map, Player};
use std::rc::Rc;
use rand::{Rng, SeedableRng, XorShiftRng};

use std::iter::repeat;

/// The complete state of an RBattle game board.
#[derive(Clone)]
pub struct State<G: VisibleGraph> {
    /// The map being played on.
    pub map: Rc<Map<G>>,

    /// Which nodes are owned, and which are vacant. Indexed by node id.
    pub nodes: Vec<Option<OwnedNode>>,

    /// The random number generator used to drive the goop flow algorithm.
    rng: XorShiftRng,
}

/// The state of a node that is owned by some player.
#[derive(Debug, Clone)]
pub struct OwnedNode {
    /// The player who controls this node.
    pub player: Player,

    /// Which neighbors of this node it sends goop out to.
    pub outflows: Vec<Node>,

    /// How much goop this node holds. Ranges from 0 to MAX_GOOP.
    pub goop: usize,

}

pub const MAX_GOOP: usize = 15;

/// Return a pair of mutable references to the `i`'th and `j`'th elements of
/// `slice`, where `i != j`.
fn index_mut_pair<T>(slice: &mut [T], i: usize, j: usize) -> (&mut T, &mut T) {
    if i < j {
        let (left, right) = slice.split_at_mut(j);
        (&mut left[i], &mut right[0])
    } else if j < i {
        let (left, right) = slice.split_at_mut(i);
        (&mut right[0], &mut left[j])
    } else {
        panic!("can't borrow two mutable references to the same element");
    }
}

impl<G: VisibleGraph> State<G> {
    pub fn new(map: Rc<Map<G>>) -> State<G> {
        const SEED: [u32; 4] = [0xcd9d5eaa, 0xf04bc9a7, 0x4602cc70, 0x98d01ef9];
        let nodes = repeat(None).take(map.graph.nodes()).collect();
        State { map, nodes, rng: XorShiftRng::from_seed(SEED) }
    }

    /// Let one unit of goop flow through each outflow.
    ///
    /// There are algorithms for finding the flow through a graph precisely, but
    /// we need something simpler here. We just visit every outgoing edge in a
    /// random order, and propagate a unit of goop if the destination permits
    /// it.
    pub fn flow(&mut self) {
        // Build a vector of (from, to) pairs.
        let mut outflow_list = Vec::new();
        for node in 0..self.map.graph.nodes() {
            if let &Some(ref owned) = &self.nodes[node] {
                for &outflow in &owned.outflows {
                    outflow_list.push((node, outflow))
                }
            }
        }

        // Put the pairs in a random order.
        self.rng.shuffle(&mut outflow_list);

        while let Some((from_index, to_index)) = outflow_list.pop() {
            match index_mut_pair(&mut self.nodes, from_index, to_index) {
                // We shouldn't have generated a pair for an empty source, and
                // when we clear a node we're supposed to remove pairs from
                // `outflow` that originate there.
                (&mut None, _) => panic!("outflow from empty node"),

                // Source has no goop. No effect.
                (&mut Some(OwnedNode { goop: 0, .. }), _) => (),

                // Goop flowing into an unoccupied node. New player claims ownership.
                (&mut Some(OwnedNode { player, ref mut goop, .. }),
                 &mut ref mut to @ None) => {
                    *goop -= 1;
                    *to = Some(OwnedNode { player, outflows: vec![], goop: 1 });
                },

                // Goop flowing into a node occupied by the same player.
                (&mut Some(OwnedNode { player: from_player, goop: ref mut from_goop, .. }),
                 &mut Some(OwnedNode { player: to_player,   goop: ref mut to_goop, .. }))
                    if from_player == to_player =>
                {
                    if *from_goop > 0 && *to_goop < MAX_GOOP {
                        *from_goop -= 1;
                        *to_goop += 1;
                    }
                }

                // Goop flowing into a node occupied by another player, but
                // doesn't clear it. All outflow from destination stopped.
                (&mut Some(OwnedNode { goop: ref mut from_goop, .. }),
                 &mut Some(OwnedNode { outflows: ref mut to_outflows,
                                       goop:     ref mut to_goop, .. }))
                    if *to_goop > 1 =>
                {
                    *from_goop -= 1;
                    *to_goop -= 1;
                    to_outflows.clear();
                    // Since all outflow from `to` is cancelled, remove any
                    // pending pairs from `outflow_list`.
                    outflow_list.retain(|&(from, _)| from != to_index);
                },

                // Goop flowing into an occupied node, succeeds in clearing it.
                (&mut Some(OwnedNode { player, goop: ref mut from_goop, .. }),
                 &mut ref mut to) => {
                    *from_goop -= 1;
                    *to = Some(OwnedNode { player, outflows: vec![], goop: 0 });
                    // Since all outflow from `to` is cancelled, remove any
                    // pending pairs from `outflow_list`.
                    outflow_list.retain(|&(from, _)| from != to_index);
                }
            }
        }
    }

    /// Let sources generate new goop.
    pub fn generate_goop(&mut self) {
        for &source in &self.map.sources {
            match &mut self.nodes[source] {
                &mut None => panic!("source nodes should always be owned by someone"),
                &mut Some(OwnedNode { ref mut goop, .. }) => {
                    if *goop < MAX_GOOP {
                        *goop += 1;
                    }
                }
            }
        }
    }
}

/// Actions that can be taken on a `State`.
pub enum Action {
    /// Toggle the state of the given outflow.
    ToggleOutflow((Node, Node)),
}

<commit_msg>State: Add take_action method.<commit_after>//! Module for the dynamic state of the game.
//!
//! This module defines the `State` type and its entourage. The data needed to
//! run an RBattle game is split into three categories:
//!
//! - `State` holds all the significant varying state of a game. What changes as the game proceeds
//!   are the amount of goop in each node, and the outflows the user has chosen;
//!   these are the `State`.
//!
//! - The positions of nodes and their boundaries and the locations of goop
//!   sources are all fixed, and are part of the `Map`.
//!
//! - Interface elements enter hover and active states as the user mouses
//!   around, but those states are ephemeral; they are part of the `Mouse` type.
//!   When the user actually completes an interaction with an interface element,
//!   only then is the `State` affected.

use graph::Node;
use visible_graph::VisibleGraph;
use map::{Map, Player};
use std::rc::Rc;
use rand::{Rng, SeedableRng, XorShiftRng};

use std::iter::repeat;

/// The complete state of an RBattle game board.
#[derive(Clone)]
pub struct State<G: VisibleGraph> {
    /// The map being played on.
    pub map: Rc<Map<G>>,

    /// Which nodes are owned, and which are vacant. Indexed by node id.
    pub nodes: Vec<Option<OwnedNode>>,

    /// The random number generator used to drive the goop flow algorithm.
    rng: XorShiftRng,
}

/// The state of a node that is owned by some player.
#[derive(Debug, Clone)]
pub struct OwnedNode {
    /// The player who controls this node.
    pub player: Player,

    /// Which neighbors of this node it sends goop out to.
    pub outflows: Vec<Node>,

    /// How much goop this node holds. Ranges from 0 to MAX_GOOP.
    pub goop: usize,

}

pub const MAX_GOOP: usize = 15;

/// Return a pair of mutable references to the `i`'th and `j`'th elements of
/// `slice`, where `i != j`.
fn index_mut_pair<T>(slice: &mut [T], i: usize, j: usize) -> (&mut T, &mut T) {
    if i < j {
        let (left, right) = slice.split_at_mut(j);
        (&mut left[i], &mut right[0])
    } else if j < i {
        let (left, right) = slice.split_at_mut(i);
        (&mut right[0], &mut left[j])
    } else {
        panic!("can't borrow two mutable references to the same element");
    }
}

impl<G: VisibleGraph> State<G> {
    pub fn new(map: Rc<Map<G>>) -> State<G> {
        const SEED: [u32; 4] = [0xcd9d5eaa, 0xf04bc9a7, 0x4602cc70, 0x98d01ef9];
        let nodes = repeat(None).take(map.graph.nodes()).collect();
        State { map, nodes, rng: XorShiftRng::from_seed(SEED) }
    }

    /// Let one unit of goop flow through each outflow.
    ///
    /// There are algorithms for finding the flow through a graph precisely, but
    /// we need something simpler here. We just visit every outgoing edge in a
    /// random order, and propagate a unit of goop if the destination permits
    /// it.
    pub fn flow(&mut self) {
        // Build a vector of (from, to) pairs.
        let mut outflow_list = Vec::new();
        for node in 0..self.map.graph.nodes() {
            if let &Some(ref owned) = &self.nodes[node] {
                for &outflow in &owned.outflows {
                    outflow_list.push((node, outflow))
                }
            }
        }

        // Put the pairs in a random order.
        self.rng.shuffle(&mut outflow_list);

        while let Some((from_index, to_index)) = outflow_list.pop() {
            match index_mut_pair(&mut self.nodes, from_index, to_index) {
                // We shouldn't have generated a pair for an empty source, and
                // when we clear a node we're supposed to remove pairs from
                // `outflow` that originate there.
                (&mut None, _) => panic!("outflow from empty node"),

                // Source has no goop. No effect.
                (&mut Some(OwnedNode { goop: 0, .. }), _) => (),

                // Goop flowing into an unoccupied node. New player claims ownership.
                (&mut Some(OwnedNode { player, ref mut goop, .. }),
                 &mut ref mut to @ None) => {
                    *goop -= 1;
                    *to = Some(OwnedNode { player, outflows: vec![], goop: 1 });
                },

                // Goop flowing into a node occupied by the same player.
                (&mut Some(OwnedNode { player: from_player, goop: ref mut from_goop, .. }),
                 &mut Some(OwnedNode { player: to_player,   goop: ref mut to_goop, .. }))
                    if from_player == to_player =>
                {
                    if *from_goop > 0 && *to_goop < MAX_GOOP {
                        *from_goop -= 1;
                        *to_goop += 1;
                    }
                }

                // Goop flowing into a node occupied by another player, but
                // doesn't clear it. All outflow from destination stopped.
                (&mut Some(OwnedNode { goop: ref mut from_goop, .. }),
                 &mut Some(OwnedNode { outflows: ref mut to_outflows,
                                       goop:     ref mut to_goop, .. }))
                    if *to_goop > 1 =>
                {
                    *from_goop -= 1;
                    *to_goop -= 1;
                    to_outflows.clear();
                    // Since all outflow from `to` is cancelled, remove any
                    // pending pairs from `outflow_list`.
                    outflow_list.retain(|&(from, _)| from != to_index);
                },

                // Goop flowing into an occupied node, succeeds in clearing it.
                (&mut Some(OwnedNode { player, goop: ref mut from_goop, .. }),
                 &mut ref mut to) => {
                    *from_goop -= 1;
                    *to = Some(OwnedNode { player, outflows: vec![], goop: 0 });
                    // Since all outflow from `to` is cancelled, remove any
                    // pending pairs from `outflow_list`.
                    outflow_list.retain(|&(from, _)| from != to_index);
                }
            }
        }
    }

    /// Let sources generate new goop.
    pub fn generate_goop(&mut self) {
        for &source in &self.map.sources {
            match &mut self.nodes[source] {
                &mut None => panic!("source nodes should always be owned by someone"),
                &mut Some(OwnedNode { ref mut goop, .. }) => {
                    if *goop < MAX_GOOP {
                        *goop += 1;
                    }
                }
            }
        }
    }

    /// Apply `action` to this state.
    pub fn take_action(&mut self, action: Action) {
        println!("take_action({:?})", action);
        match action {
            Action::ToggleOutflow((from, to)) => {
                // This is really just a click on the shared boundary of the two
                // nodes; it doesn't express any particular desired direction.
                // Try to infer the user's intent from the situation.
                let (from, to) = match (&self.nodes[from], &self.nodes[to]) {
                    (&Some(_), &None) => (from, to),
                    (&None, &Some(_)) => (to, from),
                    _ => return
                };

                let outflows = &mut self.nodes[from].as_mut().unwrap().outflows;
                if outflows.contains(&to) {
                    outflows.retain(|&dest| dest != to);
                } else {
                    outflows.push(to);
                }
            }
        }
    }
}

/// Actions that can be taken on a `State`.
#[derive(Debug)]
pub enum Action {
    /// Toggle the state of the given outflow.
    ToggleOutflow((Node, Node)),
}

<|endoftext|>