<commit_before>//!Response writers.

use std;
use std::io::{self, Write};
use std::error;
use std::borrow::Cow;
use std::convert::From;
use std::str::{from_utf8, Utf8Error};
use std::string::{FromUtf8Error};

use hyper;
use hyper::header::{Headers, Header, HeaderFormat};
use hyper::net::Fresh;
use hyper::http::h1::HttpWriter;
use hyper::version::HttpVersion;

use anymap::AnyMap;

use StatusCode;

use filter::{FilterContext, ResponseFilter};
use filter::ResponseAction as Action;
use log::Log;

use Global;

///The result of a response action.
#[derive(Debug)]
pub enum Error {
    ///A response filter failed.
    Filter(String),

    ///There was an IO error.
    Io(io::Error)
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Error::Filter(ref desc) => write!(f, "filter error: {}", desc),
            Error::Io(ref e) => write!(f, "io error: {}", e)
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Filter(ref desc) => desc,
            Error::Io(ref e) => e.description()
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::Filter(_) => None,
            Error::Io(ref e) => Some(e)
        }
    }
}

///Unified representation of response data.
pub enum Data<'a> {
    ///Data in byte form.
    Bytes(Cow<'a, [u8]>),

    ///Data in string form.
    String(Cow<'a, str>)
}

impl<'a> Data<'a> {
    ///Borrow the content as a byte slice.
    pub fn as_bytes(&self) -> &[u8] {
        match self {
            &Data::Bytes(ref bytes) => bytes,
            &Data::String(ref string) => string.as_bytes(),
        }
    }

    ///Turns the content into a byte vector. Slices are copied.
    pub fn into_bytes(self) -> Vec<u8> {
        match self {
            Data::Bytes(bytes) => bytes.into_owned(),
            Data::String(string) => string.into_owned().into_bytes()
        }
    }

    ///Borrow the content as a UTF-8 string slice, if possible.
    pub fn as_string(&self) -> Result<&str, Utf8Error> {
        match self {
            &Data::Bytes(ref bytes) => from_utf8(bytes),
            &Data::String(ref string) => Ok(string),
        }
    }

    ///Turn the content into a UTF-8 string, if possible. Slices are copied.
    pub fn into_string(self) -> Result<String, FromUtf8Error> {
        match self {
            Data::Bytes(bytes) => String::from_utf8(bytes.into_owned()),
            Data::String(string) => Ok(string.into_owned())
        }
    }
}

impl<'a> Into<Data<'a>> for Vec<u8> {
    fn into(self) -> Data<'a> {
        Data::Bytes(Cow::Owned(self))
    }
}

impl<'a> Into<Data<'a>> for &'a [u8] {
    fn into(self) -> Data<'a> {
        Data::Bytes(Cow::Borrowed(self))
    }
}

impl<'a> Into<Data<'a>> for String {
    fn into(self) -> Data<'a> {
        Data::String(Cow::Owned(self))
    }
}

impl<'a> Into<Data<'a>> for &'a str {
    fn into(self) -> Data<'a> {
        Data::String(Cow::Borrowed(self))
    }
}

///An interface for setting HTTP status code and response headers, before data gets written to the client.
pub struct Response<'a, 'b> {
    headers: Option<&'a mut Headers>,

    status: Option<StatusCode>,

    version: Option<HttpVersion>,
    writer: Option<HttpWriter<&'a mut (io::Write + 'a)>>,
    filters: &'b Vec<Box<ResponseFilter>>,
    log: &'b (Log + 'b),
    global: &'b Global,
    filter_storage: Option<AnyMap>
}

impl<'a, 'b> Response<'a, 'b> {
    pub fn new(
        response: hyper::server::response::Response<'a>,
        filters: &'b Vec<Box<ResponseFilter>>,
        log: &'b Log,
        global: &'b Global
    ) -> Response<'a, 'b> {
        let (version, writer, status, headers) = response.deconstruct();
        Response {
            headers: Some(headers),
            status: Some(status),
            version: Some(version),
            writer: Some(writer),
            filters: filters,
            log: log,
            global: global,
            filter_storage: Some(AnyMap::new())
        }
    }

    ///Set HTTP status code. Ok (200) is default.
    pub fn set_status(&mut self, status: StatusCode) {
        self.status = Some(status);
    }

    ///Set a HTTP response header. Date, content type (text/plain) and server is automatically set.
    pub fn set_header<H: Header + HeaderFormat>(&mut self, header: H) {
        if let Some(ref mut headers) = self.headers {
            headers.set(header);
        }
    }

    ///Get a HTTP response header if set.
    pub fn get_header<H: Header + HeaderFormat>(&self) -> Option<&H> {
        self.headers.as_ref().and_then(|h| h.get::<H>())
    }

    ///Mutably borrow the filter storage. It can be used to communicate with
    ///the response filters.
    pub fn filter_storage(&mut self) -> &mut AnyMap {
        self.filter_storage.as_mut().expect("response used after drop")
    }

    ///Turn the `Response` into a `ResponseWriter` to allow the response body to be written.
    ///
    ///Status code and headers will be written to the client and `ResponseFilter::begin()`
    ///will be called on the registered response filters.
    pub fn into_writer(mut self) -> ResponseWriter<'a, 'b> {
        self.make_writer()
    }

    fn make_writer(&mut self) -> ResponseWriter<'a, 'b> {
        let mut write_queue = Vec::new();
        let mut header_result = (self.status.take().unwrap(), self.headers.take().unwrap(), Action::Next(None));

        for filter in self.filters {
            header_result = match header_result {
                (_, _, Action::SilentAbort) => break,
                (_, _, Action::Abort(_)) => break,
                (status, headers, r) => {
                    write_queue.push(r);

                    let filter_res = {
                        let filter_context = FilterContext {
                            storage: self.filter_storage(),
                            log: self.log,
                            global: self.global,
                        };
                        filter.begin(filter_context, status, headers)
                    };

                    match filter_res {
                        (status, Action::Abort(e)) => (status, headers, Action::Abort(e)),
                        (status, result) => {
                            let mut error = None;

                            write_queue = write_queue.into_iter().filter_map(|action| match action {
                                Action::Next(content) => {
                                    let filter_context = FilterContext {
                                        storage: self.filter_storage(),
                                        log: self.log,
                                        global: self.global,
                                    };
                                    Some(filter.write(filter_context, content))
                                },
                                Action::SilentAbort => None,
                                Action::Abort(e) => {
                                    error = Some(e);
                                    None
                                }
                            }).collect();

                            match error {
                                Some(e) => (status, headers, Action::Abort(e)),
                                None => (status, headers, result)
                            }
                        }
                    }
                }
            }
        }

        let writer = match header_result {
            (_, _, Action::Abort(e)) => Err(Error::Filter(e)),
            (status, headers, last_result) => {
                write_queue.push(last_result);

                let version = self.version.take().unwrap();
                let writer = self.writer.take().unwrap();
                let writer = hyper::server::response::Response::<Fresh>::construct(version, writer, status, headers).start();
                let mut writer = match writer {
                    Ok(writer) => Ok(writer),
                    Err(e) => Err(Error::Io(e))
                };

                for action in write_queue {
                    writer = match (action, writer) {
                        (Action::Next(Some(content)), Ok(mut writer)) => match writer.write_all(content.as_bytes()) {
                            Ok(_) => Ok(writer),
                            Err(e) => Err(Error::Io(e))
                        },
                        (Action::Abort(e), _) => Err(Error::Filter(e)),
                        (_, writer) => writer
                    };
                }

                writer
            }
        };

        ResponseWriter {
            writer: Some(writer),
            filters: self.filters,
            log: self.log,
            global: self.global,
            filter_storage: self.filter_storage.take().expect("response used after drop")
        }
    }
}

#[allow(unused_must_use)]
impl<'a, 'b> Drop for Response<'a, 'b> {
    ///Writes status code and headers and closes the connection.
    fn drop(&mut self) {
        if self.writer.is_some() {
            self.make_writer();
        }
    }
}

///An interface for writing to the response body.
pub struct ResponseWriter<'a, 'b> {
    writer: Option<Result<hyper::server::response::Response<'a, hyper::net::Streaming>, Error>>,
    filters: &'b Vec<Box<ResponseFilter>>,
    log: &'b (Log + 'b),
    global: &'b Global,
    filter_storage: AnyMap
}

impl<'a, 'b> ResponseWriter<'a, 'b> {

    ///Mutably borrow the filter storage. It can be used to communicate with
    ///the response filters.
    pub fn filter_storage(&mut self) -> &mut AnyMap {
        &mut self.filter_storage
    }

    ///Write response body data to the client.
    ///
    ///Any errors that occures while writing the data will be ignored. Use
    ///`try_send`, instead, to also get error information.
    #[allow(unused_must_use)]
    pub fn send<'d, Content: Into<Data<'d>>>(&mut self, content: Content) {
        self.try_send(content);
    }

    ///Write response body data to the client and receive the number of
    ///written bytes, or any error that occured.
    pub fn try_send<'d, Content: Into<Data<'d>>>(&mut self, content: Content) -> Result<usize, Error> {
        let mut writer = match self.writer {
            Some(Ok(ref mut writer)) => writer,
            None => return Err(Error::Io(io::Error::new(io::ErrorKind::BrokenPipe, "write after close"))),
            Some(Err(_)) => if let Some(Err(e)) = self.writer.take() {
                return Err(e);
            } else { unreachable!(); }
        };

        let mut filter_result = Action::next(Some(content));

        for filter in self.filters {
            filter_result = match filter_result {
                Action::Next(content) => {
                    let filter_context = FilterContext {
                        storage: &mut self.filter_storage,
                        log: self.log,
                        global: self.global,
                    };
                    filter.write(filter_context, content)
                },
                _ => break
            }
        }

        let write_result = match filter_result {
            Action::Next(Some(ref s)) => {
                let buf = s.as_bytes();
                match writer.write_all(buf) {
                    Ok(()) => Some(Ok(buf.len())),
                    Err(e) => Some(Err(e))
                }
            },
            _ => None
        };

        match write_result {
            Some(Ok(l)) => Ok(l),
            Some(Err(e)) => Err(Error::Io(e)),
            None => match filter_result {
                Action::Abort(e) => Err(Error::Filter(e)),
                Action::Next(None) => Ok(0),
                _ => unreachable!()
            }
        }
    }

    ///Finish writing the response and collect eventual errors.
    ///
    ///This is optional and will happen silently when the writer drops out of
    ///scope.
    pub fn end(mut self) -> Result<(), Error> {
        self.finish()
    }

    fn finish(&mut self) -> Result<(), Error> {
        let mut writer = try!(self.writer.take().expect("can only finish once"));
        let mut write_queue: Vec<Action> = Vec::new();

        for filter in self.filters {
            let mut error = None;
            write_queue = write_queue.into_iter().filter_map(|action| match action {
                Action::Next(content) => {
                    let filter_context = FilterContext {
                        storage: &mut self.filter_storage,
                        log: self.log,
                        global: self.global,
                    };
                    Some(filter.write(filter_context, content))
                },
                Action::SilentAbort => None,
                Action::Abort(e) => {
                    error = Some(e);
                    None
                }
            }).collect();

            match error {
                Some(e) => return Err(Error::Filter(e)),
                None => {
                    let filter_context = FilterContext {
                        storage: &mut self.filter_storage,
                        log: self.log,
                        global: self.global,
                    };
                    write_queue.push(filter.end(filter_context))
                }
            }
        }

        for action in write_queue {
            try!{
                match action {
                    Action::Next(Some(content)) => writer.write_all(content.as_bytes()),
                    Action::Abort(e) => return Err(Error::Filter(e)),
                    _ => Ok(())
                }
            }
        }

        writer.end().map_err(|e| Error::Io(e))
    }

    fn borrow_writer(&mut self) -> Result<&mut hyper::server::response::Response<'a, hyper::net::Streaming>, Error> {
        match self.writer {
            Some(Ok(ref mut writer)) => Ok(writer),
            None => Err(Error::Io(io::Error::new(io::ErrorKind::BrokenPipe, "write after close"))),
            Some(Err(_)) => if let Some(Err(e)) = self.writer.take() {
                Err(e)
            } else { unreachable!(); }
        }
    }
}

impl<'a, 'b> Write for ResponseWriter<'a, 'b> {
    fn write(&mut self, content: &[u8]) -> io::Result<usize> {
        response_to_io_result(self.try_send(content))
    }

    fn write_all(&mut self, content: &[u8]) -> io::Result<()> {
        self.write(content).map(|_| ())
    }

    fn flush(&mut self) -> io::Result<()> {
        let mut writer = try!(response_to_io_result(self.borrow_writer()));
        writer.flush()
    }
}

#[allow(unused_must_use)]
impl<'a, 'b> Drop for ResponseWriter<'a, 'b> {
    ///Finishes writing and closes the connection.
    fn drop(&mut self) {
        if self.writer.is_some() {
            self.finish();
        }
    }
}

fn response_to_io_result<T>(res:  Result<T, Error>) -> io::Result<T> {
    match res {
        Ok(v) => Ok(v),
        Err(Error::Io(e)) => Err(e),
        Err(e) => Err(io::Error::new(io::ErrorKind::Other, e))
    }
}<commit_msg>Don't deconstruct the Hyper Response in Response<commit_after>//!Response writers.

use std;
use std::io::{self, Write};
use std::error;
use std::borrow::Cow;
use std::convert::From;
use std::str::{from_utf8, Utf8Error};
use std::string::{FromUtf8Error};

use hyper;
use hyper::header::{Header, HeaderFormat};

use anymap::AnyMap;

use StatusCode;

use filter::{FilterContext, ResponseFilter};
use filter::ResponseAction as Action;
use log::Log;

use Global;

///The result of a response action.
#[derive(Debug)]
pub enum Error {
    ///A response filter failed.
    Filter(String),

    ///There was an IO error.
    Io(io::Error)
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Error::Filter(ref desc) => write!(f, "filter error: {}", desc),
            Error::Io(ref e) => write!(f, "io error: {}", e)
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Filter(ref desc) => desc,
            Error::Io(ref e) => e.description()
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::Filter(_) => None,
            Error::Io(ref e) => Some(e)
        }
    }
}

///Unified representation of response data.
pub enum Data<'a> {
    ///Data in byte form.
    Bytes(Cow<'a, [u8]>),

    ///Data in string form.
    String(Cow<'a, str>)
}

impl<'a> Data<'a> {
    ///Borrow the content as a byte slice.
    pub fn as_bytes(&self) -> &[u8] {
        match self {
            &Data::Bytes(ref bytes) => bytes,
            &Data::String(ref string) => string.as_bytes(),
        }
    }

    ///Turns the content into a byte vector. Slices are copied.
    pub fn into_bytes(self) -> Vec<u8> {
        match self {
            Data::Bytes(bytes) => bytes.into_owned(),
            Data::String(string) => string.into_owned().into_bytes()
        }
    }

    ///Borrow the content as a UTF-8 string slice, if possible.
    pub fn as_string(&self) -> Result<&str, Utf8Error> {
        match self {
            &Data::Bytes(ref bytes) => from_utf8(bytes),
            &Data::String(ref string) => Ok(string),
        }
    }

    ///Turn the content into a UTF-8 string, if possible. Slices are copied.
    pub fn into_string(self) -> Result<String, FromUtf8Error> {
        match self {
            Data::Bytes(bytes) => String::from_utf8(bytes.into_owned()),
            Data::String(string) => Ok(string.into_owned())
        }
    }
}

impl<'a> Into<Data<'a>> for Vec<u8> {
    fn into(self) -> Data<'a> {
        Data::Bytes(Cow::Owned(self))
    }
}

impl<'a> Into<Data<'a>> for &'a [u8] {
    fn into(self) -> Data<'a> {
        Data::Bytes(Cow::Borrowed(self))
    }
}

impl<'a> Into<Data<'a>> for String {
    fn into(self) -> Data<'a> {
        Data::String(Cow::Owned(self))
    }
}

impl<'a> Into<Data<'a>> for &'a str {
    fn into(self) -> Data<'a> {
        Data::String(Cow::Borrowed(self))
    }
}

///An interface for setting HTTP status code and response headers, before data gets written to the client.
pub struct Response<'a, 'b> {
    writer: Option<hyper::server::response::Response<'a>>,
    filters: &'b Vec<Box<ResponseFilter>>,
    log: &'b (Log + 'b),
    global: &'b Global,
    filter_storage: Option<AnyMap>
}

impl<'a, 'b> Response<'a, 'b> {
    pub fn new(
        response: hyper::server::response::Response<'a>,
        filters: &'b Vec<Box<ResponseFilter>>,
        log: &'b Log,
        global: &'b Global
    ) -> Response<'a, 'b> {
        Response {
            writer: Some(response),
            filters: filters,
            log: log,
            global: global,
            filter_storage: Some(AnyMap::new())
        }
    }

    ///Set HTTP status code. Ok (200) is default.
    pub fn set_status(&mut self, status: StatusCode) {
        if let Some(ref mut writer) = self.writer {
            *writer.status_mut() = status;
        }
    }

    ///Set a HTTP response header. Date, content type (text/plain) and server is automatically set.
    pub fn set_header<H: Header + HeaderFormat>(&mut self, header: H) {
        if let Some(ref mut writer) = self.writer {
            writer.headers_mut().set(header);
        }
    }

    ///Get a HTTP response header if set.
    pub fn get_header<H: Header + HeaderFormat>(&self) -> Option<&H> {
        self.writer.as_ref().and_then(|w| w.headers().get())
    }

    ///Mutably borrow the filter storage. It can be used to communicate with
    ///the response filters.
    pub fn filter_storage(&mut self) -> &mut AnyMap {
        self.filter_storage.as_mut().expect("response used after drop")
    }

    ///Turn the `Response` into a `ResponseWriter` to allow the response body to be written.
    ///
    ///Status code and headers will be written to the client and `ResponseFilter::begin()`
    ///will be called on the registered response filters.
    pub fn into_writer(mut self) -> ResponseWriter<'a, 'b> {
        self.make_writer()
    }

    fn make_writer(&mut self) -> ResponseWriter<'a, 'b> {
        let mut write_queue = Vec::new();
        let mut writer = self.writer.take().expect("response used after drop");
        let mut header_result = (writer.status(), Action::Next(None));

        for filter in self.filters {
            header_result = match header_result {
                (_, Action::SilentAbort) => break,
                (_, Action::Abort(_)) => break,
                (status, r) => {
                    write_queue.push(r);

                    let filter_res = {
                        let filter_context = FilterContext {
                            storage: self.filter_storage(),
                            log: self.log,
                            global: self.global,
                        };
                        filter.begin(filter_context, status, writer.headers_mut())
                    };

                    match filter_res {
                        (status, Action::Abort(e)) => (status, Action::Abort(e)),
                        (status, result) => {
                            let mut error = None;

                            write_queue = write_queue.into_iter().filter_map(|action| match action {
                                Action::Next(content) => {
                                    let filter_context = FilterContext {
                                        storage: self.filter_storage(),
                                        log: self.log,
                                        global: self.global,
                                    };
                                    Some(filter.write(filter_context, content))
                                },
                                Action::SilentAbort => None,
                                Action::Abort(e) => {
                                    error = Some(e);
                                    None
                                }
                            }).collect();

                            match error {
                                Some(e) => (status, Action::Abort(e)),
                                None => (status, result)
                            }
                        }
                    }
                }
            }
        }

        let writer = match header_result {
            (_, Action::Abort(e)) => Err(Error::Filter(e)),
            (status, last_result) => {
                write_queue.push(last_result);

                *writer.status_mut() = status;
                let mut writer = match writer.start() {
                    Ok(writer) => Ok(writer),
                    Err(e) => Err(Error::Io(e))
                };

                for action in write_queue {
                    writer = match (action, writer) {
                        (Action::Next(Some(content)), Ok(mut writer)) => match writer.write_all(content.as_bytes()) {
                            Ok(_) => Ok(writer),
                            Err(e) => Err(Error::Io(e))
                        },
                        (Action::Abort(e), _) => Err(Error::Filter(e)),
                        (_, writer) => writer
                    };
                }

                writer
            }
        };

        ResponseWriter {
            writer: Some(writer),
            filters: self.filters,
            log: self.log,
            global: self.global,
            filter_storage: self.filter_storage.take().expect("response used after drop")
        }
    }
}

#[allow(unused_must_use)]
impl<'a, 'b> Drop for Response<'a, 'b> {
    ///Writes status code and headers and closes the connection.
    fn drop(&mut self) {
        if self.writer.is_some() {
            self.make_writer();
        }
    }
}

///An interface for writing to the response body.
pub struct ResponseWriter<'a, 'b> {
    writer: Option<Result<hyper::server::response::Response<'a, hyper::net::Streaming>, Error>>,
    filters: &'b Vec<Box<ResponseFilter>>,
    log: &'b (Log + 'b),
    global: &'b Global,
    filter_storage: AnyMap
}

impl<'a, 'b> ResponseWriter<'a, 'b> {

    ///Mutably borrow the filter storage. It can be used to communicate with
    ///the response filters.
    pub fn filter_storage(&mut self) -> &mut AnyMap {
        &mut self.filter_storage
    }

    ///Write response body data to the client.
    ///
    ///Any errors that occures while writing the data will be ignored. Use
    ///`try_send`, instead, to also get error information.
    #[allow(unused_must_use)]
    pub fn send<'d, Content: Into<Data<'d>>>(&mut self, content: Content) {
        self.try_send(content);
    }

    ///Write response body data to the client and receive the number of
    ///written bytes, or any error that occured.
    pub fn try_send<'d, Content: Into<Data<'d>>>(&mut self, content: Content) -> Result<usize, Error> {
        let mut writer = match self.writer {
            Some(Ok(ref mut writer)) => writer,
            None => return Err(Error::Io(io::Error::new(io::ErrorKind::BrokenPipe, "write after close"))),
            Some(Err(_)) => if let Some(Err(e)) = self.writer.take() {
                return Err(e);
            } else { unreachable!(); }
        };

        let mut filter_result = Action::next(Some(content));

        for filter in self.filters {
            filter_result = match filter_result {
                Action::Next(content) => {
                    let filter_context = FilterContext {
                        storage: &mut self.filter_storage,
                        log: self.log,
                        global: self.global,
                    };
                    filter.write(filter_context, content)
                },
                _ => break
            }
        }

        let write_result = match filter_result {
            Action::Next(Some(ref s)) => {
                let buf = s.as_bytes();
                match writer.write_all(buf) {
                    Ok(()) => Some(Ok(buf.len())),
                    Err(e) => Some(Err(e))
                }
            },
            _ => None
        };

        match write_result {
            Some(Ok(l)) => Ok(l),
            Some(Err(e)) => Err(Error::Io(e)),
            None => match filter_result {
                Action::Abort(e) => Err(Error::Filter(e)),
                Action::Next(None) => Ok(0),
                _ => unreachable!()
            }
        }
    }

    ///Finish writing the response and collect eventual errors.
    ///
    ///This is optional and will happen silently when the writer drops out of
    ///scope.
    pub fn end(mut self) -> Result<(), Error> {
        self.finish()
    }

    fn finish(&mut self) -> Result<(), Error> {
        let mut writer = try!(self.writer.take().expect("can only finish once"));
        let mut write_queue: Vec<Action> = Vec::new();

        for filter in self.filters {
            let mut error = None;
            write_queue = write_queue.into_iter().filter_map(|action| match action {
                Action::Next(content) => {
                    let filter_context = FilterContext {
                        storage: &mut self.filter_storage,
                        log: self.log,
                        global: self.global,
                    };
                    Some(filter.write(filter_context, content))
                },
                Action::SilentAbort => None,
                Action::Abort(e) => {
                    error = Some(e);
                    None
                }
            }).collect();

            match error {
                Some(e) => return Err(Error::Filter(e)),
                None => {
                    let filter_context = FilterContext {
                        storage: &mut self.filter_storage,
                        log: self.log,
                        global: self.global,
                    };
                    write_queue.push(filter.end(filter_context))
                }
            }
        }

        for action in write_queue {
            try!{
                match action {
                    Action::Next(Some(content)) => writer.write_all(content.as_bytes()),
                    Action::Abort(e) => return Err(Error::Filter(e)),
                    _ => Ok(())
                }
            }
        }

        writer.end().map_err(|e| Error::Io(e))
    }

    fn borrow_writer(&mut self) -> Result<&mut hyper::server::response::Response<'a, hyper::net::Streaming>, Error> {
        match self.writer {
            Some(Ok(ref mut writer)) => Ok(writer),
            None => Err(Error::Io(io::Error::new(io::ErrorKind::BrokenPipe, "write after close"))),
            Some(Err(_)) => if let Some(Err(e)) = self.writer.take() {
                Err(e)
            } else { unreachable!(); }
        }
    }
}

impl<'a, 'b> Write for ResponseWriter<'a, 'b> {
    fn write(&mut self, content: &[u8]) -> io::Result<usize> {
        response_to_io_result(self.try_send(content))
    }

    fn write_all(&mut self, content: &[u8]) -> io::Result<()> {
        self.write(content).map(|_| ())
    }

    fn flush(&mut self) -> io::Result<()> {
        let mut writer = try!(response_to_io_result(self.borrow_writer()));
        writer.flush()
    }
}

#[allow(unused_must_use)]
impl<'a, 'b> Drop for ResponseWriter<'a, 'b> {
    ///Finishes writing and closes the connection.
    fn drop(&mut self) {
        if self.writer.is_some() {
            self.finish();
        }
    }
}

fn response_to_io_result<T>(res:  Result<T, Error>) -> io::Result<T> {
    match res {
        Ok(v) => Ok(v),
        Err(Error::Io(e)) => Err(e),
        Err(e) => Err(io::Error::new(io::ErrorKind::Other, e))
    }
}<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// An "interner" is a data structure that associates values with uint tags and
// allows bidirectional lookup; i.e. given a value, one can easily find the
// type, and vice versa.

use ast::Name;

use std::cmp::Equiv;
use std::hashmap::HashMap;

pub struct Interner<T> {
    priv map: @mut HashMap<T, Name>,
    priv vect: @mut ~[T],
}

// when traits can extend traits, we should extend index<Name,T> to get []
impl<T:Eq + IterBytes + Hash + Freeze + Clone + 'static> Interner<T> {
    pub fn new() -> Interner<T> {
        Interner {
            map: @mut HashMap::new(),
            vect: @mut ~[],
        }
    }

    pub fn prefill(init: &[T]) -> Interner<T> {
        let rv = Interner::new();
        for v in init.iter() {
            rv.intern((*v).clone());
        }
        rv
    }

    pub fn intern(&self, val: T) -> Name {
        match self.map.find(&val) {
            Some(&idx) => return idx,
            None => (),
        }

        let vect = &mut *self.vect;
        let new_idx = vect.len() as Name;
        self.map.insert(val.clone(), new_idx);
        vect.push(val);
        new_idx
    }

    pub fn gensym(&self, val: T) -> Name {
        let new_idx = {
            let vect = &*self.vect;
            vect.len() as Name
        };
        // leave out of .map to avoid colliding
        self.vect.push(val);
        new_idx
    }

    pub fn get(&self, idx: Name) -> T {
        self.vect[idx].clone()
    }

    pub fn len(&self) -> uint { let vect = &*self.vect; vect.len() }

    pub fn find_equiv<Q:Hash + IterBytes + Equiv<T>>(&self, val: &Q)
                                              -> Option<Name> {
        match self.map.find_equiv(val) {
            Some(v) => Some(*v),
            None => None,
        }
    }
}

// A StrInterner differs from Interner<String> in that it accepts
// borrowed pointers rather than @ ones, resulting in less allocation.
pub struct StrInterner {
    priv map: @mut HashMap<@str, Name>,
    priv vect: @mut ~[@str],
}

// when traits can extend traits, we should extend index<Name,T> to get []
impl StrInterner {
    pub fn new() -> StrInterner {
        StrInterner {
            map: @mut HashMap::new(),
            vect: @mut ~[],
        }
    }

    pub fn prefill(init: &[&str]) -> StrInterner {
        let rv = StrInterner::new();
        for &v in init.iter() { rv.intern(v); }
        rv
    }

    pub fn intern(&self, val: &str) -> Name {
        match self.map.find_equiv(&val) {
            Some(&idx) => return idx,
            None => (),
        }

        let new_idx = self.len() as Name;
        let val = val.to_managed();
        self.map.insert(val, new_idx);
        self.vect.push(val);
        new_idx
    }

    pub fn gensym(&self, val: &str) -> Name {
        let new_idx = self.len() as Name;
        // leave out of .map to avoid colliding
        self.vect.push(val.to_managed());
        new_idx
    }

    // I want these gensyms to share name pointers
    // with existing entries. This would be automatic,
    // except that the existing gensym creates its
    // own managed ptr using to_managed. I think that
    // adding this utility function is the most
    // lightweight way to get what I want, though not
    // necessarily the cleanest.

    // create a gensym with the same name as an existing
    // entry.
    pub fn gensym_copy(&self, idx : Name) -> Name {
        let new_idx = self.len() as Name;
        // leave out of map to avoid colliding
        self.vect.push(self.vect[idx]);
        new_idx
    }

    pub fn get(&self, idx: Name) -> @str { self.vect[idx] }

    pub fn len(&self) -> uint { let vect = &*self.vect; vect.len() }

    pub fn find_equiv<Q:Hash + IterBytes + Equiv<@str>>(&self, val: &Q)
                                                         -> Option<Name> {
        match self.map.find_equiv(val) {
            Some(v) => Some(*v),
            None => None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    #[should_fail]
    fn i1 () {
        let i : Interner<@str> = Interner::new();
        i.get(13);
    }

    #[test]
    fn interner_tests () {
        let i : Interner<@str> = Interner::new();
        // first one is zero:
        assert_eq!(i.intern(@"dog"), 0);
        // re-use gets the same entry:
        assert_eq!(i.intern(@"dog"), 0);
        // different string gets a different #:
        assert_eq!(i.intern(@"cat"), 1);
        assert_eq!(i.intern(@"cat"), 1);
        // dog is still at zero
        assert_eq!(i.intern(@"dog"), 0);
        // gensym gets 3
        assert_eq!(i.gensym(@"zebra" ), 2);
        // gensym of same string gets new number :
        assert_eq!(i.gensym (@"zebra" ), 3);
        // gensym of *existing* string gets new number:
        assert_eq!(i.gensym(@"dog"), 4);
        assert_eq!(i.get(0), @"dog");
        assert_eq!(i.get(1), @"cat");
        assert_eq!(i.get(2), @"zebra");
        assert_eq!(i.get(3), @"zebra");
        assert_eq!(i.get(4), @"dog");
    }

    #[test]
    fn i3 () {
        let i : Interner<@str> = Interner::prefill([@"Alan",@"Bob",@"Carol"]);
        assert_eq!(i.get(0), @"Alan");
        assert_eq!(i.get(1), @"Bob");
        assert_eq!(i.get(2), @"Carol");
        assert_eq!(i.intern(@"Bob"), 1);
    }

    #[test]
    fn string_interner_tests() {
        let i : StrInterner = StrInterner::new();
        // first one is zero:
        assert_eq!(i.intern("dog"), 0);
        // re-use gets the same entry:
        assert_eq!(i.intern ("dog"), 0);
        // different string gets a different #:
        assert_eq!(i.intern("cat"), 1);
        assert_eq!(i.intern("cat"), 1);
        // dog is still at zero
        assert_eq!(i.intern("dog"), 0);
        // gensym gets 3
        assert_eq!(i.gensym("zebra"), 2);
        // gensym of same string gets new number :
        assert_eq!(i.gensym("zebra"), 3);
        // gensym of *existing* string gets new number:
        assert_eq!(i.gensym("dog"), 4);
        // gensym tests again with gensym_copy:
        assert_eq!(i.gensym_copy(2), 5);
        assert_eq!(i.get(5), @"zebra");
        assert_eq!(i.gensym_copy(2), 6);
        assert_eq!(i.get(6), @"zebra");
        assert_eq!(i.get(0), @"dog");
        assert_eq!(i.get(1), @"cat");
        assert_eq!(i.get(2), @"zebra");
        assert_eq!(i.get(3), @"zebra");
        assert_eq!(i.get(4), @"dog");
    }
}
<commit_msg>libsyntax: De-`@mut` the interner map<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// An "interner" is a data structure that associates values with uint tags and
// allows bidirectional lookup; i.e. given a value, one can easily find the
// type, and vice versa.

use ast::Name;

use std::cell::RefCell;
use std::cmp::Equiv;
use std::hashmap::HashMap;

pub struct Interner<T> {
    priv map: @RefCell<HashMap<T, Name>>,
    priv vect: @mut ~[T],
}

// when traits can extend traits, we should extend index<Name,T> to get []
impl<T:Eq + IterBytes + Hash + Freeze + Clone + 'static> Interner<T> {
    pub fn new() -> Interner<T> {
        Interner {
            map: @RefCell::new(HashMap::new()),
            vect: @mut ~[],
        }
    }

    pub fn prefill(init: &[T]) -> Interner<T> {
        let rv = Interner::new();
        for v in init.iter() {
            rv.intern((*v).clone());
        }
        rv
    }

    pub fn intern(&self, val: T) -> Name {
        let mut map = self.map.borrow_mut();
        match map.get().find(&val) {
            Some(&idx) => return idx,
            None => (),
        }

        let vect = &mut *self.vect;
        let new_idx = vect.len() as Name;
        map.get().insert(val.clone(), new_idx);
        vect.push(val);
        new_idx
    }

    pub fn gensym(&self, val: T) -> Name {
        let new_idx = {
            let vect = &*self.vect;
            vect.len() as Name
        };
        // leave out of .map to avoid colliding
        self.vect.push(val);
        new_idx
    }

    pub fn get(&self, idx: Name) -> T {
        self.vect[idx].clone()
    }

    pub fn len(&self) -> uint { let vect = &*self.vect; vect.len() }

    pub fn find_equiv<Q:Hash + IterBytes + Equiv<T>>(&self, val: &Q)
                                              -> Option<Name> {
        let map = self.map.borrow();
        match map.get().find_equiv(val) {
            Some(v) => Some(*v),
            None => None,
        }
    }
}

// A StrInterner differs from Interner<String> in that it accepts
// borrowed pointers rather than @ ones, resulting in less allocation.
pub struct StrInterner {
    priv map: @RefCell<HashMap<@str, Name>>,
    priv vect: @mut ~[@str],
}

// when traits can extend traits, we should extend index<Name,T> to get []
impl StrInterner {
    pub fn new() -> StrInterner {
        StrInterner {
            map: @RefCell::new(HashMap::new()),
            vect: @mut ~[],
        }
    }

    pub fn prefill(init: &[&str]) -> StrInterner {
        let rv = StrInterner::new();
        for &v in init.iter() { rv.intern(v); }
        rv
    }

    pub fn intern(&self, val: &str) -> Name {
        let mut map = self.map.borrow_mut();
        match map.get().find_equiv(&val) {
            Some(&idx) => return idx,
            None => (),
        }

        let new_idx = self.len() as Name;
        let val = val.to_managed();
        map.get().insert(val, new_idx);
        self.vect.push(val);
        new_idx
    }

    pub fn gensym(&self, val: &str) -> Name {
        let new_idx = self.len() as Name;
        // leave out of .map to avoid colliding
        self.vect.push(val.to_managed());
        new_idx
    }

    // I want these gensyms to share name pointers
    // with existing entries. This would be automatic,
    // except that the existing gensym creates its
    // own managed ptr using to_managed. I think that
    // adding this utility function is the most
    // lightweight way to get what I want, though not
    // necessarily the cleanest.

    // create a gensym with the same name as an existing
    // entry.
    pub fn gensym_copy(&self, idx : Name) -> Name {
        let new_idx = self.len() as Name;
        // leave out of map to avoid colliding
        self.vect.push(self.vect[idx]);
        new_idx
    }

    pub fn get(&self, idx: Name) -> @str { self.vect[idx] }

    pub fn len(&self) -> uint { let vect = &*self.vect; vect.len() }

    pub fn find_equiv<Q:Hash + IterBytes + Equiv<@str>>(&self, val: &Q)
                                                         -> Option<Name> {
        let map = self.map.borrow();
        match map.get().find_equiv(val) {
            Some(v) => Some(*v),
            None => None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    #[should_fail]
    fn i1 () {
        let i : Interner<@str> = Interner::new();
        i.get(13);
    }

    #[test]
    fn interner_tests () {
        let i : Interner<@str> = Interner::new();
        // first one is zero:
        assert_eq!(i.intern(@"dog"), 0);
        // re-use gets the same entry:
        assert_eq!(i.intern(@"dog"), 0);
        // different string gets a different #:
        assert_eq!(i.intern(@"cat"), 1);
        assert_eq!(i.intern(@"cat"), 1);
        // dog is still at zero
        assert_eq!(i.intern(@"dog"), 0);
        // gensym gets 3
        assert_eq!(i.gensym(@"zebra" ), 2);
        // gensym of same string gets new number :
        assert_eq!(i.gensym (@"zebra" ), 3);
        // gensym of *existing* string gets new number:
        assert_eq!(i.gensym(@"dog"), 4);
        assert_eq!(i.get(0), @"dog");
        assert_eq!(i.get(1), @"cat");
        assert_eq!(i.get(2), @"zebra");
        assert_eq!(i.get(3), @"zebra");
        assert_eq!(i.get(4), @"dog");
    }

    #[test]
    fn i3 () {
        let i : Interner<@str> = Interner::prefill([@"Alan",@"Bob",@"Carol"]);
        assert_eq!(i.get(0), @"Alan");
        assert_eq!(i.get(1), @"Bob");
        assert_eq!(i.get(2), @"Carol");
        assert_eq!(i.intern(@"Bob"), 1);
    }

    #[test]
    fn string_interner_tests() {
        let i : StrInterner = StrInterner::new();
        // first one is zero:
        assert_eq!(i.intern("dog"), 0);
        // re-use gets the same entry:
        assert_eq!(i.intern ("dog"), 0);
        // different string gets a different #:
        assert_eq!(i.intern("cat"), 1);
        assert_eq!(i.intern("cat"), 1);
        // dog is still at zero
        assert_eq!(i.intern("dog"), 0);
        // gensym gets 3
        assert_eq!(i.gensym("zebra"), 2);
        // gensym of same string gets new number :
        assert_eq!(i.gensym("zebra"), 3);
        // gensym of *existing* string gets new number:
        assert_eq!(i.gensym("dog"), 4);
        // gensym tests again with gensym_copy:
        assert_eq!(i.gensym_copy(2), 5);
        assert_eq!(i.get(5), @"zebra");
        assert_eq!(i.gensym_copy(2), 6);
        assert_eq!(i.get(6), @"zebra");
        assert_eq!(i.get(0), @"dog");
        assert_eq!(i.get(1), @"cat");
        assert_eq!(i.get(2), @"zebra");
        assert_eq!(i.get(3), @"zebra");
        assert_eq!(i.get(4), @"dog");
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use std::sync::{Arc, Mutex};

use timely::dataflow::*;
use timely::dataflow::operators::*;
use timely::dataflow::operators::Capture;
use timely::dataflow::operators::capture::Extract;

use differential_dataflow::{Collection, AsCollection};

use differential_dataflow::operators::*;
use differential_dataflow::lattice::Lattice;

type Node = usize;
type Edge = (Node, Node);

#[test] fn bfs_10_20_1000() { test_sizes(10, 20, 200); }
#[test] fn bfs_100_200_10() { test_sizes(100, 200, 10); }
#[test] fn bfs_100_2000_1() { test_sizes(100, 2000, 1); }

fn test_sizes(nodes: usize, edges: usize, rounds: usize) {

    let root_list = vec![(1, 0, 1)];
    let mut edge_list = Vec::new();

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
    let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

    for _ in 0 .. edges {
        edge_list.push(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), 0, 1));
    }

    for round in 1 .. rounds {
        edge_list.push(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), round, 1));
        edge_list.push(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), round,-1));
    }

    let mut results1 = bfs_sequential(root_list.clone(), edge_list.clone());
    let mut results2 = bfs_differential(root_list.clone(), edge_list.clone());

    results1.sort();
    results1.sort_by(|x,y| x.1.cmp(&y.1));
    results2.sort();
    results2.sort_by(|x,y| x.1.cmp(&y.1));

    if results1 != results2 {
        println!("RESULTS INEQUAL!!!");
        for x in &results1 {
            if !results2.contains(x) {
                println!("  in seq, not diff: {:?}", x);
            }
        }
        for x in &results2 {
            if !results1.contains(x) {
                println!("  in diff, not seq: {:?}", x);
            }
        }

    }

    assert_eq!(results1, results2);
}

fn bfs_sequential(
    root_list: Vec<(usize, usize, isize)>,
    edge_list: Vec<((usize, usize), usize, isize)>)
-> Vec<((usize, usize), usize, isize)> {

    let mut nodes = 0;
    for &(root, _, _) in &root_list {
        nodes = ::std::cmp::max(nodes, root + 1);
    }
    for &((src,dst), _, _) in &edge_list {
        nodes = ::std::cmp::max(nodes, src + 1);
        nodes = ::std::cmp::max(nodes, dst + 1);
    }

    let mut rounds = 0;
    for &(_, time, _) in &root_list { rounds = ::std::cmp::max(rounds, time + 1); }
    for &(_, time, _) in &edge_list { rounds = ::std::cmp::max(rounds, time + 1); }

    let mut counts = vec![0; nodes];
    let mut results = Vec::new();

    for round in 0 .. rounds {

        let mut roots = ::std::collections::HashMap::new();
        for &(root, time, diff) in &root_list {
            if time <= round { *roots.entry(root).or_insert(0) += diff; }
        }

        let mut edges = ::std::collections::HashMap::new();
        for &((src, dst), time, diff) in &edge_list {
            if time <= round { *edges.entry((src, dst)).or_insert(0) += diff; }
        }

        let mut dists = vec![usize::max_value(); nodes];
        for (&key, &val) in roots.iter() {
            if val > 0 { dists[key] = 0; }
        }

        let mut changes = true;
        while changes {
            changes = false;
            for (&(src, dst), &cnt) in edges.iter() {
                if cnt > 0 {
                    if dists[src] != usize::max_value() && dists[dst] > dists[src] + 1 {
                        dists[dst] = dists[src] + 1;
                        changes = true;
                    }
                }
            }
        }

        let mut new_counts = vec![0; nodes];
        for &value in dists.iter() {
            if value != usize::max_value() {
                new_counts[value] += 1;
            }
        }

        for index in 0 .. nodes {
            if new_counts[index] != counts[index] {
                if new_counts[index] != 0 { results.push(((index, new_counts[index]), round, 1)); }
                if counts[index] != 0 { results.push(((index, counts[index]), round,-1)); }
                counts[index] = new_counts[index];
            }
        }
    }

    results
}

fn bfs_differential(
    roots_list: Vec<(usize, usize, isize)>,
    edges_list: Vec<((usize, usize), usize, isize)>)
-> Vec<((usize, usize), usize, isize)>
{

    let (send, recv) = ::std::sync::mpsc::channel();
    let send = Arc::new(Mutex::new(send));

    timely::execute(timely::Configuration::Thread, move |worker| {

        let mut roots_list = roots_list.clone();
        let mut edges_list = edges_list.clone();

        // define BFS dataflow; return handles to roots and edges inputs
        let (mut roots, mut edges) = worker.dataflow(|scope| {

            let send = send.lock().unwrap().clone();

            let (root_input, roots) = scope.new_input();
            let (edge_input, edges) = scope.new_input();

            let roots = roots.as_collection();
            let edges = edges.as_collection();

            bfs(&edges, &roots).map(|(_, dist)| dist)
                               .count()
                               .map(|(x,y)| (x, y as usize))
                               .inner
                               .capture_into(send);

            (root_input, edge_input)
        });

        // sort by decreasing insertion time.
        roots_list.sort_by(|x,y| y.1.cmp(&x.1));
        edges_list.sort_by(|x,y| y.1.cmp(&x.1));

        let mut roots = differential_dataflow::input::InputSession::from(&mut roots);
        let mut edges = differential_dataflow::input::InputSession::from(&mut edges);

        let mut round = 0;
        while roots_list.len() > 0 || edges_list.len() > 0 {

            while roots_list.last().map(|x| x.1) == Some(round) {
                let (node, _time, diff) = roots_list.pop().unwrap();
                roots.update(node, diff);
            }
            while edges_list.last().map(|x| x.1) == Some(round) {
                let ((src, dst), _time, diff) = edges_list.pop().unwrap();
                edges.update((src, dst), diff);
            }

            round += 1;
            roots.advance_to(round);
            edges.advance_to(round);
        }

    }).unwrap();

    recv.extract()
        .into_iter()
        .flat_map(|(_, list)| list.into_iter().map(|((dst,cnt),time,diff)| ((dst,cnt), time.inner, diff)))
        .collect()
}

fn bfs_arranged(
    roots_list: Vec<(usize, usize, isize)>,
    edges_list: Vec<((usize, usize), usize, isize)>)
-> Vec<((usize, usize), usize, isize)>
{

    let (send, recv) = ::std::sync::mpsc::channel();
    let send = Arc::new(Mutex::new(send));

    timely::execute(timely::Configuration::Thread, move |worker| {

        let mut roots_list = roots_list.clone();
        let mut edges_list = edges_list.clone();

        // define BFS dataflow; return handles to roots and edges inputs
        let (mut roots, mut edges) = worker.dataflow(|scope| {

            let send = send.lock().unwrap().clone();

            let (root_input, roots) = scope.new_input();
            let (edge_input, edges) = scope.new_input();

            let roots = roots.as_collection();
            let edges = edges.as_collection();

            bfs(&edges, &roots).map(|(_, dist)| dist)
                               .count()
                               .map(|(x,y)| (x, y as usize))
                               .inner
                               .capture_into(send);

            (root_input, edge_input)
        });

        // sort by decreasing insertion time.
        roots_list.sort_by(|x,y| y.1.cmp(&x.1));
        edges_list.sort_by(|x,y| y.1.cmp(&x.1));

        let mut roots = differential_dataflow::input::InputSession::from(&mut roots);
        let mut edges = differential_dataflow::input::InputSession::from(&mut edges);

        let mut round = 0;
        while roots_list.len() > 0 || edges_list.len() > 0 {

            while roots_list.last().map(|x| x.1) == Some(round) {
                let (node, _time, diff) = roots_list.pop().unwrap();
                roots.update(node, diff);
            }
            while edges_list.last().map(|x| x.1) == Some(round) {
                let ((src, dst), _time, diff) = edges_list.pop().unwrap();
                edges.update((src, dst), diff);
            }

            round += 1;
            roots.advance_to(round);
            edges.advance_to(round);
        }

    }).unwrap();

    recv.extract()
        .into_iter()
        .flat_map(|(_, list)| list.into_iter().map(|((dst,cnt),time,diff)| ((dst,cnt), time.inner, diff)))
        .collect()
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn bfs<G: Scope>(edges: &Collection<G, Edge>, roots: &Collection<G, Node>) -> Collection<G, (Node, usize)>
where G::Timestamp: Lattice+Ord {

    // initialize roots as reaching themselves at distance 0
    let nodes = roots.map(|x| (x, 0));

    // repeatedly update minimal distances each node can be reached from each root
    nodes.iterate(|inner| {

        let edges = edges.enter(&inner.scope());
        let nodes = nodes.enter(&inner.scope());

        inner.join_map(&edges, |_k,l,d| (*d, l+1))
             .concat(&nodes)
             .group(|_, s, t| t.push((s[0].0, 1)))
     })
}<commit_msg>cleaned up tests<commit_after>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use std::sync::{Arc, Mutex};

use timely::dataflow::*;
use timely::dataflow::operators::*;
use timely::dataflow::operators::Capture;
use timely::dataflow::operators::capture::Extract;

use differential_dataflow::{Collection, AsCollection};

use differential_dataflow::operators::*;
use differential_dataflow::lattice::Lattice;

type Node = usize;
type Edge = (Node, Node);

#[test] fn bfs_10_20_1000() { test_sizes(10, 20, 200); }
#[test] fn bfs_100_200_10() { test_sizes(100, 200, 10); }
#[test] fn bfs_100_2000_1() { test_sizes(100, 2000, 1); }

fn test_sizes(nodes: usize, edges: usize, rounds: usize) {

    let root_list = vec![(1, 0, 1)];
    let mut edge_list = Vec::new();

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
    let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

    for _ in 0 .. edges {
        edge_list.push(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), 0, 1));
    }

    for round in 1 .. rounds {
        edge_list.push(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), round, 1));
        edge_list.push(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), round,-1));
    }

    let mut results1 = bfs_sequential(root_list.clone(), edge_list.clone());
    let mut results2 = bfs_differential(root_list.clone(), edge_list.clone());

    results1.sort();
    results1.sort_by(|x,y| x.1.cmp(&y.1));
    results2.sort();
    results2.sort_by(|x,y| x.1.cmp(&y.1));

    if results1 != results2 {
        println!("RESULTS INEQUAL!!!");
        for x in &results1 {
            if !results2.contains(x) {
                println!("  in seq, not diff: {:?}", x);
            }
        }
        for x in &results2 {
            if !results1.contains(x) {
                println!("  in diff, not seq: {:?}", x);
            }
        }

    }

    assert_eq!(results1, results2);
}

fn bfs_sequential(
    root_list: Vec<(usize, usize, isize)>,
    edge_list: Vec<((usize, usize), usize, isize)>)
-> Vec<((usize, usize), usize, isize)> {

    let mut nodes = 0;
    for &(root, _, _) in &root_list {
        nodes = ::std::cmp::max(nodes, root + 1);
    }
    for &((src,dst), _, _) in &edge_list {
        nodes = ::std::cmp::max(nodes, src + 1);
        nodes = ::std::cmp::max(nodes, dst + 1);
    }

    let mut rounds = 0;
    for &(_, time, _) in &root_list { rounds = ::std::cmp::max(rounds, time + 1); }
    for &(_, time, _) in &edge_list { rounds = ::std::cmp::max(rounds, time + 1); }

    let mut counts = vec![0; nodes];
    let mut results = Vec::new();

    for round in 0 .. rounds {

        let mut roots = ::std::collections::HashMap::new();
        for &(root, time, diff) in &root_list {
            if time <= round { *roots.entry(root).or_insert(0) += diff; }
        }

        let mut edges = ::std::collections::HashMap::new();
        for &((src, dst), time, diff) in &edge_list {
            if time <= round { *edges.entry((src, dst)).or_insert(0) += diff; }
        }

        let mut dists = vec![usize::max_value(); nodes];
        for (&key, &val) in roots.iter() {
            if val > 0 { dists[key] = 0; }
        }

        let mut changes = true;
        while changes {
            changes = false;
            for (&(src, dst), &cnt) in edges.iter() {
                if cnt > 0 {
                    if dists[src] != usize::max_value() && dists[dst] > dists[src] + 1 {
                        dists[dst] = dists[src] + 1;
                        changes = true;
                    }
                }
            }
        }

        let mut new_counts = vec![0; nodes];
        for &value in dists.iter() {
            if value != usize::max_value() {
                new_counts[value] += 1;
            }
        }

        for index in 0 .. nodes {
            if new_counts[index] != counts[index] {
                if new_counts[index] != 0 { results.push(((index, new_counts[index]), round, 1)); }
                if counts[index] != 0 { results.push(((index, counts[index]), round,-1)); }
                counts[index] = new_counts[index];
            }
        }
    }

    results
}

fn bfs_differential(
    roots_list: Vec<(usize, usize, isize)>,
    edges_list: Vec<((usize, usize), usize, isize)>)
-> Vec<((usize, usize), usize, isize)>
{

    let (send, recv) = ::std::sync::mpsc::channel();
    let send = Arc::new(Mutex::new(send));

    timely::execute(timely::Configuration::Thread, move |worker| {

        let mut roots_list = roots_list.clone();
        let mut edges_list = edges_list.clone();

        // define BFS dataflow; return handles to roots and edges inputs
        let (mut roots, mut edges) = worker.dataflow(|scope| {

            let send = send.lock().unwrap().clone();

            let (root_input, roots) = scope.new_input();
            let (edge_input, edges) = scope.new_input();

            let roots = roots.as_collection();
            let edges = edges.as_collection();

            bfs(&edges, &roots).map(|(_, dist)| dist)
                               .count()
                               .map(|(x,y)| (x, y as usize))
                               .inner
                               .capture_into(send);

            (root_input, edge_input)
        });

        // sort by decreasing insertion time.
        roots_list.sort_by(|x,y| y.1.cmp(&x.1));
        edges_list.sort_by(|x,y| y.1.cmp(&x.1));

        let mut roots = differential_dataflow::input::InputSession::from(&mut roots);
        let mut edges = differential_dataflow::input::InputSession::from(&mut edges);

        let mut round = 0;
        while roots_list.len() > 0 || edges_list.len() > 0 {

            while roots_list.last().map(|x| x.1) == Some(round) {
                let (node, _time, diff) = roots_list.pop().unwrap();
                roots.update(node, diff);
            }
            while edges_list.last().map(|x| x.1) == Some(round) {
                let ((src, dst), _time, diff) = edges_list.pop().unwrap();
                edges.update((src, dst), diff);
            }

            round += 1;
            roots.advance_to(round);
            edges.advance_to(round);
        }

    }).unwrap();

    recv.extract()
        .into_iter()
        .flat_map(|(_, list)| list.into_iter().map(|((dst,cnt),time,diff)| ((dst,cnt), time.inner, diff)))
        .collect()
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn bfs<G: Scope>(edges: &Collection<G, Edge>, roots: &Collection<G, Node>) -> Collection<G, (Node, usize)>
where G::Timestamp: Lattice+Ord {

    // initialize roots as reaching themselves at distance 0
    let nodes = roots.map(|x| (x, 0));

    // repeatedly update minimal distances each node can be reached from each root
    nodes.iterate(|inner| {

        let edges = edges.enter(&inner.scope());
        let nodes = nodes.enter(&inner.scope());

        inner.join_map(&edges, |_k,l,d| (*d, l+1))
             .concat(&nodes)
             .group(|_, s, t| t.push((s[0].0, 1)))
     })
}<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;
extern crate warc_parser;
mod tests{
    use std::error::Error;
    use std::fs::File;
    use std::io::prelude::*;
    use std::path::Path;

    fn read_sample_file(sample_name: &str) -> String{
        let full_path = "sample/".to_string()+sample_name;
        let mut f = File::open(full_path).unwrap();
        let mut s = String::new();
        f.read_to_string(&mut s).unwrap();
        s
    }
    use warc_parser;
    #[test]
    fn it_parses_a_plethora(){
        let examples = read_sample_file("picplz.warc");
        let parsed = warc_parser::records(examples.as_bytes());
        println!("{:?}",parsed);
        assert!(parsed.is_done());
    }

    #[test]
    fn it_parses_single(){
        let bbc = read_sample_file("bbc.warc");
        let parsed = warc_parser::record(bbc.as_bytes());
        assert!(parsed.is_done());
    }
}
<commit_msg>Read test input as bytes instead of strings<commit_after>#![feature(test)]
extern crate test;
extern crate warc_parser;
mod tests{
    use std::error::Error;
    use std::fs::File;
    use std::io::prelude::*;
    use std::path::Path;

    fn read_sample_file(sample_name: &str) -> Vec<u8> {
        let full_path = "sample/".to_string()+sample_name;
        let mut f = File::open(full_path).unwrap();
        let mut s = Vec::new();
        f.read_to_end(&mut s).unwrap();
        s
    }
    use warc_parser;
    #[test]
    fn it_parses_a_plethora(){
        let examples = read_sample_file("picplz.warc");
        let parsed = warc_parser::records(&examples);
        println!("{:?}",parsed);
        assert!(parsed.is_done());
    }

    #[test]
    fn it_parses_single(){
        let bbc = read_sample_file("bbc.warc");
        let parsed = warc_parser::record(&bbc);
        assert!(parsed.is_done());
    }
}
<|endoftext|>


<commit_before>extern crate pbr;

use pbr::{ProgressBar, PbIter};
use std::time::Duration;
use std::thread;

#[test]
fn simple_example() {
    let count = 5000;
    let mut pb = ProgressBar::new(count);
    pb.format("╢▌▌░╟");
    for _ in 0..count {
        pb.inc();
        thread::sleep(Duration::from_millis(5));
    }
    println!("done!");
}

#[test]
fn simple_iter_example() {
    for _ in PbIter::new(0..20000) {
        thread::sleep(Duration::from_millis(1));
    }
    println!("done!");
}

#[test]
fn timeout_example() {
    let count = 10;
    let mut pb = ProgressBar::new(count * 20);
    pb.tick_format("▏▎▍▌▋▊▉██▉▊▋▌▍▎▏");
    pb.show_message = true;
    pb.inc();
    for _ in 0..count {
        for _ in 0..20 {
            pb.message("Waiting  : ");
            thread::sleep(Duration::from_millis(50));
            pb.tick();
        }
        for _ in 0..20 {
            pb.message("Connected: ");
            thread::sleep(Duration::from_millis(50));
            pb.inc();
        }
    }
    for _ in 0..10 {
        pb.message("Cleaning :");
        thread::sleep(Duration::from_millis(50));
        pb.tick();
    }
    pb.finish();
    println!("done!");
}

#[test]
// see: issue #11
fn tick_before_start() {
    let count = 100;
    let mut pb = ProgressBar::new(count);
    pb.tick_format("▏▎▍▌▋▊▉██▉▊▋▌▍▎▏");
    pb.tick();
    for _ in 0..count {
        pb.tick();
        thread::sleep(Duration::from_millis(50));
    }
    for _ in 0..count {
        pb.inc();
        thread::sleep(Duration::from_millis(50));
    }
}

#[test]
fn npm_bar() {
    let count = 30;
    let mut pb = ProgressBar::new(count * 5);
    pb.tick_format("\\|/-");
    pb.format("|#--|");
    pb.show_tick = true;
    pb.show_speed = false;
    pb.show_percent = false;
    pb.show_counter = false;
    pb.show_time_left = false;
    pb.inc();
    for _ in 0..count {
        for _ in 0..5 {
            pb.message("normalize -> thing ");
            thread::sleep(Duration::from_millis(80));
            pb.tick();
        }
        for _ in 0..5 {
            pb.message("fuzz -> tree       ");
            thread::sleep(Duration::from_millis(80));
            pb.inc();
        }
    }
    pb.finish();
    println!("done!");
}
<commit_msg>test: add example test with custom width<commit_after>extern crate pbr;

use pbr::{ProgressBar, PbIter};
use std::time::Duration;
use std::thread;

#[test]
fn simple_example() {
    let count = 5000;
    let mut pb = ProgressBar::new(count);
    pb.format("╢▌▌░╟");
    for _ in 0..count {
        pb.inc();
        thread::sleep(Duration::from_millis(5));
    }
    pb.finish_print("done!");
}

#[test]
fn custom_width_example() {
    let count = 500;
    let mut pb = ProgressBar::new(count);
    pb.set_width(Some(80));
    pb.format("╢▌▌░╟");
    for _ in 0..count {
        pb.inc();
        thread::sleep(Duration::from_millis(5));
    }
    pb.finish_print("done!");
}

#[test]
fn simple_iter_example() {
    for _ in PbIter::new(0..2000) {
        thread::sleep(Duration::from_millis(1));
    }
}

#[test]
fn timeout_example() {
    let count = 10;
    let mut pb = ProgressBar::new(count * 20);
    pb.tick_format("▏▎▍▌▋▊▉██▉▊▋▌▍▎▏");
    pb.show_message = true;
    pb.inc();
    for _ in 0..count {
        for _ in 0..20 {
            pb.message("Waiting  : ");
            thread::sleep(Duration::from_millis(50));
            pb.tick();
        }
        for _ in 0..20 {
            pb.message("Connected: ");
            thread::sleep(Duration::from_millis(50));
            pb.inc();
        }
    }
    for _ in 0..10 {
        pb.message("Cleaning :");
        thread::sleep(Duration::from_millis(50));
        pb.tick();
    }
    pb.finish_print("done!");
}

#[test]
// see: issue #11
fn tick_before_start() {
    let count = 100;
    let mut pb = ProgressBar::new(count);
    pb.tick_format("▏▎▍▌▋▊▉██▉▊▋▌▍▎▏");
    pb.tick();
    for _ in 0..count {
        pb.tick();
        thread::sleep(Duration::from_millis(50));
    }
    for _ in 0..count {
        pb.inc();
        thread::sleep(Duration::from_millis(50));
    }
}

#[test]
fn npm_bar() {
    let count = 30;
    let mut pb = ProgressBar::new(count * 5);
    pb.tick_format("\\|/-");
    pb.format("|#--|");
    pb.show_tick = true;
    pb.show_speed = false;
    pb.show_percent = false;
    pb.show_counter = false;
    pb.show_time_left = false;
    pb.inc();
    for _ in 0..count {
        for _ in 0..5 {
            pb.message("normalize -> thing ");
            thread::sleep(Duration::from_millis(80));
            pb.tick();
        }
        for _ in 0..5 {
            pb.message("fuzz -> tree       ");
            thread::sleep(Duration::from_millis(80));
            pb.inc();
        }
    }
    pb.finish_print("done!");
}
<|endoftext|>


<commit_before>extern crate image;

use std::io::File;

#[test]
fn test_open_and_save_tga() {
    let path = Path::new("./tests/images/tga/testsuite/ctc24.tga");
    let img = image::open(&path).unwrap();
    let fout = File::create(&Path::new("./tests/output/tga-ctc24.png")).unwrap();
    let _ = img.save(fout, image::PNG);

    let path = Path::new("./tests/images/tga/testsuite/cbw8.tga");
    let img = image::open(&path).unwrap();
    let fout = File::create(&Path::new("./tests/output/tga-cbw8.png")).unwrap();
    let _ = img.save(fout, image::PNG);
}
<commit_msg>Fix tests, create output directory.<commit_after>extern crate image;

use std::io::{fs, File, USER_RWX};

#[test]
fn test_open_and_save_tga() {
    let _ = fs::mkdir(&Path::new("./tests/output"), USER_RWX);
    let path = Path::new("./tests/images/tga/testsuite/ctc24.tga");
    let img = image::open(&path).unwrap();
    let fout = File::create(&Path::new("./tests/output/tga-ctc24.png")).unwrap();
    let _ = img.save(fout, image::PNG);

    let path = Path::new("./tests/images/tga/testsuite/cbw8.tga");
    let img = image::open(&path).unwrap();
    let fout = File::create(&Path::new("./tests/output/tga-cbw8.png")).unwrap();
    let _ = img.save(fout, image::PNG);
}
<|endoftext|>


<commit_before><commit_msg>fix wrong bus type<commit_after><|endoftext|>


<commit_before>use seed::prelude::*;
use crate::Msg;

extern crate num_bigint as bigint;
extern crate num_traits;
use num_bigint::BigUint;
use num_traits::{Zero, One};
use std::mem::replace;

fn nth(num: usize) -> String {
    format!("{}{}", num, match (num % 10, num % 100) {
        (1, 11) | (2, 12) | (3, 13) => "th",
        (1, _) => "st",
        (2, _) => "nd",
        (3, _) => "rd",
        _ => "th",
    })
}

/*
 * Return a vector of fibonnaci numbers from n to n+count
 */
fn nth_fibonacci(n: usize, count: usize) -> Vec<BigUint> {
    let mut f0: BigUint = Zero::zero();
    let mut f1: BigUint = One::one();
    let mut x = vec![];
    for i in 0..(n+count-1) {
        let f2 = f0 + &f1;
        // This is a low cost way of swapping f0 with f1 and f1 with f2.
        f0 = replace(&mut f1, f2);
        if i >= n-1 {
            x.push(f0.to_owned());
        }
    }
    x
}

pub fn render(slug:String) -> seed::dom_types::Node<Msg> {
    let numbers_per_page:usize = 25;
    //TODO: what occurs if slug_int is an overflow? i.e. greater tha 64bits
    let slug_int:usize = slug.parse().unwrap();
    let fib_vec = nth_fibonacci(slug_int, numbers_per_page);

    let mut fib_vec_formatted = vec![];
    for i in 0..numbers_per_page {
        fib_vec_formatted.push(span![fib_vec[i].to_string()]);
        fib_vec_formatted.push(br![]);
    }

    let href_prev:String;
    let prev_link:Vec<seed::dom_types::Node<_>>;
    if slug_int <= 1 {
        prev_link = vec![];
    } else if slug_int <= 25 {
        href_prev = "/archive/fibonacci/1/".to_string();
        prev_link = vec![a!["back to 1st fibonacci numbers", attrs!{At::Class => "link", At::Href => href_prev}]];
    } else {
        href_prev = vec!["/archive/fibonacci/",&(slug_int-numbers_per_page).to_string(),"/"].into_iter().collect();
        prev_link = vec![a!["previous ",numbers_per_page.to_string()," fibonacci numbers", attrs!{At::Class => "link", At::Href => href_prev}]];
    }
    let href_next:String = vec!["/archive/fibonacci/",&(slug_int+numbers_per_page).to_string(),"/"].into_iter().collect();

    div![
        h1!["The Fibonacci Numbers"],
        br![],
        "This page shows the ",nth(slug_int)," fibonacci number followed by the next ",(numbers_per_page-1).to_string(),".",
        br![],
        br![],
        fib_vec_formatted,
        br![],
        prev_link,
        br![],
        a!["next ",numbers_per_page.to_string()," fibonacci numbers", attrs!{At::Class => "link", At::Href => href_next}],
        br![],
        br![],
        a!["100th Fibonacci Number", attrs!{At::Class => "link", At::Href => "/archive/fibonacci/100/"}],
        br![],
        a!["1000th Fibonacci Number", attrs!{At::Class => "link", At::Href => "/archive/fibonacci/1000/"}],
        br![],
        a!["10000th Fibonacci Number", attrs!{At::Class => "link", At::Href => "/archive/fibonacci/10000/"}],
    ]
}

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

    #[test]
    fn nth_fibonacci_test() {
        let f0: BigUint = Zero::zero();
        let f1: BigUint = One::one();
        let f2: BigUint = &f0 + &f1;
        let f3: BigUint = &f1 + &f2;
        let f4: BigUint = &f2 + &f3;
        let f5: BigUint = &f3 + &f4;
        let f6: BigUint = &f4 + &f5;
        let f7: BigUint = &f5 + &f6;
        let f8: BigUint = &f6 + &f7;
        let f9: BigUint = &f7 + &f8;
        let f10: BigUint = &f8 + &f9;
        let f11: BigUint = &f9 + &f10;

        assert_eq!(nth_fibonacci(1,2), vec![f1,f2]);
        assert_eq!(nth_fibonacci(3,6), vec![f3,f4,f5,f6,f7,f8]);
        assert_eq!(nth_fibonacci(9,3), vec![f9,f10,f11]);
    }

    #[test]
    fn nth_test() {
        assert_eq!(nth(7), "7th");
        assert_ne!(nth(7), "1st");
        assert_eq!(nth(7000000000000000000), "7000000000000000000th");
        assert_eq!(nth(7000000000000000001), "7000000000000000001st");
        assert_eq!(nth(7000000000000000002), "7000000000000000002nd");
        assert_eq!(nth(7000000000000000003), "7000000000000000003rd");
        assert_eq!(nth(7000000000000000011), "7000000000000000011th");
        assert_eq!(nth(7000000000000000012), "7000000000000000012th");
        assert_eq!(nth(7000000000000000013), "7000000000000000013th");
    }
}<commit_msg>Removed todo, as is todone<commit_after>use seed::prelude::*;
use crate::Msg;

extern crate num_bigint as bigint;
extern crate num_traits;
use num_bigint::BigUint;
use num_traits::{Zero, One};
use std::mem::replace;

fn nth(num: usize) -> String {
    format!("{}{}", num, match (num % 10, num % 100) {
        (1, 11) | (2, 12) | (3, 13) => "th",
        (1, _) => "st",
        (2, _) => "nd",
        (3, _) => "rd",
        _ => "th",
    })
}

/*
 * Return a vector of fibonnaci numbers from n to n+count
 */
fn nth_fibonacci(n: usize, count: usize) -> Vec<BigUint> {
    let mut f0: BigUint = Zero::zero();
    let mut f1: BigUint = One::one();
    let mut x = vec![];
    for i in 0..(n+count-1) {
        let f2 = f0 + &f1;
        // This is a low cost way of swapping f0 with f1 and f1 with f2.
        f0 = replace(&mut f1, f2);
        if i >= n-1 {
            x.push(f0.to_owned());
        }
    }
    x
}

pub fn render(slug:String) -> seed::dom_types::Node<Msg> {
    let numbers_per_page:usize = 25;
    let slug_int:usize = slug.parse().unwrap();
    let fib_vec = nth_fibonacci(slug_int, numbers_per_page);

    let mut fib_vec_formatted = vec![];
    for i in 0..numbers_per_page {
        fib_vec_formatted.push(span![fib_vec[i].to_string()]);
        fib_vec_formatted.push(br![]);
    }

    let href_prev:String;
    let prev_link:Vec<seed::dom_types::Node<_>>;
    if slug_int <= 1 {
        prev_link = vec![];
    } else if slug_int <= 25 {
        href_prev = "/archive/fibonacci/1/".to_string();
        prev_link = vec![a!["back to 1st fibonacci numbers", attrs!{At::Class => "link", At::Href => href_prev}]];
    } else {
        href_prev = vec!["/archive/fibonacci/",&(slug_int-numbers_per_page).to_string(),"/"].into_iter().collect();
        prev_link = vec![a!["previous ",numbers_per_page.to_string()," fibonacci numbers", attrs!{At::Class => "link", At::Href => href_prev}]];
    }
    let href_next:String = vec!["/archive/fibonacci/",&(slug_int+numbers_per_page).to_string(),"/"].into_iter().collect();

    div![
        h1!["The Fibonacci Numbers"],
        br![],
        "This page shows the ",nth(slug_int)," fibonacci number followed by the next ",(numbers_per_page-1).to_string(),".",
        br![],
        br![],
        fib_vec_formatted,
        br![],
        prev_link,
        br![],
        a!["next ",numbers_per_page.to_string()," fibonacci numbers", attrs!{At::Class => "link", At::Href => href_next}],
        br![],
        br![],
        a!["100th Fibonacci Number", attrs!{At::Class => "link", At::Href => "/archive/fibonacci/100/"}],
        br![],
        a!["1000th Fibonacci Number", attrs!{At::Class => "link", At::Href => "/archive/fibonacci/1000/"}],
        br![],
        a!["10000th Fibonacci Number", attrs!{At::Class => "link", At::Href => "/archive/fibonacci/10000/"}],
    ]
}

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

    #[test]
    fn nth_fibonacci_test() {
        let f0: BigUint = Zero::zero();
        let f1: BigUint = One::one();
        let f2: BigUint = &f0 + &f1;
        let f3: BigUint = &f1 + &f2;
        let f4: BigUint = &f2 + &f3;
        let f5: BigUint = &f3 + &f4;
        let f6: BigUint = &f4 + &f5;
        let f7: BigUint = &f5 + &f6;
        let f8: BigUint = &f6 + &f7;
        let f9: BigUint = &f7 + &f8;
        let f10: BigUint = &f8 + &f9;
        let f11: BigUint = &f9 + &f10;

        assert_eq!(nth_fibonacci(1,2), vec![f1,f2]);
        assert_eq!(nth_fibonacci(3,6), vec![f3,f4,f5,f6,f7,f8]);
        assert_eq!(nth_fibonacci(9,3), vec![f9,f10,f11]);
    }

    #[test]
    fn nth_test() {
        assert_eq!(nth(7), "7th");
        assert_ne!(nth(7), "1st");
        assert_eq!(nth(7000000000000000000), "7000000000000000000th");
        assert_eq!(nth(7000000000000000001), "7000000000000000001st");
        assert_eq!(nth(7000000000000000002), "7000000000000000002nd");
        assert_eq!(nth(7000000000000000003), "7000000000000000003rd");
        assert_eq!(nth(7000000000000000011), "7000000000000000011th");
        assert_eq!(nth(7000000000000000012), "7000000000000000012th");
        assert_eq!(nth(7000000000000000013), "7000000000000000013th");
    }
}<|endoftext|>


<commit_before>//! Add a delta to a weave file.

use regex::Regex;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::fs::{File, rename, remove_file};
use std::mem::replace;
use std::io::{self, BufRead, BufReader, BufWriter, Write};
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::rc::Rc;

use header::Header;
use NamingConvention;
use {Parser, Sink};
use Result;
use WriterInfo;

/// A DeltaWriter is used to write a new delta.  Data should be written to the writer, and then the
/// `close` method called to update the weave file with the new delta.
pub struct DeltaWriter<'n> {
    naming: &'n NamingConvention,

    // Where the temporary file will be written.
    temp: Option<WriterInfo>,

    // The base delta.
    base: usize,

    // The new delta.
    new_delta: usize,

    // The name of the file with the base written to it.
    base_name: PathBuf,

    // The regex for parsing diff output.
    diff_re: Regex,

    // The header to be written for the new delta.
    header: Header,
}

impl<'n> DeltaWriter<'n> {
    /// Construct a writer for a new delta.  The naming convention and the tags set where the names
    /// will be written, and what tags will be associated with the convention.  The `base` is the
    /// existing delta that the change should be based on.
    pub fn new<'a, 'b, I>(nc: &NamingConvention, tags: I, base: usize) -> Result<DeltaWriter>
        where I: Iterator<Item=(&'a str, &'b str)>
    {
        // Copy the tags, making sure there is a "name", which is used to index.
        // TODO: Ensure that "name" is unique among the existing deltas.
        let mut ntags = BTreeMap::new();
        for (k, v) in tags {
            ntags.insert(k.to_owned(), v.to_owned());
        }
        if !ntags.contains_key("name") {
            return Err("DeltaWriter does not contain a tag \"name\"".into());
        }

        // Extract the base delta to a file.
        let bfd = File::open(nc.main_file())?;
        let lines = BufReader::new(bfd).lines();
        let (base_name, base_file) = nc.temp_file()?;
        let dsink = Rc::new(RefCell::new(RevWriter { dest: BufWriter::new(base_file) }));
        let mut header = {
            let mut parser = Parser::new(lines, dsink, base)?;
            match parser.parse_to(0) {
                Ok(0) => (),
                Ok(_) => panic!("Unexpected stop of parser"),
                Err(e) => return Err(e),
            }
            parser.get_header().clone()
        };
        let new_delta = header.add(ntags)?;

        let (new_name, new_file) = nc.temp_file()?;

        Ok(DeltaWriter {
            naming: nc,
            temp: Some(WriterInfo {
                name: new_name,
                file: new_file,
            }),
            base: base,
            new_delta: new_delta,
            base_name: base_name,
            diff_re: Regex::new(r"(\d+)(,(\d+))?([acd]).*$").unwrap(),
            header: header,
        })
    }

    pub fn close(mut self) -> Result<()> {
        // Close the temporary file, getting its name.
        let temp = replace(&mut self.temp, None);
        let temp_name = match temp {
            Some(mut wi) => {
                wi.file.flush()?;
                drop(wi.file);
                wi.name
            }
            None => return Err("DeltaWriter already closed".into()),
        };

        let (tweave_name, tweave_file) = self.naming.temp_file()?;
        // TODO: Header from old.

        let old_fd = File::open(self.naming.main_file())?;
        let old_lines = BufReader::new(old_fd).lines();

        // Invoke diff on the files.
        let mut child = Command::new("diff")
            .arg(self.base_name.as_os_str())
            .arg(temp_name.as_os_str())
            .stdout(Stdio::piped())
            .spawn()?;

        {
            let lines = BufReader::new(child.stdout.as_mut().unwrap()).lines();
            let weave_write = Rc::new(RefCell::new(WeaveWriter { dest: BufWriter::new(tweave_file) }));
            let mut parser = Parser::new(old_lines, weave_write.clone(), self.base)?;

            self.header.write(&mut weave_write.borrow_mut().dest)?;

            let mut is_done = false;
            let mut is_adding = false;

            for line in lines {
                let line = line?;
                match self.diff_re.captures(&line) {
                    Some(cap) => {
                        // If adding, this completes the add.
                        if is_adding {
                            weave_write.borrow_mut().end(self.new_delta)?;
                            is_adding = false;
                        }

                        let left = cap.get(1).unwrap().as_str().parse::<usize>().unwrap();
                        let right = match cap.get(3) {
                            None => left,
                            Some(r) => r.as_str().parse().unwrap(),
                        };
                        let cmd = cap.get(4).unwrap().as_str().chars().next().unwrap();

                        if cmd == 'd' || cmd == 'c' {
                            // These include deletions.
                            match parser.parse_to(left)? {
                                0 => return Err("Unexpected eof".into()),
                                n if n == left => (),
                                _ => panic!("Unexpected parse result"),
                            }
                            weave_write.borrow_mut().delete(self.new_delta)?;
                            match parser.parse_to(right + 1) {
                                Ok(0) => is_done = true,
                                Ok(n) if n == right + 1 => (),
                                Ok(_) => panic!("Unexpected parse result"),
                                Err(e) => return Err(e),
                            }
                            weave_write.borrow_mut().end(self.new_delta)?;
                        } else {
                            match parser.parse_to(right + 1) {
                                Ok(0) => is_done = true,
                                Ok(n) if n == right + 1 => (),
                                Ok(_) => panic!("Unexpected parse result"),
                                Err(e) => return Err(e),
                            }
                        }

                        if cmd == 'c' || cmd == 'a' {
                            weave_write.borrow_mut().insert(self.new_delta)?;
                            is_adding = true;
                        }

                        continue;
                    },
                    None => (),
                }

                match line.chars().next() {
                    None => panic!("Unexpected blank line in diff"),
                    Some('<') => continue,
                    Some('-') => continue,
                    Some('>') => {
                        // Add lines should just be written as-is.
                        weave_write.borrow_mut().plain(&line[2..], true)?;
                    }
                    Some(_) => panic!("Unexpected diff line: {:?}", line),
                }
            }

            if is_adding {
                weave_write.borrow_mut().end(self.new_delta)?;
            }

            if !is_done {
                match parser.parse_to(0) {
                    Ok(0) => (),
                    Ok(_) => panic!("Unexpected non-eof"),
                    Err(e) => return Err(e),
                }
            }
        }

        match child.wait()?.code() {
            None => return Err("diff killed by signal".into()),
            Some(0) => (), // No diffs
            Some(1) => (), // Normal with diffs
            Some(n) => return Err(format!("diff returned error status: {}", n).into()),
        }

        // Now that is all done, clean up the temp files, and cycle the backup.
        let _ = rename(self.naming.main_file(), self.naming.backup_file());
        rename(tweave_name, self.naming.main_file())?;
        remove_file(&self.base_name)?;
        remove_file(&temp_name)?;

        Ok(())
    }
}

impl <'n> Write for DeltaWriter<'n> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.temp.as_mut()
            .expect("Attempt to write to DeltaWriter that is closed")
            .file.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.temp.as_mut()
            .expect("Attempt to flush DeltaWriter that is closed")
            .file.flush()
    }
}

struct RevWriter<W: Write> {
    dest: BufWriter<W>,
}

impl<W: Write> Sink for RevWriter<W> {
    fn plain(&mut self, text: &str, keep: bool) -> Result<()> {
        if !keep {
            return Ok(());
        }

        writeln!(&mut self.dest, "{}", text)?;
        Ok(())
    }
}

/// The weave writer writes out the contents of a weave to a file.
struct WeaveWriter<W: Write> {
    dest: BufWriter<W>,
}

impl <W: Write> Sink for WeaveWriter<W> {
    fn insert(&mut self, delta: usize) -> Result<()> {
        writeln!(&mut self.dest, "\x01I {}", delta)?;
        Ok(())
    }
    fn delete(&mut self, delta: usize) -> Result<()> {
        writeln!(&mut self.dest, "\x01D {}", delta)?;
        Ok(())
    }
    fn end(&mut self, delta: usize) -> Result<()> {
        writeln!(&mut self.dest, "\x01E {}", delta)?;
        Ok(())
    }
    fn plain(&mut self, text: &str, _keep: bool) -> Result<()> {
        writeln!(&mut self.dest, "{}", text)?;
        Ok(())
    }
}
<commit_msg>weave: Anchor diff command pattern<commit_after>//! Add a delta to a weave file.

use regex::Regex;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::fs::{File, rename, remove_file};
use std::mem::replace;
use std::io::{self, BufRead, BufReader, BufWriter, Write};
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::rc::Rc;

use header::Header;
use NamingConvention;
use {Parser, Sink};
use Result;
use WriterInfo;

/// A DeltaWriter is used to write a new delta.  Data should be written to the writer, and then the
/// `close` method called to update the weave file with the new delta.
pub struct DeltaWriter<'n> {
    naming: &'n NamingConvention,

    // Where the temporary file will be written.
    temp: Option<WriterInfo>,

    // The base delta.
    base: usize,

    // The new delta.
    new_delta: usize,

    // The name of the file with the base written to it.
    base_name: PathBuf,

    // The regex for parsing diff output.
    diff_re: Regex,

    // The header to be written for the new delta.
    header: Header,
}

impl<'n> DeltaWriter<'n> {
    /// Construct a writer for a new delta.  The naming convention and the tags set where the names
    /// will be written, and what tags will be associated with the convention.  The `base` is the
    /// existing delta that the change should be based on.
    pub fn new<'a, 'b, I>(nc: &NamingConvention, tags: I, base: usize) -> Result<DeltaWriter>
        where I: Iterator<Item=(&'a str, &'b str)>
    {
        // Copy the tags, making sure there is a "name", which is used to index.
        // TODO: Ensure that "name" is unique among the existing deltas.
        let mut ntags = BTreeMap::new();
        for (k, v) in tags {
            ntags.insert(k.to_owned(), v.to_owned());
        }
        if !ntags.contains_key("name") {
            return Err("DeltaWriter does not contain a tag \"name\"".into());
        }

        // Extract the base delta to a file.
        let bfd = File::open(nc.main_file())?;
        let lines = BufReader::new(bfd).lines();
        let (base_name, base_file) = nc.temp_file()?;
        let dsink = Rc::new(RefCell::new(RevWriter { dest: BufWriter::new(base_file) }));
        let mut header = {
            let mut parser = Parser::new(lines, dsink, base)?;
            match parser.parse_to(0) {
                Ok(0) => (),
                Ok(_) => panic!("Unexpected stop of parser"),
                Err(e) => return Err(e),
            }
            parser.get_header().clone()
        };
        let new_delta = header.add(ntags)?;

        let (new_name, new_file) = nc.temp_file()?;

        Ok(DeltaWriter {
            naming: nc,
            temp: Some(WriterInfo {
                name: new_name,
                file: new_file,
            }),
            base: base,
            new_delta: new_delta,
            base_name: base_name,
            diff_re: Regex::new(r"^(\d+)(,(\d+))?([acd]).*$").unwrap(),
            header: header,
        })
    }

    pub fn close(mut self) -> Result<()> {
        // Close the temporary file, getting its name.
        let temp = replace(&mut self.temp, None);
        let temp_name = match temp {
            Some(mut wi) => {
                wi.file.flush()?;
                drop(wi.file);
                wi.name
            }
            None => return Err("DeltaWriter already closed".into()),
        };

        let (tweave_name, tweave_file) = self.naming.temp_file()?;
        // TODO: Header from old.

        let old_fd = File::open(self.naming.main_file())?;
        let old_lines = BufReader::new(old_fd).lines();

        // Invoke diff on the files.
        let mut child = Command::new("diff")
            .arg(self.base_name.as_os_str())
            .arg(temp_name.as_os_str())
            .stdout(Stdio::piped())
            .spawn()?;

        {
            let lines = BufReader::new(child.stdout.as_mut().unwrap()).lines();
            let weave_write = Rc::new(RefCell::new(WeaveWriter { dest: BufWriter::new(tweave_file) }));
            let mut parser = Parser::new(old_lines, weave_write.clone(), self.base)?;

            self.header.write(&mut weave_write.borrow_mut().dest)?;

            let mut is_done = false;
            let mut is_adding = false;

            for line in lines {
                let line = line?;
                match self.diff_re.captures(&line) {
                    Some(cap) => {
                        // If adding, this completes the add.
                        if is_adding {
                            weave_write.borrow_mut().end(self.new_delta)?;
                            is_adding = false;
                        }

                        let left = cap.get(1).unwrap().as_str().parse::<usize>().unwrap();
                        let right = match cap.get(3) {
                            None => left,
                            Some(r) => r.as_str().parse().unwrap(),
                        };
                        let cmd = cap.get(4).unwrap().as_str().chars().next().unwrap();

                        if cmd == 'd' || cmd == 'c' {
                            // These include deletions.
                            match parser.parse_to(left)? {
                                0 => return Err("Unexpected eof".into()),
                                n if n == left => (),
                                _ => panic!("Unexpected parse result"),
                            }
                            weave_write.borrow_mut().delete(self.new_delta)?;
                            match parser.parse_to(right + 1) {
                                Ok(0) => is_done = true,
                                Ok(n) if n == right + 1 => (),
                                Ok(_) => panic!("Unexpected parse result"),
                                Err(e) => return Err(e),
                            }
                            weave_write.borrow_mut().end(self.new_delta)?;
                        } else {
                            match parser.parse_to(right + 1) {
                                Ok(0) => is_done = true,
                                Ok(n) if n == right + 1 => (),
                                Ok(_) => panic!("Unexpected parse result"),
                                Err(e) => return Err(e),
                            }
                        }

                        if cmd == 'c' || cmd == 'a' {
                            weave_write.borrow_mut().insert(self.new_delta)?;
                            is_adding = true;
                        }

                        continue;
                    },
                    None => (),
                }

                match line.chars().next() {
                    None => panic!("Unexpected blank line in diff"),
                    Some('<') => continue,
                    Some('-') => continue,
                    Some('>') => {
                        // Add lines should just be written as-is.
                        weave_write.borrow_mut().plain(&line[2..], true)?;
                    }
                    Some(_) => panic!("Unexpected diff line: {:?}", line),
                }
            }

            if is_adding {
                weave_write.borrow_mut().end(self.new_delta)?;
            }

            if !is_done {
                match parser.parse_to(0) {
                    Ok(0) => (),
                    Ok(_) => panic!("Unexpected non-eof"),
                    Err(e) => return Err(e),
                }
            }
        }

        match child.wait()?.code() {
            None => return Err("diff killed by signal".into()),
            Some(0) => (), // No diffs
            Some(1) => (), // Normal with diffs
            Some(n) => return Err(format!("diff returned error status: {}", n).into()),
        }

        // Now that is all done, clean up the temp files, and cycle the backup.
        let _ = rename(self.naming.main_file(), self.naming.backup_file());
        rename(tweave_name, self.naming.main_file())?;
        remove_file(&self.base_name)?;
        remove_file(&temp_name)?;

        Ok(())
    }
}

impl <'n> Write for DeltaWriter<'n> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.temp.as_mut()
            .expect("Attempt to write to DeltaWriter that is closed")
            .file.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.temp.as_mut()
            .expect("Attempt to flush DeltaWriter that is closed")
            .file.flush()
    }
}

struct RevWriter<W: Write> {
    dest: BufWriter<W>,
}

impl<W: Write> Sink for RevWriter<W> {
    fn plain(&mut self, text: &str, keep: bool) -> Result<()> {
        if !keep {
            return Ok(());
        }

        writeln!(&mut self.dest, "{}", text)?;
        Ok(())
    }
}

/// The weave writer writes out the contents of a weave to a file.
struct WeaveWriter<W: Write> {
    dest: BufWriter<W>,
}

impl <W: Write> Sink for WeaveWriter<W> {
    fn insert(&mut self, delta: usize) -> Result<()> {
        writeln!(&mut self.dest, "\x01I {}", delta)?;
        Ok(())
    }
    fn delete(&mut self, delta: usize) -> Result<()> {
        writeln!(&mut self.dest, "\x01D {}", delta)?;
        Ok(())
    }
    fn end(&mut self, delta: usize) -> Result<()> {
        writeln!(&mut self.dest, "\x01E {}", delta)?;
        Ok(())
    }
    fn plain(&mut self, text: &str, _keep: bool) -> Result<()> {
        writeln!(&mut self.dest, "{}", text)?;
        Ok(())
    }
}
<|endoftext|>