<commit_before>use std::str;

macro_rules! eof {
    ($buf:expr, $i:expr) => (
        if $buf.len() == $i {
            return Ok(Status::Partial);
        }
    )
}
macro_rules! next {
    ($buf:expr, $i:ident) => ({
        let buf = $buf;
        eof!(buf, $i);
        let ret = unsafe { *$buf.get_unchecked($i) };
        $i += 1;
        ret
    })
}

macro_rules! expect {
    ($buf:ident[$i:ident] == $pat:pat => $ret:expr) => {
        match next!($buf, $i) {
            v@$pat => v,
            _ => return $ret
        }
    }
}

/// Determines if byte is a token char.
///
/// > ```notrust
/// > token          = 1*tchar
/// >
/// > tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*"
/// >                / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
/// >                / DIGIT / ALPHA
/// >                ; any VCHAR, except delimiters
/// > ```
macro_rules! is_token {
    ($b:expr) => {
        $b > 0x1F && $b < 0x7F
    }
}

macro_rules! parse {
    ($obj:ident.$field:ident = parse_version ($buf:expr)) => ({
        $obj.$field = match try!(parse_version($buf)) {
            Status::Complete(val) => {
                $buf = $buf.split_at(8).1;
                Some(val)
            },
            Status::Partial => return Ok(Status::Partial)
        }
    });
    ($obj:ident.$field:ident = parse_code ($buf:expr)) => ({
        $obj.$field = match try!(parse_code($buf)) {
            Status::Complete(val) => {
                $buf = $buf.split_at(3).1;
                Some(val)
            },
            Status::Partial => return Ok(Status::Partial)
        }
    });
    ($obj:ident.$field:ident = $action:ident ($buf:expr)) => ({
        $obj.$field = match try!($action($buf)) {
            Status::Complete(val) => {
                $buf = $buf.split_at(val.len()).1;
                Some(val)
            },
            Status::Partial => return Ok(Status::Partial)
        }
    })
}

macro_rules! newline {
    ($buf:ident) => ({
        let mut i = 0;
        eof!($buf, i);
        match next!($buf, i) {
            b'\r' => {
                expect!($buf[i] == b'\n' => Ok(Status::Partial));
                $buf = $buf.split_at(2).1;
            },
            b'\n' => {
                $buf = $buf.split_at(1).1;
            },
            _ => return Err(Error::NewLine)
        }
    })
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Error {
    HeaderName,
    HeaderValue,
    NewLine,
    Status,
    Token,
    TooManyHeaders,
    Version
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Status<T> {
    Complete(T),
    Partial
}

impl<T> Status<T> {
    #[inline]
    pub fn is_complete(&self) -> bool {
        match *self {
            Status::Complete(..) => true,
            Status::Partial => false
        }
    }

    #[inline]
    pub fn is_partial(&self) -> bool {
        match *self {
            Status::Complete(..) => false,
            Status::Partial => true
        }
    }

    #[inline]
    pub fn unwrap(self) -> T {
        match self {
            Status::Complete(t) => t,
            Status::Partial => panic!("Tried to unwrap Status::Partial")
        }
    }
}

pub struct Request<'a> {
    pub method: Option<&'a str>,
    pub path: Option<&'a str>,
    pub version: Option<u8>,
    pub headers: &'a mut [Header<'a>]
}

impl<'a> Request<'a> {
    #[inline]
    pub fn new(headers: &'a mut [Header<'a>]) -> Request<'a> {
        Request {
            method: None,
            path: None,
            version: None,
            headers: headers,
        }
    }

    pub fn parse(&mut self, mut buf: &'a [u8]) -> Result<Status<usize>, Error> {
        let orig_len = buf.len();
        parse!(self.method = parse_token(buf));
        buf = buf.split_at(1).1;
        parse!(self.path = parse_token(buf));
        buf = buf.split_at(1).1;
        parse!(self.version = parse_version(buf));
        newline!(buf);

        let len = orig_len - buf.len();
        let headers_len = match try!(parse_headers(self.headers, buf)) {
            Status::Complete(len) => len,
            Status::Partial => return Ok(Status::Partial)
        };

        Ok(Status::Complete(len + headers_len))
    }
}

pub struct Response<'a> {
    pub version: Option<u8>,
    pub code: Option<u16>,
    pub reason: Option<&'a str>,
    pub headers: &'a mut [Header<'a>]
}

impl<'a> Response<'a> {
    #[inline]
    pub fn new(headers: &'a mut [Header<'a>]) -> Response<'a> {
        Response {
            version: None,
            code: None,
            reason: None,
            headers: headers,
        }
    }

    pub fn parse(&mut self, mut buf: &'a [u8]) -> Result<Status<usize>, Error> {
        let orig_len = buf.len();

        parse!(self.version = parse_version(buf));
        buf = buf.split_at(1).1;
        parse!(self.code = parse_code(buf));
        buf = buf.split_at(1).1;
        parse!(self.reason = parse_token(buf));
        newline!(buf);

        let headers_len = match try!(parse_headers(self.headers, buf)) {
            Status::Complete(len) => len,
            Status::Partial => return Ok(Status::Partial)
        };
        Ok(Status::Complete(orig_len - buf.len() - headers_len))
    }
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Header<'a> {
    pub name: &'a str,
    pub value: &'a [u8],
}

#[inline]
fn parse_version(buf: &[u8]) -> Result<Status<u8>, Error> {
    let mut i = 0;

    expect!(buf[i] == b'H' => Err(Error::Version));
    expect!(buf[i] == b'T' => Err(Error::Version));
    expect!(buf[i] == b'T' => Err(Error::Version));
    expect!(buf[i] == b'P' => Err(Error::Version));
    expect!(buf[i] == b'/' => Err(Error::Version));
    expect!(buf[i] == b'1' => Err(Error::Version));
    expect!(buf[i] == b'.' => Err(Error::Version));
    match next!(buf, i) {
        b'0' => Ok(Status::Complete(0)),
        b'1' => Ok(Status::Complete(1)),
        _ => Err(Error::Version)
    }
}

#[inline]
fn parse_token(buf: &[u8]) -> Result<Status<&str>, Error> {
    let mut i: usize = 0;
    loop {
        let b = next!(buf, i);
        if b == b' ' || b == b'\r' || b == b'\n' {
            return Ok(Status::Complete(unsafe {
                // all bytes up till `i` must have been `is_token`.
                str::from_utf8_unchecked(&buf[..i - 1])
            }));
        } else if !is_token!(b) {
            return Err(Error::Token);
        }
    }
}

#[inline]
fn parse_code(buf: &[u8]) -> Result<Status<u16>, Error> {
    let mut i = 0;
    let hundreds = expect!(buf[i] == b'0'...b'9' => Err(Error::Status));
    let tens = expect!(buf[i] == b'0'...b'9' => Err(Error::Status));
    let ones = expect!(buf[i] == b'0'...b'9' => Err(Error::Status));

    Ok(Status::Complete((hundreds - b'0') as u16 * 100 +
                        (tens - b'0') as u16 * 10 +
                        (ones - b'0') as u16))
}

fn parse_headers<'a>(headers: &mut [Header<'a>], buf: &'a [u8]) -> Result<Status<usize>, Error> {
    let mut i: usize = 0;
    let mut last_i: usize = 0;
    for header in headers {
        // a newline here means the head is over!
        eof!(buf, i);
        let b = unsafe { *buf.get_unchecked(i) };
        if b == b'\r' {
            i += 1;
            expect!(buf[i] == b'\n' => Err(Error::NewLine));
            return Ok(Status::Complete(i));
        } else if b == b'\n' {
            i += 1;
            return Ok(Status::Complete(i));
        }

        // parse header name until colon
        loop {
            let b = next!(buf, i);
            if b == b':' {
                header.name = unsafe {
                    str::from_utf8_unchecked(&buf[last_i..i - 1])
                }; //TODO: remove bounds checks
                break;
            } else if !is_token!(b) {
                return Err(Error::HeaderName);
            }
        }

        // eat white space between colon and value
        loop {
            let b = next!(buf, i);
            if !(b == b' ' || b == b'\t') {
                i -= 1;
                last_i = i;
                break;
            }
        }

        // parse value till EOL
        loop {
            let b = next!(buf, i);
            if !is_token!(b) {
                if b == b'\r' {
                    expect!(buf[i] == b'\n' => Err(Error::HeaderValue));
                    header.value = &buf[last_i..i - 2];
                    break;
                } else if b == b'\n' {
                    header.value = &buf[last_i..i - 1];
                    break;
                } else {
                    return Err(Error::HeaderValue);
                }
                last_i = i;
            }
        }
    }

    Err(Error::TooManyHeaders)
}

#[cfg(test)]
mod tests {
    use super::{Request, Response, Header};

    #[test]
    fn test_request_complete() {
        let mut headers = [Header{ name: "", value: &[] }; 16];
        let mut req = Request::new(&mut headers[]);
        let status = req.parse(b"GET / HTTP/1.1\r\n\r\n").unwrap();
        assert!(status.is_complete());
        assert_eq!(req.method.unwrap(), "GET");
        assert_eq!(req.path.unwrap(), "/");
        assert_eq!(req.version.unwrap(), 1);

        let mut headers = [Header{ name: "", value: &[] }; 16];
        let mut req = Request::new(&mut headers[]);
        let status = req.parse(b"GET / HTTP/1.1\r\nHost: foo.com\r\n\r\n").unwrap();
        assert!(status.is_complete());
        assert_eq!(req.method.unwrap(), "GET");
        assert_eq!(req.path.unwrap(), "/");
        assert_eq!(req.version.unwrap(), 1);
        assert_eq!(req.headers[0].name, "Host");
        assert_eq!(req.headers[0].value, b"foo.com");

    }

    #[test]
    fn test_request_partial() {
        let mut headers = [Header{ name: "", value: &[] }; 16];
        let mut req = Request::new(&mut headers[]);
        assert!(req.parse(b"GET").unwrap().is_partial());
        assert!(req.method.is_none());

        let mut headers = [Header{ name: "", value: &[] }; 16];
        let mut req = Request::new(&mut headers);
        assert!(req.parse(b"GET ").unwrap().is_partial());
        assert_eq!(req.method.unwrap(), "GET");
        assert!(req.path.is_none());
    }

    #[test]
    fn test_response_complete() {
        let mut headers = [Header{ name: "", value: &[] }; 16];
        let mut res = Response::new(&mut headers[]);
        assert!(res.parse(b"HTTP/1.1 200 OK\r\n\r\n").unwrap().is_complete());
        assert_eq!(res.version.unwrap(), 1);
        assert_eq!(res.code.unwrap(), 200);
        assert_eq!(res.reason.unwrap(), "OK");
    }
}
<commit_msg>adding tests (and fixes)<commit_after>#![allow(unused_assignments)]

use std::str;

macro_rules! eof {
    ($buf:expr, $i:expr) => (
        if $buf.len() == $i {
            return Ok(Status::Partial);
        }
    )
}
macro_rules! next {
    ($buf:expr, $i:ident) => ({
        let buf = $buf;
        eof!(buf, $i);
        let ret = unsafe { *$buf.get_unchecked($i) };
        $i += 1;
        ret
    })
}

macro_rules! expect {
    ($buf:ident[$i:ident] == $pat:pat => $ret:expr) => {
        match next!($buf, $i) {
            v@$pat => v,
            _ => return $ret
        }
    }
}

/// Determines if byte is a token char.
///
/// > ```notrust
/// > token          = 1*tchar
/// >
/// > tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*"
/// >                / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
/// >                / DIGIT / ALPHA
/// >                ; any VCHAR, except delimiters
/// > ```
macro_rules! is_token {
    ($b:expr) => {
        $b > 0x1F && $b < 0x7F
    }
}

macro_rules! parse {
    ($obj:ident.$field:ident = parse_version ($buf:expr)) => ({
        $obj.$field = match try!(parse_version($buf)) {
            Status::Complete(val) => {
                $buf = $buf.split_at(8).1;
                Some(val)
            },
            Status::Partial => return Ok(Status::Partial)
        }
    });
    ($obj:ident.$field:ident = parse_code ($buf:expr)) => ({
        $obj.$field = match try!(parse_code($buf)) {
            Status::Complete(val) => {
                $buf = $buf.split_at(3).1;
                Some(val)
            },
            Status::Partial => return Ok(Status::Partial)
        }
    });
    ($obj:ident.$field:ident = $action:ident ($buf:expr)) => ({
        $obj.$field = match try!($action($buf)) {
            Status::Complete(val) => {
                $buf = $buf.split_at(val.len()).1;
                Some(val)
            },
            Status::Partial => return Ok(Status::Partial)
        }
    })
}

macro_rules! newline {
    ($buf:ident) => ({
        let mut i = 0;
        eof!($buf, i);
        match next!($buf, i) {
            b'\r' => {
                expect!($buf[i] == b'\n' => Ok(Status::Partial));
                $buf = $buf.split_at(2).1;
            },
            b'\n' => {
                $buf = $buf.split_at(1).1;
            },
            _ => return Err(Error::NewLine)
        }
    })
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Error {
    HeaderName,
    HeaderValue,
    NewLine,
    Status,
    Token,
    TooManyHeaders,
    Version
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Status<T> {
    Complete(T),
    Partial
}

impl<T> Status<T> {
    #[inline]
    pub fn is_complete(&self) -> bool {
        match *self {
            Status::Complete(..) => true,
            Status::Partial => false
        }
    }

    #[inline]
    pub fn is_partial(&self) -> bool {
        match *self {
            Status::Complete(..) => false,
            Status::Partial => true
        }
    }

    #[inline]
    pub fn unwrap(self) -> T {
        match self {
            Status::Complete(t) => t,
            Status::Partial => panic!("Tried to unwrap Status::Partial")
        }
    }
}

pub struct Request<'a> {
    pub method: Option<&'a str>,
    pub path: Option<&'a str>,
    pub version: Option<u8>,
    pub headers: &'a mut [Header<'a>]
}

impl<'a> Request<'a> {
    #[inline]
    pub fn new(headers: &'a mut [Header<'a>]) -> Request<'a> {
        Request {
            method: None,
            path: None,
            version: None,
            headers: headers,
        }
    }

    pub fn parse(&mut self, mut buf: &'a [u8]) -> Result<Status<usize>, Error> {
        let orig_len = buf.len();
        parse!(self.method = parse_token(buf));
        buf = buf.split_at(1).1;
        parse!(self.path = parse_token(buf));
        buf = buf.split_at(1).1;
        parse!(self.version = parse_version(buf));
        newline!(buf);

        let len = orig_len - buf.len();
        let headers_len = match try!(parse_headers(self.headers, buf)) {
            Status::Complete(len) => len,
            Status::Partial => return Ok(Status::Partial)
        };

        Ok(Status::Complete(len + headers_len))
    }
}

pub struct Response<'a> {
    pub version: Option<u8>,
    pub code: Option<u16>,
    pub reason: Option<&'a str>,
    pub headers: &'a mut [Header<'a>]
}

impl<'a> Response<'a> {
    #[inline]
    pub fn new(headers: &'a mut [Header<'a>]) -> Response<'a> {
        Response {
            version: None,
            code: None,
            reason: None,
            headers: headers,
        }
    }

    pub fn parse(&mut self, mut buf: &'a [u8]) -> Result<Status<usize>, Error> {
        let orig_len = buf.len();

        parse!(self.version = parse_version(buf));
        buf = buf.split_at(1).1;
        parse!(self.code = parse_code(buf));
        buf = buf.split_at(1).1;
        parse!(self.reason = parse_token(buf));
        newline!(buf);

        let len = orig_len - buf.len();
        let headers_len = match try!(parse_headers(self.headers, buf)) {
            Status::Complete(len) => len,
            Status::Partial => return Ok(Status::Partial)
        };
        Ok(Status::Complete(len + headers_len))
    }
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Header<'a> {
    pub name: &'a str,
    pub value: &'a [u8],
}

#[inline]
fn parse_version(buf: &[u8]) -> Result<Status<u8>, Error> {
    let mut i = 0;

    expect!(buf[i] == b'H' => Err(Error::Version));
    expect!(buf[i] == b'T' => Err(Error::Version));
    expect!(buf[i] == b'T' => Err(Error::Version));
    expect!(buf[i] == b'P' => Err(Error::Version));
    expect!(buf[i] == b'/' => Err(Error::Version));
    expect!(buf[i] == b'1' => Err(Error::Version));
    expect!(buf[i] == b'.' => Err(Error::Version));
    match next!(buf, i) {
        b'0' => Ok(Status::Complete(0)),
        b'1' => Ok(Status::Complete(1)),
        _ => Err(Error::Version)
    }
}

#[inline]
fn parse_token(buf: &[u8]) -> Result<Status<&str>, Error> {
    let mut i: usize = 0;
    loop {
        let b = next!(buf, i);
        if b == b' ' || b == b'\r' || b == b'\n' {
            return Ok(Status::Complete(unsafe {
                // all bytes up till `i` must have been `is_token`.
                str::from_utf8_unchecked(&buf[..i - 1])
            }));
        } else if !is_token!(b) {
            return Err(Error::Token);
        }
    }
}

#[inline]
fn parse_code(buf: &[u8]) -> Result<Status<u16>, Error> {
    let mut i = 0;
    let hundreds = expect!(buf[i] == b'0'...b'9' => Err(Error::Status));
    let tens = expect!(buf[i] == b'0'...b'9' => Err(Error::Status));
    let ones = expect!(buf[i] == b'0'...b'9' => Err(Error::Status));

    Ok(Status::Complete((hundreds - b'0') as u16 * 100 +
                        (tens - b'0') as u16 * 10 +
                        (ones - b'0') as u16))
}

fn parse_headers<'a>(headers: &mut [Header<'a>], buf: &'a [u8]) -> Result<Status<usize>, Error> {
    let mut i: usize = 0;
    let mut last_i: usize = 0;
    for header in headers {
        // a newline here means the head is over!
        eof!(buf, i);
        let b = unsafe { *buf.get_unchecked(i) };
        if b == b'\r' {
            i += 1;
            expect!(buf[i] == b'\n' => Err(Error::NewLine));
            return Ok(Status::Complete(i));
        } else if b == b'\n' {
            i += 1;
            return Ok(Status::Complete(i));
        }

        last_i = i;
        // parse header name until colon
        loop {
            let b = next!(buf, i);
            if b == b':' {
                header.name = unsafe {
                    str::from_utf8_unchecked(&buf[last_i..i - 1])
                }; //TODO: remove bounds checks
                break;
            } else if !is_token!(b) {
                return Err(Error::HeaderName);
            }
        }

        // eat white space between colon and value
        loop {
            let b = next!(buf, i);
            if !(b == b' ' || b == b'\t') {
                i -= 1;
                last_i = i;
                break;
            }
        }

        // parse value till EOL
        loop {
            let b = next!(buf, i);
            if !is_token!(b) {
                if (b < 0o40 && b != 0o11) || b == 0o177 {
                    if b == b'\r' {
                        expect!(buf[i] == b'\n' => Err(Error::HeaderValue));
                        header.value = &buf[last_i..i - 2];
                        break;
                    } else if b == b'\n' {
                        header.value = &buf[last_i..i - 1];
                        break;
                    } else {
                        return Err(Error::HeaderValue);
                    }
                }
            }
        }
    }

    Err(Error::TooManyHeaders)
}

#[cfg(test)]
mod tests {
    use super::{Request, Response, Header, Status};

    macro_rules! req {
        ($name:ident, $buf:expr, $closure:expr) => (
            req! {$name, $buf, Ok(Status::Complete($buf.len())), $closure }
        );
        ($name:ident, $buf:expr, $len:expr, $closure:expr) => (
        #[test]
        fn $name() {
            let mut headers = [Header{ name: "", value: &[] }; 16];
            let mut req = Request::new(&mut headers[..]);
            let closure: Box<Fn(Request)> = Box::new($closure);
            let status = req.parse(unsafe { ::std::mem::transmute($buf) });
            assert_eq!(status, $len);
            closure(req);
        }
        )
    }

    req! {
        test_request_simple,
        "GET / HTTP/1.1\r\n\r\n",
        |req| {
            assert_eq!(req.method.unwrap(), "GET");
            assert_eq!(req.path.unwrap(), "/");
            assert_eq!(req.version.unwrap(), 1);
        }
    }

    req! {
        test_request_headers,
        "GET / HTTP/1.1\r\nHost: foo.com\r\nCookie: \r\n\r\n",
        |req| {
            assert_eq!(req.method.unwrap(), "GET");
            assert_eq!(req.path.unwrap(), "/");
            assert_eq!(req.version.unwrap(), 1);
            assert_eq!(req.headers[0].name, "Host");
            assert_eq!(req.headers[0].value, b"foo.com");
            assert_eq!(req.headers[1].name, "Cookie");
            assert_eq!(req.headers[1].value, b"");
        }
    }

    req! {
        test_request_multibyte,
        b"GET / HTTP/1.1\r\nHost: foo.com\r\nUser-Agent: \xe3\x81\xb2\xe3/1.0\r\n\r\n",
        |req| {
            assert_eq!(req.method.unwrap(), "GET");
            assert_eq!(req.path.unwrap(), "/");
            assert_eq!(req.version.unwrap(), 1);
            assert_eq!(req.headers[0].name, "Host");
            assert_eq!(req.headers[0].value, b"foo.com");
            assert_eq!(req.headers[1].name, "User-Agent");
            assert_eq!(req.headers[1].value, b"\xe3\x81\xb2\xe3/1.0");
        }
    }

    req! {
        test_request_partial,
        "GET / HTTP/1.1\r\n\r", Ok(Status::Partial),
        |_req| {}
    }

    macro_rules! res {
        ($name:ident, $buf:expr, $closure:expr) => (
            res! {$name, $buf, Ok(Status::Complete($buf.len())), $closure }
        );
        ($name:ident, $buf:expr, $len:expr, $closure:expr) => (
        #[test]
        fn $name() {
            let mut headers = [Header{ name: "", value: &[] }; 16];
            let mut res = Response::new(&mut headers[..]);
            let closure: Box<Fn(Response)> = Box::new($closure);
            let status = res.parse(unsafe { ::std::mem::transmute($buf.as_bytes()) });
            assert_eq!(status, $len);
            closure(res);
        }
        )
    }

    res! {
        test_response_simple,
        "HTTP/1.1 200 OK\r\n\r\n",
        |res| {
            assert_eq!(res.version.unwrap(), 1);
            assert_eq!(res.code.unwrap(), 200);
            assert_eq!(res.reason.unwrap(), "OK");
        }
    }
}
<|endoftext|>


<commit_before>use std::cmp::min;
use std::io::{Result, Error, ErrorKind};

use super::{ReadAt, WriteAt, Size};

impl ReadAt for Vec<u8> {
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> Result<usize> {
        self.as_slice().read_at(pos, buf)
    }
}

impl WriteAt for Vec<u8> {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> Result<usize> {
        // Ensure no overflow.
        if pos > (usize::max_value() as u64) {
            return Err(Error::new(ErrorKind::InvalidInput, "vector size too big"));
        }
        let pos = pos as usize;

        // Resize the vector so pos <= self.len().
        if pos >= self.len() {
            self.resize(pos as usize, 0);
        }

        // Copy anything that fits into existing space.
        let avail = min(self.len() - pos, buf.len());
        if avail > 0 {
            self[pos..(pos + avail)].copy_from_slice(&buf[..avail]);
        }

        // Extend with anything leftover.
        if avail < buf.len() {
            self.extend_from_slice(&buf[avail..]);
        }

        Ok(buf.len())
    }

    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}

impl Size for Vec<u8> {
    fn size(&self) -> Result<Option<u64>> {
        Ok(Some(self.len() as u64))
    }
}
<commit_msg>spell out io::Result some more<commit_after>use std::cmp::min;
use std::io;

use super::{ReadAt, WriteAt, Size};

impl ReadAt for Vec<u8> {
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
        self.as_slice().read_at(pos, buf)
    }
}

impl WriteAt for Vec<u8> {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
        // Ensure no overflow.
        if pos > (usize::max_value() as u64) {
            return Err(io::Error::new(io::ErrorKind::InvalidInput, "vector size too big"));
        }
        let pos = pos as usize;

        // Resize the vector so pos <= self.len().
        if pos >= self.len() {
            self.resize(pos as usize, 0);
        }

        // Copy anything that fits into existing space.
        let avail = min(self.len() - pos, buf.len());
        if avail > 0 {
            self[pos..(pos + avail)].copy_from_slice(&buf[..avail]);
        }

        // Extend with anything leftover.
        if avail < buf.len() {
            self.extend_from_slice(&buf[avail..]);
        }

        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Size for Vec<u8> {
    fn size(&self) -> io::Result<Option<u64>> {
        Ok(Some(self.len() as u64))
    }
}
<|endoftext|>


<commit_before>
use std::f32;
use std::vec;
use std::collections::HashMap;
use std::collections::hash_set::HashSet;

extern crate ocl;
use ocl::{ProQue, Buffer};

static KERNEL_SOURCE: &'static str = include_str!("kernel_source.cl");

type Dimension = (usize, usize);
type NodeId = usize;

//		ActivationFunction::Sigmoid => 1.0f32/(1.0 + (-value).exp()),

enum Operation {
	Input,
	MatrixMultiply(NodeId, NodeId),
	BinaryElement(NodeId, NodeId, Box<Fn(f32,f32)->f32>),
	UnaryElement(NodeId, Box<Fn(f32)->f32>),
}

struct Node {
	id : NodeId,
	shape : Dimension,
	operation : Operation,
}

struct Graph {
//	proque : ProQue,
	nodes : Vec<Node>,
}

impl Graph {
	fn new() -> Graph {
		Graph {
//			proque : ProQue::builder().src(KERNEL_SOURCE).dims([3]).build().unwrap(),
			nodes : vec![],
		}
	}

	// Graph methods
	fn get_output(&self, node_id : NodeId, input_map : &HashMap<NodeId, Vec<f32>>) -> Vec<f32> {
		//(node.operation)(&self, input_map)
		match self.nodes[node_id].operation {
			Operation::Input => { input_map.get(&node_id).unwrap().clone() },
			Operation::MatrixMultiply(n1, n2) => {
				// Verify shapes
				let a_width = self.nodes[n1].shape.1; // Columns (j)
				let a_height = self.nodes[n1].shape.0; // Rows (i)
				let b_width = self.nodes[n2].shape.1; // Columns (k)
				let b_height = self.nodes[n2].shape.0; // Rows (j)
				let c_width = b_width;
				let c_height = a_height;
				assert_eq!(a_width, b_height);

				let mut result = vec![0.0; a_height*b_width];

				// Set up the buffer for this node.
				let a : Vec<f32> = self.get_output(n1, &input_map);
				let b : Vec<f32> = self.get_output(n2, &input_map);

				// Multiply
				for i in 0..a_height { // Column [Iterating over row]
					for k in 0..b_width { // Row/Width [Iterating over column]
						let mut accumulator = 0.0;
						for j in 0..a_width { // Column
							accumulator += a[j + i*a_width]*b[k + j*b_width];
						}
						result[k + i*c_width] = accumulator;
					}
				}

				result
			},
			Operation::BinaryElement(n1, n2, ref f) => {
				let a : Vec<f32> = self.get_output(n1, &input_map);
				let b : Vec<f32> = self.get_output(n2, &input_map);
				let mut result = vec![0.0; a.len()];
				let vec_len = result.len();

				for i in 0..vec_len {
					result[i] = f(a[i], b[i]);
				}

				result
			},
			Operation::UnaryElement(n1, ref f) => {
				let a : Vec<f32> = self.get_output(n1, &input_map);
				let vec_len = a.len();
				let mut result = vec![0.0; vec_len];

				for i in 0..vec_len {
					result[i] = f(a[i]);
				}
				result
			}
		}
	}

	// Node creation
	fn new_input(&mut self, shape : Dimension) -> NodeId {
		let mut n = Node {
			id : 0,
			shape : shape,
			operation : Operation::Input,
		};
		self.nodes.push(n);
		let id = self.nodes.len()-1;
		n.id = id;
		id
	}

	fn new_matmul(&mut self, node_a_id : NodeId, node_b_id : NodeId) -> NodeId {
		let mut n = Node {
			id : 0,
			shape : (self.nodes[node_a_id].shape.0, self.nodes[node_b_id].shape.1),
			//operation : Operation::BinaryElement(node_a_id, node_b_id, Box::new(|a, b| { 0.0 })),
			operation : Operation::MatrixMultiply(node_a_id, node_b_id),
		};
		self.nodes.push(n);
		let id = self.nodes.len()-1;
		n.id = id;
		id
	}
}

#[cfg(test)]
mod tests {
	use super::{Graph, Dimension, Node, NodeId};
	use std::collections::HashMap;

	#[test]
	fn test_identity() {
		// Build graph
		let mut input = HashMap::new();
		let mut g = Graph::new();
		let m : NodeId = g.new_input((3, 3));
		let n : NodeId = g.new_input((1, 3));
		let o = g.new_matmul(n, m);
		let j : NodeId = g.new_input((3, 5));
		let k = g.new_matmul(m, j);

		// Shape check
		assert_eq!(g.nodes[m].shape, (3, 3));
		assert_eq!(g.nodes[n].shape, (1, 3));
		assert_eq!(g.nodes[o].shape, (1, 3));

		// Configure data
		input.insert(m, vec![
			1.0, 0.0, 0.0,
			0.0, 1.0, 0.0,
			0.0, 0.0, 1.0
		]);
		input.insert(n, vec![
			0.0, 1.0, 2.0
		]);
		input.insert(j, vec![
			1.0, 2.0, 3.0,
			4.0, 5.0, 6.0,
			7.0, 8.0, 9.0,
			10.0, 11.0, 12.0,
			13.0, 14.0, 15.0
		]);

		// Verify outputs
		let res = g.get_output(o, &input);
		assert_eq!(res[0], 0.0);
		assert_eq!(res[1], 1.0);
		assert_eq!(res[2], 2.0);
		let res2 = g.get_output(k, &input);
		for i in 0..15 {
			assert_eq!(res2[i], (i as f32+1.0));
		}
	}

    #[test]
    fn integration_full_test() {
		let g = Graph::new();
    }
}
<commit_msg>Start adding backprop + autodiff.<commit_after>
use std::f32;
use std::vec;
use std::collections::HashMap;
use std::collections::hash_set::HashSet;

extern crate ocl;
use ocl::{ProQue, Buffer};

static KERNEL_SOURCE: &'static str = include_str!("kernel_source.cl");

type Dimension = (usize, usize);
type NodeId = usize;

//		ActivationFunction::Sigmoid => 1.0f32/(1.0 + (-value).exp()),

enum Operation {
	Input,
	MatrixMultiply(NodeId, NodeId),
	BinaryElement(NodeId, NodeId, Box<Fn(f32,f32)->f32>, Box<Fn(f32,f32)->f32>), // Node1, Node2, Fn, Derivative
	UnaryElement(NodeId, Box<Fn(f32)->f32>, Box<Fn(f32)->f32>), // Node1, Fn, Derivative
}

struct Node {
	id : NodeId,
	shape : Dimension,
	operation : Operation,
}

struct Graph {
//	proque : ProQue,
	nodes : Vec<Node>,
}

impl Graph {
	fn new() -> Graph {
		Graph {
//			proque : ProQue::builder().src(KERNEL_SOURCE).dims([3]).build().unwrap(),
			nodes : vec![],
		}
	}

	// Graph methods
	fn get_output(&self, node_id : NodeId, input_map : &HashMap<NodeId, Vec<f32>>) -> Vec<f32> {
		match self.nodes[node_id].operation {
			Operation::Input => { input_map.get(&node_id).unwrap().clone() },
			Operation::MatrixMultiply(n1, n2) => {
				// Verify shapes
				let a_width = self.nodes[n1].shape.1; // Columns (j)
				let a_height = self.nodes[n1].shape.0; // Rows (i)
				let b_width = self.nodes[n2].shape.1; // Columns (k)
				let b_height = self.nodes[n2].shape.0; // Rows (j)
				let c_width = b_width;
				let c_height = a_height;
				assert_eq!(a_width, b_height);

				let mut result = vec![0.0; a_height*b_width];

				// Set up the buffer for this node.
				let a : Vec<f32> = self.get_output(n1, &input_map);
				let b : Vec<f32> = self.get_output(n2, &input_map);

				// Multiply
				for i in 0..a_height { // Column [Iterating over row]
					for k in 0..b_width { // Row/Width [Iterating over column]
						let mut accumulator = 0.0;
						for j in 0..a_width { // Column
							accumulator += a[j + i*a_width]*b[k + j*b_width];
						}
						result[k + i*c_width] = accumulator;
					}
				}

				result
			},
			Operation::BinaryElement(n1, n2, ref f, _) => {
				let a : Vec<f32> = self.get_output(n1, &input_map);
				let b : Vec<f32> = self.get_output(n2, &input_map);
				let mut result = vec![0.0; a.len()];
				let vec_len = result.len();

				for i in 0..vec_len {
					result[i] = f(a[i], b[i]);
				}

				result
			},
			Operation::UnaryElement(n1, ref f, _) => {
				let a : Vec<f32> = self.get_output(n1, &input_map);
				let vec_len = a.len();
				let mut result = vec![0.0; vec_len];

				for i in 0..vec_len {
					result[i] = f(a[i]);
				}
				result
			}
		}
	}

	// TODO: Understand Tann's slides + Torch's updateOutput, updateGradInput, and accGradParameters

	fn get_gradient(&self, node_id : NodeId, wrt : NodeId, input_map : &HashMap<NodeId, Vec<f32>>) -> Vec<f32> {
		vec![]
/*
		match self.nodes[node_id].operation {
			Operation::Input => {
				vec![
					if node_id == wrt {
						1.0
					} else {
						0.0
					} ; self.nodes[node_id].shape.0*self.nodes[node_id].shape.1
				]
			},
			Operation::MatrixMultiply(n1, n2) => {
				let mut result = vec![0.0; a_height*b_width];
				result
			},
			Operation::BinaryElement(n1, n2, ref f) => {
				result
			},
			Operation::UnaryElement(n1, ref f) => {
				result
			}
		}
*/
	}

	// Node creation
	fn new_input(&mut self, shape : Dimension) -> NodeId {
		let mut n = Node {
			id : 0,
			shape : shape,
			operation : Operation::Input,
		};
		self.nodes.push(n);
		let id = self.nodes.len()-1;
		n.id = id;
		id
	}

	fn new_matmul(&mut self, node_a_id : NodeId, node_b_id : NodeId) -> NodeId {
		let mut n = Node {
			id : 0,
			shape : (self.nodes[node_a_id].shape.0, self.nodes[node_b_id].shape.1),
			//operation : Operation::BinaryElement(node_a_id, node_b_id, Box::new(|a, b| { 0.0 })),
			operation : Operation::MatrixMultiply(node_a_id, node_b_id),
		};
		self.nodes.push(n);
		let id = self.nodes.len()-1;
		n.id = id;
		id
	}

	fn new_inverse(&mut self, node_id : NodeId) -> NodeId {
		let mut n = Node {
			id: 0,
			shape : self.nodes[node_id].shape,
			operation : Operation::UnaryElement(node_id, Box::new(|x| { 1.0/x }), Box::new(|x| {x.ln()}) ),
		};
		self.nodes.push(n);
		let id = self.nodes.len()-1;
		n.id = id;
		id
	}

	fn new_scalar_broadcast(&mut self, node_id : NodeId, scalar : f32) -> NodeId {
		let mut n = Node {
			id : 0,
			shape : (self.nodes[node_id].shape.0, self.nodes[node_id].shape.1),
			operation : Operation::UnaryElement(node_id, Box::new(move |x| { x+scalar }), Box::new(move |x| { x + scalar })),
		};
		self.nodes.push(n);
		let id = self.nodes.len()-1;
		n.id = id;
		id
	}
}

#[cfg(test)]
mod tests {
	use super::{Graph, Dimension, Node, NodeId};
	use std::collections::HashMap;

	#[test]
	fn test_identity() {
		// Build graph
		let mut input = HashMap::new();
		let mut g = Graph::new();
		let m : NodeId = g.new_input((3, 3));
		let n : NodeId = g.new_input((1, 3));
		let o = g.new_matmul(n, m);
		let j : NodeId = g.new_input((3, 5));
		let k = g.new_matmul(m, j);

		// Shape check
		assert_eq!(g.nodes[m].shape, (3, 3));
		assert_eq!(g.nodes[n].shape, (1, 3));
		assert_eq!(g.nodes[o].shape, (1, 3));

		// Configure data
		input.insert(m, vec![
			1.0, 0.0, 0.0,
			0.0, 1.0, 0.0,
			0.0, 0.0, 1.0
		]);
		input.insert(n, vec![
			0.0, 1.0, 2.0
		]);
		input.insert(j, vec![
			1.0, 2.0, 3.0,
			4.0, 5.0, 6.0,
			7.0, 8.0, 9.0,
			10.0, 11.0, 12.0,
			13.0, 14.0, 15.0
		]);

		// Verify outputs
		let res = g.get_output(o, &input);
		assert_eq!(res[0], 0.0);
		assert_eq!(res[1], 1.0);
		assert_eq!(res[2], 2.0);
		let res2 = g.get_output(k, &input);
		for i in 0..15 {
			assert_eq!(res2[i], (i as f32+1.0));
		}
	}

    #[test]
    fn integration_full_test() {
		let g = Graph::new();
    }
}
<|endoftext|>


<commit_before>/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

Metadata (such as doc comments) is allowed on each ref.

# Semantic

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.

Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.

# Example

Using the macro:

```rust
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access. On stable Rust, the macro may need to allocate each static on the heap.

*/

#![cfg_attr(feature="nightly", feature(const_fn, core_intrinsics))]

#[cfg(not(feature="nightly"))]
pub mod lazy;

#[cfg(feature="nightly")]
#[path="nightly_lazy.rs"]
pub mod lazy;

#[macro_export]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(MAKE TY, $VIS, $(#[$attr])*, $N);
        impl ::std::ops::Deref for $N {
            type Target = $T;
            fn deref<'a>(&'a self) -> &'a $T {
                unsafe {
                    #[inline(always)]
                    fn __static_ref_initialize() -> $T { $e }

                    unsafe fn __stability() -> &'static $T {
                        lazy_static_create!(LAZY, $T);
                        LAZY.get(__static_ref_initialize)
                    }
                    __stability()
                }
            }
        }
        lazy_static!($($t)*);
    };
    (MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<commit_msg>Used the @ macro expansion prefix trick<commit_after>/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

Metadata (such as doc comments) is allowed on each ref.

# Semantic

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.

Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.

# Example

Using the macro:

```rust
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access. On stable Rust, the macro may need to allocate each static on the heap.

*/

#![cfg_attr(feature="nightly", feature(const_fn, core_intrinsics))]

#[cfg(not(feature="nightly"))]
pub mod lazy;

#[cfg(feature="nightly")]
#[path="nightly_lazy.rs"]
pub mod lazy;

#[macro_export]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    (@$VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@MAKE TY, $VIS, $(#[$attr])*, $N);
        impl ::std::ops::Deref for $N {
            type Target = $T;
            fn deref<'a>(&'a self) -> &'a $T {
                unsafe {
                    #[inline(always)]
                    fn __static_ref_initialize() -> $T { $e }

                    unsafe fn __stability() -> &'static $T {
                        lazy_static_create!(LAZY, $T);
                        LAZY.get(__static_ref_initialize)
                    }
                    __stability()
                }
            }
        }
        lazy_static!($($t)*);
    };
    (@MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (@MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<|endoftext|>


<commit_before>#![feature(alloc_system)]

extern crate alloc_system;
extern crate libc;
extern crate rustbox;

mod comms;
mod utils;
pub mod msg;
pub mod tui;

use std::cmp::max;
use std::io::Write;
use std::io;
use std::mem;

use comms::{Comms, CommsRet};
use msg::{Pfx, Msg};
use tui::tabbed::MsgSource;
use tui::{TUI, TUIRet, MsgTarget};

pub struct Tiny {
    /// A connection to a server is maintained by 'Comms'.
    comms    : Vec<Comms>,

    tui      : TUI,

    nick     : String,
    hostname : String,
    realname : String,
}

#[derive(PartialEq, Eq)]
enum LoopRet {
    Abort,
    Continue,
    Disconnected { fd : libc::c_int },
    UpdateFds,
}

impl Tiny {
    pub fn new(nick : String, hostname : String, realname : String) -> Tiny {
        Tiny {
            comms: Vec::with_capacity(1),
            tui: TUI::new(),
            nick: nick,
            hostname: hostname,
            realname: realname,
        }
    }

    pub fn mainloop(&mut self) {
        self.tui.new_server_tab("debug".to_string());

        loop {
            // Set up the descriptors for select()
            let mut fd_set : libc::fd_set = unsafe { mem::zeroed() };

            // 0 is stdin
            unsafe { libc::FD_SET(0, &mut fd_set); }

            let mut max_fd : libc::c_int = 0;
            for comm in self.comms.iter() {
                let fd = comm.get_raw_fd();
                max_fd = max(fd, max_fd);
                unsafe { libc::FD_SET(fd, &mut fd_set); }
            }

            let nfds = max_fd + 1;

            // Start the loop
            if self.mainloop_(fd_set, nfds) == LoopRet::Abort {
                break;
            }
        }
    }

    fn mainloop_(&mut self, fd_set : libc::fd_set, nfds : libc::c_int) -> LoopRet {
        loop {
            self.tui.draw();

            let mut fd_set_ = fd_set.clone();
            let ret =
                unsafe {
                    libc::select(nfds,
                                 &mut fd_set_,           // read fds
                                 std::ptr::null_mut(),   // write fds
                                 std::ptr::null_mut(),   // error fds
                                 std::ptr::null_mut())   // timeval
                };

            // A resize signal (SIGWINCH) causes select() to fail, but termbox's
            // signal handler runs and we need to run termbox's poll_event() to
            // be able to catch the resize event. So, when stdin is ready we
            // call the TUI event handler, but we also call it when select() is
            // interrupted for some reason, just to be able to handle resize
            // events.
            //
            // See also https://github.com/nsf/termbox/issues/71.
            if unsafe { ret == -1 || libc::FD_ISSET(0, &mut fd_set_) } {
                match self.handle_stdin() {
                    LoopRet::Abort => { return LoopRet::Abort; },
                    LoopRet::UpdateFds => { return LoopRet::UpdateFds; }
                    _ => {}
                }
            }

            // A socket is ready
            // TODO: Can multiple sockets be set in single select() call? I
            // assume yes for now.
            else {
                // Collecting comms to read in this Vec becuase Rust sucs.
                let mut comm_idxs = Vec::with_capacity(1);
                for (comm_idx, comm) in self.comms.iter_mut().enumerate() {
                    let fd = comm.get_raw_fd();
                    if unsafe { libc::FD_ISSET(fd, &mut fd_set_) } {
                        comm_idxs.push(comm_idx);
                    }
                }

                let mut abort = false;
                let mut reset_fds = false;
                for comm_idx in comm_idxs {
                    match self.handle_socket(comm_idx) {
                        LoopRet::Abort => { abort = true; },
                        LoopRet::Disconnected { .. } => {
                            let comm = self.comms.remove(comm_idx);
                            self.tui.add_err_msg("Disconnected.", &MsgTarget::AllServTabs {
                                serv_name: &comm.serv_name,
                            });
                            reset_fds = true;
                        },
                        _ => {}
                    }
                }

                if abort {
                    return LoopRet::Abort;
                } else if reset_fds {
                    return LoopRet::Continue;
                }
            }
        }
    }

    ////////////////////////////////////////////////////////////////////////////

    fn handle_stdin(&mut self) -> LoopRet {
        match self.tui.keypressed_peek() {
            TUIRet::Abort => LoopRet::Abort,
            TUIRet::Input { msg, from } => {
                writeln!(self.tui,
                         "Input source: {:#?}, msg: {}",
                         from, msg.iter().cloned().collect::<String>()).unwrap();

                writeln!(io::stderr(),
                         "Input source: {:#?}, msg: {}",
                         from, msg.iter().cloned().collect::<String>()).unwrap();

                // We know msg has at least one character as the TUI won't
                // accept it otherwise.
                if msg[0] == '/' {
                    self.handle_command(from, (&msg[ 1 .. ]).into_iter().cloned().collect())
                } else {
                    self.send_msg(from, msg);
                    LoopRet::Continue
                }
            },
            _ => LoopRet::Continue
        }
    }

    fn handle_command(&mut self, src : MsgSource, msg : String) -> LoopRet {
        let words : Vec<&str> = msg.split_whitespace().into_iter().collect();
        if words[0] == "connect" {
            self.connect(words[1]);
            LoopRet::UpdateFds
        } else if words[0] == "join" {
            self.join(src, words[1]);
            LoopRet::Continue
        } else if words[0] == "quit" {
            LoopRet::Abort
        } else {
            self.tui.add_err_msg(
                &format!("Unsupported command: {}", words[0]), &MsgTarget::CurrentTab);
            LoopRet::Continue
        }
    }

    fn connect(&mut self, serv_addr : &str) {
        match utils::drop_port(serv_addr) {
            None => {
                self.tui.add_err_msg("connect: Need a <host>:<port>", &MsgTarget::CurrentTab);
            },
            Some(serv_name) => {
                self.tui.new_server_tab(serv_name.to_owned());
                writeln!(self.tui, "Created tab: {}", serv_name).unwrap();
                self.tui.add_msg("Connecting...", &MsgTarget::Server { serv_name: serv_name });

                match Comms::try_connect(serv_addr, serv_name,
                                         &self.nick, &self.hostname, &self.realname) {
                    Ok(comms) => {
                        self.comms.push(comms);
                    },
                    Err(err) => {
                        self.tui.add_err_msg(&format!("Error: {}", err),
                                             &MsgTarget::Server { serv_name: serv_name });
                    }
                }
            }
        }
    }

    fn join(&mut self, src : MsgSource, chan : &str) {
        Msg::join(chan, &mut self.tui).unwrap(); // debug
        let comm = self.find_comm(src.serv_name()).unwrap();
        Msg::join(chan, comm).unwrap();
    }

    fn send_msg(&mut self, from : MsgSource, msg : Vec<char>) {
        let msg_string = msg.iter().cloned().collect::<String>();

        match from {
            MsgSource::Serv { .. } => {
                self.tui.add_err_msg("Can't send PRIVMSG to a server.", &MsgTarget::CurrentTab);
            },

            MsgSource::Chan { serv_name, chan_name } => {
                {
                    let comm = self.find_comm(&serv_name).unwrap();
                    Msg::privmsg(&chan_name, &msg_string, comm).unwrap();
                }
                self.tui.add_msg(&msg_string, &MsgTarget::Chan { serv_name: &serv_name,
                                                                 chan_name: &chan_name });
            },

            MsgSource::User { serv_name, nick } => {
                {
                    let comm = self.find_comm(&serv_name).unwrap();
                    Msg::privmsg(&nick, &msg_string, comm).unwrap();
                }
                self.tui.add_msg(&msg_string, &MsgTarget::User { serv_name: &serv_name, nick: &nick });
            }
        }
    }

    fn find_comm(&mut self, serv_name : &str) -> Option<&mut Comms> {
        for comm in self.comms.iter_mut() {
            if comm.serv_name == serv_name {
                return Some(comm);
            }
        }
        None
    }

    ////////////////////////////////////////////////////////////////////////////

    fn handle_socket(&mut self, comm_idx : usize) -> LoopRet {
        let mut disconnect : Option<libc::c_int> = None;

        let rets = {
            let mut comm = unsafe { self.comms.get_unchecked_mut(comm_idx) };
            comm.read_incoming_msg()
        };

        for ret in rets {
            // tui.show_msg_current_tab(&format!("{:?}", ret));
            writeln!(&mut io::stderr(), "incoming msg: {:?}", ret).unwrap();
            match ret {
                CommsRet::Disconnected { fd } => {
                    disconnect = Some(fd);
                },
                CommsRet::Err { err_msg } => {
                    self.tui.add_err_msg(&err_msg, &MsgTarget::Server {
                        serv_name: & unsafe { self.comms.get_unchecked(comm_idx) }.serv_name
                    });
                },
                CommsRet::IncomingMsg { pfx, ty, args } => {
                    self.handle_incoming_msg(comm_idx, &pfx, &ty, args);
                },
                CommsRet::SentMsg { .. } => {
                    // TODO: Probably just ignore this?
                }
            }
        }

        if let Some(fd) = disconnect {
            LoopRet::Disconnected { fd: fd }
        } else {
            LoopRet::Continue
        }
    }

    fn handle_incoming_msg(&mut self, comm_idx : usize,
                           pfx : &Pfx, ty : &str, args : Vec<String>) {
        if ty == "JOIN" {
            let chan = &args[0];
            let serv_name = & unsafe { &self.comms.get_unchecked(comm_idx) }.serv_name;
            match pfx {
                &Pfx::Server(ref serv) => {
                    // This doesn't make any sense, log it.
                    writeln!(self.tui, "Weird JOIN message with server prefix {}", serv).unwrap();
                },
                &Pfx::User { ref nick, .. } => {
                    if *nick == self.nick {
                        self.tui.new_chan_tab(serv_name.to_owned(), chan.to_owned());
                    } else {
                        // TODO
                    }
                }
            }
        }

        else if ty == "PRIVMSG" {
            debug_assert!(args.len() == 2);
            let target = &args[0];
            let msg = &args[1];

            let comm = unsafe { &self.comms.get_unchecked(comm_idx) };

            if target.as_bytes()[0] == b'#' {
                self.tui.add_msg(&msg, &MsgTarget::Chan {
                    serv_name: &comm.serv_name,
                    chan_name: &target,
                });
            }

            else if target == &self.nick {
                let msg_target = pfx_to_target(pfx, &comm.serv_name);
                self.tui.add_msg(msg, &msg_target);
            }
        }

        else {
            // Just log for now
            writeln!(self.tui,
                     "Ignoring incoming msg:\npfx: {:?}\nty: {}\nargs: {:?}",
                     pfx, ty, args).unwrap();
        }
    }
}

fn pfx_to_target<'a>(pfx : &'a Pfx, curr_serv : &'a str) -> MsgTarget<'a> {
    match pfx {
        &Pfx::Server(ref serv_name) => MsgTarget::Server { serv_name: serv_name },
        &Pfx::User { ref nick, .. } => MsgTarget::User { serv_name: curr_serv, nick: nick },
    }
}
<commit_msg>better handling of PRIVMSG and NOTICE msgs<commit_after>#![feature(alloc_system)]

extern crate alloc_system;
extern crate libc;
extern crate rustbox;

mod comms;
mod utils;
pub mod msg;
pub mod tui;

use std::cmp::max;
use std::io::Write;
use std::io;
use std::mem;

use comms::{Comms, CommsRet};
use msg::{Pfx, Msg};
use tui::tabbed::MsgSource;
use tui::{TUI, TUIRet, MsgTarget};

pub struct Tiny {
    /// A connection to a server is maintained by 'Comms'.
    comms    : Vec<Comms>,

    tui      : TUI,

    nick     : String,
    hostname : String,
    realname : String,
}

#[derive(PartialEq, Eq)]
enum LoopRet {
    Abort,
    Continue,
    Disconnected { fd : libc::c_int },
    UpdateFds,
}

impl Tiny {
    pub fn new(nick : String, hostname : String, realname : String) -> Tiny {
        Tiny {
            comms: Vec::with_capacity(1),
            tui: TUI::new(),
            nick: nick,
            hostname: hostname,
            realname: realname,
        }
    }

    pub fn mainloop(&mut self) {
        self.tui.new_server_tab("debug".to_string());

        loop {
            // Set up the descriptors for select()
            let mut fd_set : libc::fd_set = unsafe { mem::zeroed() };

            // 0 is stdin
            unsafe { libc::FD_SET(0, &mut fd_set); }

            let mut max_fd : libc::c_int = 0;
            for comm in self.comms.iter() {
                let fd = comm.get_raw_fd();
                max_fd = max(fd, max_fd);
                unsafe { libc::FD_SET(fd, &mut fd_set); }
            }

            let nfds = max_fd + 1;

            // Start the loop
            if self.mainloop_(fd_set, nfds) == LoopRet::Abort {
                break;
            }
        }
    }

    fn mainloop_(&mut self, fd_set : libc::fd_set, nfds : libc::c_int) -> LoopRet {
        loop {
            self.tui.draw();

            let mut fd_set_ = fd_set.clone();
            let ret =
                unsafe {
                    libc::select(nfds,
                                 &mut fd_set_,           // read fds
                                 std::ptr::null_mut(),   // write fds
                                 std::ptr::null_mut(),   // error fds
                                 std::ptr::null_mut())   // timeval
                };

            // A resize signal (SIGWINCH) causes select() to fail, but termbox's
            // signal handler runs and we need to run termbox's poll_event() to
            // be able to catch the resize event. So, when stdin is ready we
            // call the TUI event handler, but we also call it when select() is
            // interrupted for some reason, just to be able to handle resize
            // events.
            //
            // See also https://github.com/nsf/termbox/issues/71.
            if unsafe { ret == -1 || libc::FD_ISSET(0, &mut fd_set_) } {
                match self.handle_stdin() {
                    LoopRet::Abort => { return LoopRet::Abort; },
                    LoopRet::UpdateFds => { return LoopRet::UpdateFds; }
                    _ => {}
                }
            }

            // A socket is ready
            // TODO: Can multiple sockets be set in single select() call? I
            // assume yes for now.
            else {
                // Collecting comms to read in this Vec becuase Rust sucs.
                let mut comm_idxs = Vec::with_capacity(1);
                for (comm_idx, comm) in self.comms.iter_mut().enumerate() {
                    let fd = comm.get_raw_fd();
                    if unsafe { libc::FD_ISSET(fd, &mut fd_set_) } {
                        comm_idxs.push(comm_idx);
                    }
                }

                let mut abort = false;
                let mut reset_fds = false;
                for comm_idx in comm_idxs {
                    match self.handle_socket(comm_idx) {
                        LoopRet::Abort => { abort = true; },
                        LoopRet::Disconnected { .. } => {
                            let comm = self.comms.remove(comm_idx);
                            self.tui.add_err_msg("Disconnected.", &MsgTarget::AllServTabs {
                                serv_name: &comm.serv_name,
                            });
                            reset_fds = true;
                        },
                        _ => {}
                    }
                }

                if abort {
                    return LoopRet::Abort;
                } else if reset_fds {
                    return LoopRet::Continue;
                }
            }
        }
    }

    ////////////////////////////////////////////////////////////////////////////

    fn handle_stdin(&mut self) -> LoopRet {
        match self.tui.keypressed_peek() {
            TUIRet::Abort => LoopRet::Abort,
            TUIRet::Input { msg, from } => {
                writeln!(self.tui,
                         "Input source: {:#?}, msg: {}",
                         from, msg.iter().cloned().collect::<String>()).unwrap();

                writeln!(io::stderr(),
                         "Input source: {:#?}, msg: {}",
                         from, msg.iter().cloned().collect::<String>()).unwrap();

                // We know msg has at least one character as the TUI won't
                // accept it otherwise.
                if msg[0] == '/' {
                    self.handle_command(from, (&msg[ 1 .. ]).into_iter().cloned().collect())
                } else {
                    self.send_msg(from, msg);
                    LoopRet::Continue
                }
            },
            _ => LoopRet::Continue
        }
    }

    fn handle_command(&mut self, src : MsgSource, msg : String) -> LoopRet {
        let words : Vec<&str> = msg.split_whitespace().into_iter().collect();
        if words[0] == "connect" {
            self.connect(words[1]);
            LoopRet::UpdateFds
        } else if words[0] == "join" {
            self.join(src, words[1]);
            LoopRet::Continue
        } else if words[0] == "quit" {
            LoopRet::Abort
        } else {
            self.tui.add_err_msg(
                &format!("Unsupported command: {}", words[0]), &MsgTarget::CurrentTab);
            LoopRet::Continue
        }
    }

    fn connect(&mut self, serv_addr : &str) {
        match utils::drop_port(serv_addr) {
            None => {
                self.tui.add_err_msg("connect: Need a <host>:<port>", &MsgTarget::CurrentTab);
            },
            Some(serv_name) => {
                self.tui.new_server_tab(serv_name.to_owned());
                writeln!(self.tui, "Created tab: {}", serv_name).unwrap();
                self.tui.add_msg("Connecting...", &MsgTarget::Server { serv_name: serv_name });

                match Comms::try_connect(serv_addr, serv_name,
                                         &self.nick, &self.hostname, &self.realname) {
                    Ok(comms) => {
                        self.comms.push(comms);
                    },
                    Err(err) => {
                        self.tui.add_err_msg(&format!("Error: {}", err),
                                             &MsgTarget::Server { serv_name: serv_name });
                    }
                }
            }
        }
    }

    fn join(&mut self, src : MsgSource, chan : &str) {
        Msg::join(chan, &mut self.tui).unwrap(); // debug
        let comm = self.find_comm(src.serv_name()).unwrap();
        Msg::join(chan, comm).unwrap();
    }

    fn send_msg(&mut self, from : MsgSource, msg : Vec<char>) {
        let msg_string = msg.iter().cloned().collect::<String>();

        match from {
            MsgSource::Serv { .. } => {
                self.tui.add_err_msg("Can't send PRIVMSG to a server.", &MsgTarget::CurrentTab);
            },

            MsgSource::Chan { serv_name, chan_name } => {
                {
                    let comm = self.find_comm(&serv_name).unwrap();
                    Msg::privmsg(&chan_name, &msg_string, comm).unwrap();
                }
                self.tui.add_msg(&msg_string, &MsgTarget::Chan { serv_name: &serv_name,
                                                                 chan_name: &chan_name });
            },

            MsgSource::User { serv_name, nick } => {
                {
                    let comm = self.find_comm(&serv_name).unwrap();
                    Msg::privmsg(&nick, &msg_string, comm).unwrap();
                }
                self.tui.add_msg(&msg_string, &MsgTarget::User { serv_name: &serv_name, nick: &nick });
            }
        }
    }

    fn find_comm(&mut self, serv_name : &str) -> Option<&mut Comms> {
        for comm in self.comms.iter_mut() {
            if comm.serv_name == serv_name {
                return Some(comm);
            }
        }
        None
    }

    ////////////////////////////////////////////////////////////////////////////

    fn handle_socket(&mut self, comm_idx : usize) -> LoopRet {
        let mut disconnect : Option<libc::c_int> = None;

        let rets = {
            let mut comm = unsafe { self.comms.get_unchecked_mut(comm_idx) };
            comm.read_incoming_msg()
        };

        for ret in rets {
            // tui.show_msg_current_tab(&format!("{:?}", ret));
            writeln!(&mut io::stderr(), "incoming msg: {:?}", ret).unwrap();
            match ret {
                CommsRet::Disconnected { fd } => {
                    disconnect = Some(fd);
                },
                CommsRet::Err { err_msg } => {
                    self.tui.add_err_msg(&err_msg, &MsgTarget::Server {
                        serv_name: & unsafe { self.comms.get_unchecked(comm_idx) }.serv_name
                    });
                },
                CommsRet::IncomingMsg { pfx, ty, args } => {
                    self.handle_incoming_msg(comm_idx, &pfx, &ty, args);
                },
                CommsRet::SentMsg { .. } => {
                    // TODO: Probably just ignore this?
                }
            }
        }

        if let Some(fd) = disconnect {
            LoopRet::Disconnected { fd: fd }
        } else {
            LoopRet::Continue
        }
    }

    fn handle_incoming_msg(&mut self, comm_idx : usize,
                           pfx : &Pfx, ty : &str, args : Vec<String>) {
        if ty == "JOIN" {
            let chan = &args[0];
            let serv_name = & unsafe { &self.comms.get_unchecked(comm_idx) }.serv_name;
            match pfx {
                &Pfx::Server(ref serv) => {
                    // This doesn't make any sense, log it.
                    writeln!(self.tui, "Weird JOIN message with server prefix {}", serv).unwrap();
                },
                &Pfx::User { ref nick, .. } => {
                    if *nick == self.nick {
                        self.tui.new_chan_tab(serv_name.to_owned(), chan.to_owned());
                    } else {
                        // TODO
                    }
                }
            }
        }

        else if ty == "PRIVMSG" {
            debug_assert!(args.len() == 2);
            let target = &args[0];
            let msg = &args[1];

            let comm = unsafe { &self.comms.get_unchecked(comm_idx) };

            if target.as_bytes()[0] == b'#' {
                self.tui.add_msg(&msg, &MsgTarget::Chan {
                    serv_name: &comm.serv_name,
                    chan_name: &target,
                });
            }

            else if target == &self.nick {
                let msg_target = pfx_to_target(pfx, &comm.serv_name);
                self.tui.add_msg(msg, &msg_target);
            }

            else {
                writeln!(self.tui, "Weird PRIVMSG target: {}", target);
            }
        }

        else if ty == "NOTICE" {
            debug_assert!(args.len() == 2);
            let target = &args[0];
            let msg = &args[1];

            let comm = unsafe { &self.comms.get_unchecked(comm_idx) };

            if target == "*" || target == &self.nick {
                self.tui.add_msg(&msg, &pfx_to_target(pfx, &comm.serv_name));
            } else {
                writeln!(self.tui, "Weird NOTICE target: {}", target);
            }
        }

        else {
            // Just log for now
            writeln!(self.tui,
                     "Ignoring incoming msg:\npfx: {:?}\nty: {}\nargs: {:?}",
                     pfx, ty, args).unwrap();
        }
    }
}

fn pfx_to_target<'a>(pfx : &'a Pfx, curr_serv : &'a str) -> MsgTarget<'a> {
    match pfx {
        &Pfx::Server(_) => MsgTarget::Server { serv_name: curr_serv },
        &Pfx::User { ref nick, .. } => MsgTarget::User { serv_name: curr_serv, nick: nick },
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

//! A C-style `for` loop in macro form.
//!
//! This takes the form `cfor!(initialiser; condition; step {
//! body })`.
//!
//! - `initialiser` is a statement evaluated before any iterations of
//!   the loop. Any variables declared here are scoped to the `cfor!`
//!   invocation, that is, only usable inside `condition`, `step` and
//!   `body`.
//! - `condition` is an boolean expression evaluated at the start of
//!   each iteration. If it evaluates to `false` iteration will stop.
//! - `step` is an arbitrary expression which is executed at the end
//!   of each iteration (including if `continue` is called), before
//!   `condition` is checked.
//!
//!
//! The initialiser and condition can be empty like C, but the step
//! cannot unlike C. A `for` loop with no step is identical to a
//! `while` loop.
//!
//! [*Source & issue tracker*](https://github.com/huonw/cfor/)
//!
//! # When should I use it?
//!
//! *Only* when `cfor!` is clearer than the more declarative built-in
//! [iterators](http://doc.rust-lang.org/master/std/iter/), [their
//! adaptors](http://doc.rust-lang.org/master/std/iter/trait.Iterator.html)
//! and the `for` loop. For example, the built-in iterator
//! functionality is more self-contained so there is less risk of
//! accidentally writing `i` in a condition when `j` was meant (I
//! personally get bitten by this semiregularly when writing nested
//! "2D" loops in C).
//!
//! Furthermore, the adaptor methods linked above allow [one to
//! write](http://huonw.github.io/2014/06/10/knn-rust.html) concise,
//! performant, reusable "functional" code in a way that is not
//! possible to achieve using C-style iteration.
//!
//! # How to use it?
//!
//! Add the repository as a normal cargo dependency, and include into
//! your crate with `#[phase(plugin)]`. (See examples below.)
//!
//! ```toml
//! [dependencies.cfor]
//! git = "https://github.com/huonw/cfor"
//! ```
//!
//! # Examples
//!
//! ## Simple
//!
//! A non-additive condition is not handled extremely naturally by
//! `std::iter`, but is straight-forward to handle directly.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1u; x < 0x1000; x *= 2 {
//!         println!("power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Intrabody condition
//!
//! If a condition requires some extra computation to be checked (or
//! if there is some code that should always be evaluated, even if the
//! condition will be `false` for a given iteration), the condition in
//! the `cfor` header can be omitted.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1u; ; x *= 2 {
//!         // ... setup ...
//!         println!("handling power of 2: {}", x);
//!
//!         if x < 0x1000 { break }
//!
//!         // ... further handling ...
//!         println!("handling power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Out-of-loop initialisation
//!
//! Sometimes one may wish to have access to a variable outside the
//! loop after it finishes so it has to be declared outside the loop,
//! or one may be iterating over some presupplied/-computed value so
//! there is no meaningful additional initialisation possible. The
//! initialisation expression can be safely omitted in this case.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! use std::rand;
//!
//! fn main() {
//!     let mut x = 1u16;
//!
//!     cfor!{; x < 0x1000; x *= 2 {
//!         println!("power of 2: {}", x);
//!
//!         // sometimes quit early
//!         if x > rand::random() { break }
//!     }}
//!
//!     println!("actually stopped at {}", x);
//! }
//! ```
//!
//! # Handling `continue`
//!
//! (Or, "why is the macro so complicated?")
//!
//! Special effort is made to ensure that `continue` acts correctly, a
//! naive macro defined as follows will cause `continue` to also skip
//! evaluating `step`, likely leading to undesirable behaviour like
//! infinite loops.
//!
//! ```rust
//! #![feature(macro_rules)]
//!
//! // WARNING: this is broken.
//! macro_rules! bad_cfor {
//!     ($init: stmt; $cond: expr; $step: expr $body: block) => {
//!         {
//!             $init;
//!             while $cond {
//!                 $body;
//!
//!                 $step;
//!             }
//!         }
//!     }
//! }
//!
//! fn main() {
//!     let mut true_counter = 0u;
//!
//!     bad_cfor!{let mut i = 0u; i < 10; i += 1 {
//!
//!         // manually avoid the infinite loop
//!         if true_counter >= 50 { break }
//!         true_counter += 1;
//!
//!         println!("i = {}", i);
//!         // try to skip just i == 4
//!         if i == 4 {
//!             // but this skips the i += 1 leaving us
//!             // on i == 4 forever.
//!             continue
//!         }
//!         // ...more code...
//!     }}
//! }
//! ```
//!
//! This is invoked in the same manner as `cfor!`, but, if `$body`
//! contains a `continue`, the `$step` at the end of the loop body
//! will never be evaluated.

/// A C-style `for` loop in macro form.
///
/// See crates docs for more information.
#[macro_export]
pub macro_rules! cfor {
    // for (; ...; ...) { ... }
    (; $($rest: tt)*) => {
        cfor!((); $($rest)*)
    };
    // for ($init; ; ...) { ... }
    ($init: stmt; ; $($rest: tt)*) => {
        cfor!($init; true; $($rest)*)
    };

    // for ($init; $cond; $step) { $body }
    ($init: stmt; $cond: expr; $step: expr $body: block) => {
        {
            let mut _first = true;
            $init;
            while {
                if _first {
                    _first = false
                } else {
                    $step
                }

                $cond
            } $body
        }
    };
}
<commit_msg>Remove linebreak in the middle of inline code.<commit_after>#![feature(macro_rules)]

//! A C-style `for` loop in macro form.
//!
//! This takes the form `cfor!(initialiser; condition; step { body })`.
//!
//! - `initialiser` is a statement evaluated before any iterations of
//!   the loop. Any variables declared here are scoped to the `cfor!`
//!   invocation, that is, only usable inside `condition`, `step` and
//!   `body`.
//! - `condition` is an boolean expression evaluated at the start of
//!   each iteration. If it evaluates to `false` iteration will stop.
//! - `step` is an arbitrary expression which is executed at the end
//!   of each iteration (including if `continue` is called), before
//!   `condition` is checked.
//!
//!
//! The initialiser and condition can be empty like C, but the step
//! cannot unlike C. A `for` loop with no step is identical to a
//! `while` loop.
//!
//! [*Source & issue tracker*](https://github.com/huonw/cfor/)
//!
//! # When should I use it?
//!
//! *Only* when `cfor!` is clearer than the more declarative built-in
//! [iterators](http://doc.rust-lang.org/master/std/iter/), [their
//! adaptors](http://doc.rust-lang.org/master/std/iter/trait.Iterator.html)
//! and the `for` loop. For example, the built-in iterator
//! functionality is more self-contained so there is less risk of
//! accidentally writing `i` in a condition when `j` was meant (I
//! personally get bitten by this semiregularly when writing nested
//! "2D" loops in C).
//!
//! Furthermore, the adaptor methods linked above allow [one to
//! write](http://huonw.github.io/2014/06/10/knn-rust.html) concise,
//! performant, reusable "functional" code in a way that is not
//! possible to achieve using C-style iteration.
//!
//! # How to use it?
//!
//! Add the repository as a normal cargo dependency, and include into
//! your crate with `#[phase(plugin)]`. (See examples below.)
//!
//! ```toml
//! [dependencies.cfor]
//! git = "https://github.com/huonw/cfor"
//! ```
//!
//! # Examples
//!
//! ## Simple
//!
//! A non-additive condition is not handled extremely naturally by
//! `std::iter`, but is straight-forward to handle directly.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1u; x < 0x1000; x *= 2 {
//!         println!("power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Intrabody condition
//!
//! If a condition requires some extra computation to be checked (or
//! if there is some code that should always be evaluated, even if the
//! condition will be `false` for a given iteration), the condition in
//! the `cfor` header can be omitted.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1u; ; x *= 2 {
//!         // ... setup ...
//!         println!("handling power of 2: {}", x);
//!
//!         if x < 0x1000 { break }
//!
//!         // ... further handling ...
//!         println!("handling power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Out-of-loop initialisation
//!
//! Sometimes one may wish to have access to a variable outside the
//! loop after it finishes so it has to be declared outside the loop,
//! or one may be iterating over some presupplied/-computed value so
//! there is no meaningful additional initialisation possible. The
//! initialisation expression can be safely omitted in this case.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! use std::rand;
//!
//! fn main() {
//!     let mut x = 1u16;
//!
//!     cfor!{; x < 0x1000; x *= 2 {
//!         println!("power of 2: {}", x);
//!
//!         // sometimes quit early
//!         if x > rand::random() { break }
//!     }}
//!
//!     println!("actually stopped at {}", x);
//! }
//! ```
//!
//! # Handling `continue`
//!
//! (Or, "why is the macro so complicated?")
//!
//! Special effort is made to ensure that `continue` acts correctly, a
//! naive macro defined as follows will cause `continue` to also skip
//! evaluating `step`, likely leading to undesirable behaviour like
//! infinite loops.
//!
//! ```rust
//! #![feature(macro_rules)]
//!
//! // WARNING: this is broken.
//! macro_rules! bad_cfor {
//!     ($init: stmt; $cond: expr; $step: expr $body: block) => {
//!         {
//!             $init;
//!             while $cond {
//!                 $body;
//!
//!                 $step;
//!             }
//!         }
//!     }
//! }
//!
//! fn main() {
//!     let mut true_counter = 0u;
//!
//!     bad_cfor!{let mut i = 0u; i < 10; i += 1 {
//!
//!         // manually avoid the infinite loop
//!         if true_counter >= 50 { break }
//!         true_counter += 1;
//!
//!         println!("i = {}", i);
//!         // try to skip just i == 4
//!         if i == 4 {
//!             // but this skips the i += 1 leaving us
//!             // on i == 4 forever.
//!             continue
//!         }
//!         // ...more code...
//!     }}
//! }
//! ```
//!
//! This is invoked in the same manner as `cfor!`, but, if `$body`
//! contains a `continue`, the `$step` at the end of the loop body
//! will never be evaluated.

/// A C-style `for` loop in macro form.
///
/// See crates docs for more information.
#[macro_export]
pub macro_rules! cfor {
    // for (; ...; ...) { ... }
    (; $($rest: tt)*) => {
        cfor!((); $($rest)*)
    };
    // for ($init; ; ...) { ... }
    ($init: stmt; ; $($rest: tt)*) => {
        cfor!($init; true; $($rest)*)
    };

    // for ($init; $cond; $step) { $body }
    ($init: stmt; $cond: expr; $step: expr $body: block) => {
        {
            let mut _first = true;
            $init;
            while {
                if _first {
                    _first = false
                } else {
                    $step
                }

                $cond
            } $body
        }
    };
}
<|endoftext|>


<commit_before>
//! # Pastebin Rust Api
//!
//! Wrapper for the [Pastebin Api](https://pastebin.com/api)
//!
//! ## Getting started
//!
//! Simple usage of `Paster`:
//!
//! ```
//! extern crate pastebin_rust_api;
//! use pastebin_rust_api::{Paster, Access, Format, Expiration};
//!
//! fn main() {
//!     // I recommend to put your dev key into an environment variable called
//!     // `PASTEBIN_DEVELOPER_TOKEN`.
//!     let parser = Paster::new(Some("<YOUR DEV KEY>".to_owned()));
//!     let response = parser.paste("<html></html>",
//!                                 Some(&Access::Private),
//!                                 Some("TestHtml"),
//!                                 Some(&Expiration::TenMinutes),
//!                                 Some(&Format::HTML5),
//!                                 None);
//!     if response.is_ok() {
//!         if let Some(paste) = response.ok() {
//!             // If everything is OK, you can get the url to your code here.
//!             println!("{}", paste.content);
//!         }
//!     }
//! }
//!
//! ```
//!

extern crate reqwest;

pub use self::paster::Paster;
pub use self::paster::format::Format;
pub use self::paster::expiration::Expiration;
pub use self::paster::access::Access;

mod paster;
pub mod objects;
mod error;

/// method for constructing the api url for pastebin.
fn construct_api_url(path: &[&str]) -> String {
    format!("https://pastebin.com/api/{}", path.join("/"))
}
<commit_msg>imported treexml<commit_after>
//! # Pastebin Rust Api
//!
//! Wrapper for the [Pastebin Api](https://pastebin.com/api)
//!
//! ## Getting started
//!
//! Simple usage of `Paster`:
//!
//! ```
//! extern crate pastebin_rust_api;
//! use pastebin_rust_api::{Paster, Access, Format, Expiration};
//!
//! fn main() {
//!     // I recommend to put your dev key into an environment variable called
//!     // `PASTEBIN_DEVELOPER_TOKEN`.
//!     let parser = Paster::new(Some("<YOUR DEV KEY>".to_owned()));
//!     let response = parser.paste("<html></html>",
//!                                 Some(&Access::Private),
//!                                 Some("TestHtml"),
//!                                 Some(&Expiration::TenMinutes),
//!                                 Some(&Format::HTML5),
//!                                 None);
//!     if response.is_ok() {
//!         if let Some(paste) = response.ok() {
//!             // If everything is OK, you can get the url to your code here.
//!             println!("{}", paste.content);
//!         }
//!     }
//! }
//!
//! ```
//!

extern crate reqwest;
extern crate treexml;

pub use self::paster::Paster;
pub use self::paster::format::Format;
pub use self::paster::expiration::Expiration;
pub use self::paster::access::Access;

mod paster;
pub mod objects;
mod error;

/// method for constructing the api url for pastebin.
fn construct_api_url(path: &[&str]) -> String {
    format!("https://pastebin.com/api/{}", path.join("/"))
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate url;

use libc::gethostname;
use serde_json::Value;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::net::TcpStream;
use std::sync::Mutex;

lazy_static! {
    pub static ref EMITTER: Mutex<Emitter<'static>> = Mutex::new(Emitter::empty());
}

pub fn emitter() -> std::sync::MutexGuard<'static, Emitter<'static>>
{
    EMITTER.lock().unwrap()
}

pub type Point<'a> = BTreeMap<&'a str, serde_json::Value>;

pub struct Emitter<'e>
{
    defaults: Point<'e>,
    output: Option<TcpStream>,
    destination: String,
    app: String,
}

impl<'e> Emitter<'e>
{
    pub fn empty() -> Emitter<'e>
    {
        let mut opts: Point = Point::new();
        let hostname = hostname();
        opts.insert("host", serde_json::to_value(hostname));
        Emitter
        {
            defaults: opts,
            output: None,
            app: String::from(""),
            destination: String::from("")
        }
    }

    pub fn init(&mut self, tmpl: BTreeMap<&'e str, Value>, app: &str)
    {
        let mut defaults = tmpl.clone();
        let hostname = hostname();
        defaults.insert("host", serde_json::to_value(hostname));

        let mut t = String::from(app);
        t.push('.');

        self.defaults = defaults;
        self.app = t;
    }

    pub fn new(tmpl: BTreeMap<&'e str, Value>, app: &str) -> Emitter<'e>
    {
        let mut defaults = tmpl.clone();
        let hostname = hostname();
        defaults.insert("host", serde_json::to_value(hostname));

        let mut t = String::from(app);
        t.push('.');

        Emitter
        {
            defaults: defaults,
            output: None,
            app: t,
            destination: String::from("")
        }
    }

    pub fn connect(&mut self, dest: &str)
    {
        self.destination = String::from(dest);
        self.output = create_connection(dest);
    }

    fn write(&mut self, metric: BTreeMap<&'e str, Value>)
    {
        match self.output
        {
            None => {},
            Some(ref mut conn) =>
            {
                let mline = serde_json::to_string(&metric).unwrap() + "\n";
                match conn.write_all(mline.as_bytes())
                {
                    Ok(_) => {},
                    Err(e) => println!("{:?}", e),
                }
            }
        }
    }

    pub fn emit(&mut self, point: BTreeMap<&'e str, Value>)
    {
        let mut metric = self.defaults.clone();
        metric.append(&mut point.clone());

        // this will fail if you forget to set a name
        let name = metric.remove("name").unwrap();
        let mut fullname = self.app.clone();
        fullname.push_str(name.as_str().unwrap());

        metric.insert("name", serde_json::to_value(fullname));
        metric.entry("value").or_insert(serde_json::to_value(1));

        let now = time::get_time();
        let millis = now.sec * 1000 + (now.nsec / 1000000) as i64;
        metric.entry("time").or_insert(serde_json::to_value(millis));

        self.write(metric);
    }

    pub fn emit_name(&mut self, name: &'e str)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        self.emit(metric);
    }

    pub fn emit_name_val_tag(&mut self, name: &'e str, value: u32, tag: &'e str, tagv: &'e str)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        metric.insert(tag, serde_json::to_value(tagv));
        self.emit(metric);
    }

    pub fn emit_name_int_tag_uint(&mut self, name: &'e str, value: i64, tag: &'e str, tagv: u16)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        metric.insert(tag, serde_json::to_value(tagv));
        self.emit(metric);
    }

    pub fn emit_float(&mut self, name: &'e str, value: f32)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        self.emit(metric);
    }

    pub fn emit_int(&mut self, name: &'e str, value: i32)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        self.emit(metric);
    }

    pub fn emit_int64(&mut self, name: &'e str, value: i64)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        self.emit(metric);
    }

    pub fn emit_unsigned(&mut self, name: &'e str, value: u32)
    {
        self.emit_int64(name, value as i64);
    }

    pub fn emit_unsigned16(&mut self, name: &'e str, value: u16)
    {
        self.emit_int(name, value as i32);
    }
}

fn create_connection(dest: &str) -> Option<std::net::TcpStream>
{
    // TODO udp vs tcp for full compatibility
    let target = url::Url::parse(dest).ok().unwrap();
    match TcpStream::connect((target.host_str().unwrap(), target.port().unwrap()))
    {
        Ok(v) => { Some(v) },
        Err(_) => { None },
    }
}

pub fn hostname<'a>() -> String
{
    let bufsize = 255;
    let mut buf = Vec::<u8>::with_capacity(bufsize);
    let ptr = buf.as_mut_slice().as_mut_ptr();

    let err = unsafe
        { gethostname(ptr as *mut libc::c_char, bufsize as libc::size_t) }
        as libc::size_t;

    if err != 0
    {
        return "localhost".into();
    }

    let mut len = bufsize;
    let mut i = 0;

    loop {
        let byte = unsafe { *(((ptr as u64) + (i as u64)) as *const u8) };
        if byte == 0
        {
            len = i;
            break;
        }
        if i == bufsize { break; }
        i += 1;
    }

    unsafe { buf.set_len(len); }
    String::from_utf8_lossy(buf.as_slice()).into_owned()
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Don't crash if `name` is missing.<commit_after>#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate url;

use libc::gethostname;
use serde_json::Value;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::net::TcpStream;
use std::sync::Mutex;

lazy_static!
{
    pub static ref EMITTER: Mutex<Emitter<'static>> = Mutex::new(Emitter::empty());
}

pub fn emitter() -> std::sync::MutexGuard<'static, Emitter<'static>>
{
    EMITTER.lock().unwrap()
}

pub type Point<'a> = BTreeMap<&'a str, serde_json::Value>;

pub struct Emitter<'e>
{
    defaults: Point<'e>,
    output: Option<TcpStream>,
    destination: String,
    app: String,
}

impl<'e> Emitter<'e>
{
    pub fn empty() -> Emitter<'e>
    {
        let mut opts: Point = Point::new();
        let hostname = hostname();
        opts.insert("host", serde_json::to_value(hostname));
        Emitter
        {
            defaults: opts,
            output: None,
            app: String::from(""),
            destination: String::from("")
        }
    }

    pub fn init(&mut self, tmpl: BTreeMap<&'e str, Value>, app: &str)
    {
        let mut defaults = tmpl.clone();
        let hostname = hostname();
        defaults.insert("host", serde_json::to_value(hostname));

        let mut t = String::from(app);
        t.push('.');

        self.defaults = defaults;
        self.app = t;
    }

    pub fn new(tmpl: BTreeMap<&'e str, Value>, app: &str) -> Emitter<'e>
    {
        let mut defaults = tmpl.clone();
        let hostname = hostname();
        defaults.insert("host", serde_json::to_value(hostname));

        let mut t = String::from(app);
        t.push('.');

        Emitter
        {
            defaults: defaults,
            output: None,
            app: t,
            destination: String::from("")
        }
    }

    pub fn connect(&mut self, dest: &str)
    {
        self.destination = String::from(dest);
        self.output = create_connection(dest);
    }

    fn write(&mut self, metric: BTreeMap<&'e str, Value>)
    {
        match self.output
        {
            None => { },
            Some(ref mut conn) =>
            {
                let mline = serde_json::to_string(&metric).unwrap() + "\n";
                match conn.write_all(mline.as_bytes())
                {
                    Ok(_) => {},
                    Err(e) => println!("{:?}", e),
                }
            }
        }
    }

    pub fn emit(&mut self, point: BTreeMap<&'e str, Value>)
    {
        let mut metric = self.defaults.clone();
        metric.append(&mut point.clone());

        // Failing to set a name means the metrics point is invalid; we decline to send it.
        let name = match metric.remove("name")
        {
            Some(v) => v,
            None => { return; },
        };
        let mut fullname = self.app.clone();
        fullname.push_str(name.as_str().unwrap());

        metric.insert("name", serde_json::to_value(fullname));
        metric.entry("value").or_insert(serde_json::to_value(1));

        let now = time::get_time();
        let millis = now.sec * 1000 + (now.nsec / 1000000) as i64;
        metric.entry("time").or_insert(serde_json::to_value(millis));

        self.write(metric);
    }

    pub fn emit_name(&mut self, name: &'e str)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        self.emit(metric);
    }

    pub fn emit_name_val_tag(&mut self, name: &'e str, value: u32, tag: &'e str, tagv: &'e str)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        metric.insert(tag, serde_json::to_value(tagv));
        self.emit(metric);
    }

    pub fn emit_name_int_tag_uint(&mut self, name: &'e str, value: i64, tag: &'e str, tagv: u16)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        metric.insert(tag, serde_json::to_value(tagv));
        self.emit(metric);
    }

    pub fn emit_float(&mut self, name: &'e str, value: f32)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        self.emit(metric);
    }

    pub fn emit_int(&mut self, name: &'e str, value: i32)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        self.emit(metric);
    }

    pub fn emit_int64(&mut self, name: &'e str, value: i64)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        self.emit(metric);
    }

    pub fn emit_unsigned(&mut self, name: &'e str, value: u32)
    {
        self.emit_int64(name, value as i64);
    }

    pub fn emit_unsigned16(&mut self, name: &'e str, value: u16)
    {
        self.emit_int(name, value as i32);
    }
}

fn create_connection(dest: &str) -> Option<std::net::TcpStream>
{
    // TODO udp vs tcp for full compatibility
    // TODO reconnect on error
    let target = url::Url::parse(dest).ok().unwrap();
    match TcpStream::connect((target.host_str().unwrap(), target.port().unwrap()))
    {
        Ok(v) => { Some(v) },
        Err(_) => { None },
    }
}

pub fn hostname<'a>() -> String
{
    let bufsize = 255;
    let mut buf = Vec::<u8>::with_capacity(bufsize);
    let ptr = buf.as_mut_slice().as_mut_ptr();

    let err = unsafe
        { gethostname(ptr as *mut libc::c_char, bufsize as libc::size_t) }
        as libc::size_t;

    if err != 0
    {
        return "localhost".into();
    }

    let mut len = bufsize;
    let mut i = 0;

    loop
    {
        let byte = unsafe { *(((ptr as u64) + (i as u64)) as *const u8) };
        if byte == 0
        {
            len = i;
            break;
        }
        if i == bufsize { break; }
        i += 1;
    }

    unsafe { buf.set_len(len); }
    String::from_utf8_lossy(buf.as_slice()).into_owned()
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>