<commit_before>//! [yEnc](http://www.yenc.org) is an encoding scheme to include binary files in Usenet messages.
mod crc32;

use std::fs::OpenOptions;
use std::io;
use std::io::{Read, Write, BufReader, BufRead};
use std::path::PathBuf;
use std::convert::From;

const NUL: u8 = 0;
const TAB: u8 = b'\t';
const LF: u8 = b'\n';
const CR: u8 = b'\r';
const SPACE: u8 = b' ';
const ESCAPE: u8 = b'=';
const LINE_SIZE: u16 = 128;

#[derive(Debug)]
pub enum DecodeError {
    IncompleteData(usize, usize),
    InvalidHeader(String, usize),
    InvalidChecksum,
    IoError(io::Error),
}

impl From<io::Error> for DecodeError {
    fn from(error: io::Error) -> DecodeError {
        DecodeError::IoError(error)
    }
}

#[derive(Default,Debug)]
struct MetaData {
    name: Option<String>,
    line: Option<u16>,
    size: Option<usize>,
    crc32: Option<u32>,
}

/// Encodes the input file in a new output file.
/// # Example
/// ```
/// yenc::yencode_file("test1.bin", "test1.bin.yenc");
/// ```
/// # Errors
/// - when the output file already exists
///
pub fn yencode_file(input_filename: &str, output_filename: &str) -> Result<(), io::Error> {
    let mut input_file = OpenOptions::new().read(true).open(input_filename)?;
    let mut output_file = OpenOptions::new().write(true).create_new(true).open(output_filename)?;
    let mut checksum: crc32::Crc32 = Default::default();
    let mut buffer = [0u8; 65536];
    let mut col = 0;
    output_file.write(format!("=ybegin line={} size={} name={}\r\n",
                       LINE_SIZE,
                       input_file.metadata()?.len(),
                       input_filename)
            .as_bytes())?;
    loop {
        let bytes_read = input_file.read(&mut buffer)?;
        match bytes_read {
            0 => break,
            _ => {
                checksum.update_with_slice(&buffer[0..bytes_read]);
                output_file.write(yencode_buffer(&buffer[0..bytes_read], &mut col, LINE_SIZE).as_slice())?;
            }
        };
    }

    output_file.write(format!("\r\n=yend size={} crc32={:08X}\r\n",
                       checksum.num_bytes,
                       checksum.crc)
            .as_bytes())?;
    Ok(())
}

/// Encode the byte slice into a vector of yEncoded bytes, with the maximum of `line_length` characters per line.
pub fn yencode_buffer(input: &[u8], col: &mut u16, line_length: u16) -> Vec<u8> {
    let mut output = Vec::<u8>::with_capacity(input.len());
    for &b in input {
        let encoded = yencode_byte(b);
        output.extend_from_slice(&encoded);
        *col += encoded.len() as u16;
        if *col >= line_length {
            output.push(CR);
            output.push(LF);
            *col = 0;
        }
    }
    output
}

#[inline]
fn yencode_byte(input_byte: u8) -> Vec<u8> {
    let mut output = Vec::<u8>::with_capacity(2);
    let mut output_byte = input_byte.overflowing_add(42).0;
    match output_byte {
        NUL | CR | LF | ESCAPE | TAB | SPACE => {
            output.push(ESCAPE);
            output_byte = output_byte.overflowing_add(64).0;
        }
        _ => {}
    };
    output.push(output_byte);
    output
}

/// Decodes the input file in a new output file.
/// # Example
/// ```
/// yenc::ydecode_file("test2.bin.yenc", "test2.bin");
/// ```
/// # Errors
/// - when the output file already exists
///
pub fn ydecode_file(input_filename: &str, output_path: &str) -> Result<String, DecodeError> {
    let input_file = OpenOptions::new().read(true).open(input_filename)?;
    let mut output_pathbuf = PathBuf::new();
    output_pathbuf.push(output_path);
    let mut rdr = BufReader::new(input_file);
    let mut line_buf = Vec::<u8>::with_capacity(2 * LINE_SIZE as usize);
    let mut checksum: crc32::Crc32 = Default::default();
    let mut yenc_block_found = false;

    loop {
        line_buf.clear();
        let length = rdr.read_until(LF, &mut line_buf)?;
        if length == 0 {
            break;
        }
        if &line_buf[0..8] == b"=ybegin " {
            yenc_block_found = true;
            break;
        }
    }

    if yenc_block_found {
        // parse header line and determine output filename
        // let header_data = parse_header_line(&line_buf[0..length)]);
        let offset = 8;
        let metadata = parse_header_line(&line_buf, offset)?;

        output_pathbuf.push(metadata.name.unwrap().to_string().trim());
        let mut output_file =
            OpenOptions::new().write(true).create_new(true).open(output_pathbuf.as_path())?;
        let mut footer_found = false;
        while !footer_found {
            line_buf.clear();
            let length = rdr.read_until(LF, &mut line_buf)?;
            if length == 0 {
                break;
            }
            if &line_buf[0..6] == b"=yend " {
                footer_found = true;
            } else {
                let decoded = ydecode_buffer(&line_buf[0..length]);
                checksum.update_with_slice(decoded.as_slice());
                output_file.write(decoded.as_slice())?;
            }
        }
        if let Some(expected_size) = metadata.size {
            if expected_size != checksum.num_bytes {
                return Err(DecodeError::IncompleteData(expected_size, checksum.num_bytes));
            }
        }
        if footer_found {
            let metadata = parse_header_line(&line_buf, 6)?;
            if let Some(expected_size) = metadata.size {
                if expected_size != checksum.num_bytes {
                    return Err(DecodeError::IncompleteData(expected_size, checksum.num_bytes));
                }
            }
            if let Some(expected_crc) = metadata.crc32 {
                if expected_crc != checksum.crc {
                    return Err(DecodeError::InvalidChecksum);
                }
            }
        }
    }
    Ok(output_pathbuf.to_str().unwrap().to_string())
}

/// Decode the yEncoded byte slice into a vector of bytes.
/// Carriage Return (CR) and Line Feed (LF) are ignored.
pub fn ydecode_buffer(input: &[u8]) -> Vec<u8> {
    let mut output = Vec::<u8>::with_capacity((input.len() as f64 * 1.02) as usize);
    let mut i = 0;
    while i < input.len() {
        let mut byte = input[i];
        i += 1;
        match byte {
            CR | LF => continue,
            ESCAPE => {
                byte = input[i].overflowing_sub(64).0;
                i += 1;
            }
            _ => {}
        };
        output.push(byte.overflowing_sub(42).0);
    }
    output
}

fn parse_header_line(line_buf: &[u8], offset: usize) -> Result<MetaData, DecodeError> {
    #[derive(Debug)]
    enum State {
        Keyword,
        Value,
        End,
    };

    let mut metadata: MetaData = Default::default();
    let mut state = State::Keyword;
    let mut keyword = Vec::<u8>::with_capacity(4);
    let mut value = Vec::<u8>::with_capacity(96);

    let header_line = String::from_utf8_lossy(&line_buf).to_string();
    for (i, &c) in line_buf[offset..].iter().enumerate() {
        let position = i + offset;
        match state {
            State::End => unreachable!(),
            State::Keyword => {
                match c {
                    b'a'...b'z' | b'0'...b'9' => keyword.push(c),
                    b'=' => {
                        if keyword.is_empty() ||
                           !(keyword.as_slice() == b"name" || keyword.as_slice() == b"line" ||
                             keyword.as_slice() == b"size" ||
                             keyword.as_slice() == b"crc32") {
                            return Err(DecodeError::InvalidHeader(header_line, position));
                        } else {
                            state = State::Value;
                        }
                    }
                    _ => {
                        return Err(DecodeError::InvalidHeader(header_line, position));
                    }
                }
            }
            State::Value => {
                match keyword.as_slice() {
                    b"name" => {
                        match c {
                            b'\r' => {}
                            b'\n' => {
                                state = State::End;
                                metadata.name = Some(String::from_utf8_lossy(&value).to_string());
                            }
                            _ => value.push(c),
                        }
                    }
                    b"size" => {
                        match c {
                            b'0'...b'9' => value.push(c),
                            b' ' => {
                                metadata.size =
                                    Some(usize::from_str_radix(&String::from_utf8_lossy(&value),
                                                               10)
                                        .unwrap());
                                state = State::Keyword;
                                keyword.clear();
                                value.clear();
                            }
                            _ => {
                                return Err(DecodeError::InvalidHeader(header_line, position));
                            }
                        }
                    }
                    b"line" => {
                        match c {
                            b'0'...b'9' => value.push(c),
                            b' ' => {
                                metadata.line =
                                    Some(u16::from_str_radix(&String::from_utf8_lossy(&value), 10)
                                        .unwrap());
                                state = State::Keyword;
                                keyword.clear();
                                value.clear();
                            }
                            _ => {
                                return Err(DecodeError::InvalidHeader(header_line, position));
                            }
                        }
                    }
                    b"crc32" => {
                        match c {
                            b'0'...b'9' | b'A'...b'F' | b'a'...b'f' => value.push(c),
                            b' ' => {
                                state = State::Keyword;
                                metadata.crc32 =
                                    Some(u32::from_str_radix(&String::from_utf8_lossy(&value), 16)
                                        .unwrap());
                                keyword.clear();
                                value.clear();
                            }
                            b'\n' => {
                                state = State::End;
                                metadata.crc32 =
                                    Some(u32::from_str_radix(&String::from_utf8_lossy(&value), 16)
                                        .unwrap());
                                keyword.clear();
                                value.clear();
                            }
                            b'\r' => {}
                            _ => {
                                return Err(DecodeError::InvalidHeader(header_line, position));
                            }
                        }
                    }
                    _ => unreachable!(),
                }
            }
        };
    }
    Ok(metadata)
}

#[cfg(test)]
mod tests {
    use super::{ESCAPE, TAB, LF, CR, SPACE, yencode_buffer, ydecode_buffer, yencode_byte};

    #[test]
    fn escape_null() {
        assert_eq!(vec![ESCAPE, 0x40], yencode_byte(214));
    }

    #[test]
    fn escape_tab() {
        assert_eq!(vec![ESCAPE, 0x49], yencode_byte(214 + TAB));
    }

    #[test]
    fn escape_lf() {
        assert_eq!(vec![ESCAPE, 0x4A], yencode_byte(214 + LF));
    }

    #[test]
    fn escape_cr() {
        assert_eq!(vec![ESCAPE, 0x4D], yencode_byte(214 + CR));
    }

    #[test]
    fn escape_space() {
        assert_eq!(vec![ESCAPE, 0x60], yencode_byte(214 + SPACE));
    }

    #[test]
    fn escape_equal_sign() {
        assert_eq!(vec![ESCAPE, 0x7D], yencode_byte(ESCAPE - 42));
    }

    #[test]
    fn equality() {
        let b = (0..256).map(|c| c as u8).collect::<Vec<u8>>();
        let mut col = 0;
        assert_eq!(b,
                   ydecode_buffer(&yencode_buffer(&b, &mut col, 128)).as_slice());
    }
}
<commit_msg>minor cleanup<commit_after>//! [yEnc](http://www.yenc.org) is an encoding scheme to include binary files in Usenet messages.
mod crc32;

use std::fs::OpenOptions;
use std::io;
use std::io::{Read, Write, BufReader, BufRead};
use std::path::PathBuf;
use std::convert::From;

const NUL: u8 = 0;
const TAB: u8 = b'\t';
const LF: u8 = b'\n';
const CR: u8 = b'\r';
const SPACE: u8 = b' ';
const ESCAPE: u8 = b'=';
const LINE_SIZE: u16 = 128;

#[derive(Debug)]
pub enum DecodeError {
    IncompleteData(usize, usize),
    InvalidHeader(String, usize),
    InvalidChecksum,
    IoError(io::Error),
}

impl From<io::Error> for DecodeError {
    fn from(error: io::Error) -> DecodeError {
        DecodeError::IoError(error)
    }
}

#[derive(Default,Debug)]
struct MetaData {
    name: Option<String>,
    line: Option<u16>,
    size: Option<usize>,
    crc32: Option<u32>,
}

/// Encodes the input file in a new output file.
/// # Example
/// ```
/// yenc::yencode_file("test1.bin", "test1.bin.yenc");
/// ```
/// # Errors
/// - when the output file already exists
///
pub fn yencode_file(input_filename: &str, output_filename: &str) -> Result<(), io::Error> {
    let mut input_file = OpenOptions::new().read(true).open(input_filename)?;
    let mut output_file = OpenOptions::new().write(true).create_new(true).open(output_filename)?;
    let mut checksum: crc32::Crc32 = Default::default();
    let mut buffer = [0u8; 65536];
    let mut col = 0;
    output_file.write(format!("=ybegin line={} size={} name={}\r\n",
                       LINE_SIZE,
                       input_file.metadata()?.len(),
                       input_filename)
            .as_bytes())?;
    loop {
        let bytes_read = input_file.read(&mut buffer)?;
        match bytes_read {
            0 => break,
            _ => {
                checksum.update_with_slice(&buffer[0..bytes_read]);
                output_file.write(yencode_buffer(&buffer[0..bytes_read], &mut col, LINE_SIZE).as_slice())?;
            }
        };
    }

    output_file.write(format!("\r\n=yend size={} crc32={:08X}\r\n",
                       checksum.num_bytes,
                       checksum.crc)
            .as_bytes())?;
    Ok(())
}

/// Encode the byte slice into a vector of yEncoded bytes, with the maximum of `line_length` characters per line.
pub fn yencode_buffer(input: &[u8], col: &mut u16, line_length: u16) -> Vec<u8> {
    let mut output = Vec::<u8>::with_capacity(input.len());
    for &b in input {
        let encoded = yencode_byte(b);
        output.extend_from_slice(&encoded);
        *col += encoded.len() as u16;
        if *col >= line_length {
            output.push(CR);
            output.push(LF);
            *col = 0;
        }
    }
    output
}

#[inline]
fn yencode_byte(input_byte: u8) -> Vec<u8> {
    let mut output = Vec::<u8>::with_capacity(2);
    let mut output_byte = input_byte.overflowing_add(42).0;
    match output_byte {
        NUL | CR | LF | ESCAPE | TAB | SPACE => {
            output.push(ESCAPE);
            output_byte = output_byte.overflowing_add(64).0;
        }
        _ => {}
    };
    output.push(output_byte);
    output
}

/// Decodes the input file in a new output file.
/// # Example
/// ```
/// yenc::ydecode_file("test2.bin.yenc", "test2.bin");
/// ```
/// # Errors
/// - when the output file already exists
///
pub fn ydecode_file(input_filename: &str, output_path: &str) -> Result<String, DecodeError> {
    let input_file = OpenOptions::new().read(true).open(input_filename)?;
    let mut output_pathbuf = PathBuf::new();
    output_pathbuf.push(output_path);
    let mut rdr = BufReader::new(input_file);
    let mut line_buf = Vec::<u8>::with_capacity(2 * LINE_SIZE as usize);
    let mut checksum: crc32::Crc32 = Default::default();
    let mut yenc_block_found = false;

    while !yenc_block_found {
        line_buf.clear();
        let length = rdr.read_until(LF, &mut line_buf)?;
        if length == 0 {
            break;
        }
        if &line_buf[0..8] == b"=ybegin " {
            yenc_block_found = true;
        }
    }

    if yenc_block_found {
        // parse header line and determine output filename
        let metadata = parse_header_line(&line_buf, 8)?;
        output_pathbuf.push(metadata.name.unwrap().to_string().trim());
        let mut output_file =
            OpenOptions::new().write(true).create_new(true).open(output_pathbuf.as_path())?;

        let mut footer_found = false;
        while !footer_found {
            line_buf.clear();
            let length = rdr.read_until(LF, &mut line_buf)?;
            if length == 0 {
                break;
            }
            if &line_buf[0..6] == b"=yend " {
                footer_found = true;
            } else {
                let decoded = ydecode_buffer(&line_buf[0..length]);
                checksum.update_with_slice(decoded.as_slice());
                output_file.write(decoded.as_slice())?;
            }
        }
        if let Some(expected_size) = metadata.size {
            if expected_size != checksum.num_bytes {
                return Err(DecodeError::IncompleteData(expected_size, checksum.num_bytes));
            }
        }
        if footer_found {
            let metadata = parse_header_line(&line_buf, 6)?;
            if let Some(expected_size) = metadata.size {
                if expected_size != checksum.num_bytes {
                    return Err(DecodeError::IncompleteData(expected_size, checksum.num_bytes));
                }
            }
            if let Some(expected_crc) = metadata.crc32 {
                if expected_crc != checksum.crc {
                    return Err(DecodeError::InvalidChecksum);
                }
            }
        }
    }
    Ok(output_pathbuf.to_str().unwrap().to_string())
}

/// Decode the yEncoded byte slice into a vector of bytes.
/// Carriage Return (CR) and Line Feed (LF) are ignored.
pub fn ydecode_buffer(input: &[u8]) -> Vec<u8> {
    let mut output = Vec::<u8>::with_capacity((input.len() as f64 * 1.02) as usize);
    let mut i = 0;
    while i < input.len() {
        let mut byte = input[i];
        i += 1;
        match byte {
            CR | LF => continue,
            ESCAPE => {
                byte = input[i].overflowing_sub(64).0;
                i += 1;
            }
            _ => {}
        };
        output.push(byte.overflowing_sub(42).0);
    }
    output
}

fn parse_header_line(line_buf: &[u8], offset: usize) -> Result<MetaData, DecodeError> {
    #[derive(Debug)]
    enum State {
        Keyword,
        Value,
        End,
    };

    let mut metadata: MetaData = Default::default();
    let mut state = State::Keyword;
    let mut keyword = Vec::<u8>::with_capacity(4);
    let mut value = Vec::<u8>::with_capacity(96);

    let header_line = String::from_utf8_lossy(line_buf).to_string();
    for (i, &c) in line_buf[offset..].iter().enumerate() {
        let position = i + offset;
        match state {
            State::End => unreachable!(),
            State::Keyword => {
                match c {
                    b'a'...b'z' | b'0'...b'9' => keyword.push(c),
                    b'=' => {
                        if keyword.is_empty() ||
                           !(keyword.as_slice() == b"name" || keyword.as_slice() == b"line" ||
                             keyword.as_slice() == b"size" ||
                             keyword.as_slice() == b"crc32") {
                            return Err(DecodeError::InvalidHeader(header_line, position));
                        } else {
                            state = State::Value;
                        }
                    }
                    _ => {
                        return Err(DecodeError::InvalidHeader(header_line, position));
                    }
                }
            }
            State::Value => {
                match keyword.as_slice() {
                    b"name" => {
                        match c {
                            b'\r' => {}
                            b'\n' => {
                                state = State::End;
                                metadata.name = Some(String::from_utf8_lossy(&value).to_string());
                            }
                            _ => value.push(c),
                        }
                    }
                    b"size" => {
                        match c {
                            b'0'...b'9' => value.push(c),
                            b' ' => {
                                metadata.size =
                                    Some(usize::from_str_radix(&String::from_utf8_lossy(&value),
                                                               10)
                                        .unwrap());
                                state = State::Keyword;
                                keyword.clear();
                                value.clear();
                            }
                            _ => {
                                return Err(DecodeError::InvalidHeader(header_line, position));
                            }
                        }
                    }
                    b"line" => {
                        match c {
                            b'0'...b'9' => value.push(c),
                            b' ' => {
                                metadata.line =
                                    Some(u16::from_str_radix(&String::from_utf8_lossy(&value), 10)
                                        .unwrap());
                                state = State::Keyword;
                                keyword.clear();
                                value.clear();
                            }
                            _ => {
                                return Err(DecodeError::InvalidHeader(header_line, position));
                            }
                        }
                    }
                    b"crc32" => {
                        match c {
                            b'0'...b'9' | b'A'...b'F' | b'a'...b'f' => value.push(c),
                            b' ' => {
                                state = State::Keyword;
                                metadata.crc32 =
                                    Some(u32::from_str_radix(&String::from_utf8_lossy(&value), 16)
                                        .unwrap());
                                keyword.clear();
                                value.clear();
                            }
                            b'\n' => {
                                state = State::End;
                                metadata.crc32 =
                                    Some(u32::from_str_radix(&String::from_utf8_lossy(&value), 16)
                                        .unwrap());
                                keyword.clear();
                                value.clear();
                            }
                            b'\r' => {}
                            _ => {
                                return Err(DecodeError::InvalidHeader(header_line, position));
                            }
                        }
                    }
                    _ => unreachable!(),
                }
            }
        };
    }
    Ok(metadata)
}

#[cfg(test)]
mod tests {
    use super::{ESCAPE, TAB, LF, CR, SPACE, yencode_buffer, ydecode_buffer, yencode_byte};

    #[test]
    fn escape_null() {
        assert_eq!(vec![ESCAPE, 0x40], yencode_byte(214));
    }

    #[test]
    fn escape_tab() {
        assert_eq!(vec![ESCAPE, 0x49], yencode_byte(214 + TAB));
    }

    #[test]
    fn escape_lf() {
        assert_eq!(vec![ESCAPE, 0x4A], yencode_byte(214 + LF));
    }

    #[test]
    fn escape_cr() {
        assert_eq!(vec![ESCAPE, 0x4D], yencode_byte(214 + CR));
    }

    #[test]
    fn escape_space() {
        assert_eq!(vec![ESCAPE, 0x60], yencode_byte(214 + SPACE));
    }

    #[test]
    fn escape_equal_sign() {
        assert_eq!(vec![ESCAPE, 0x7D], yencode_byte(ESCAPE - 42));
    }

    #[test]
    fn equality() {
        let b = (0..256).map(|c| c as u8).collect::<Vec<u8>>();
        let mut col = 0;
        assert_eq!(b,
                   ydecode_buffer(&yencode_buffer(&b, &mut col, 128)).as_slice());
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate rustc_serialize;
extern crate url;
extern crate regex;

use regex::{Captures, Regex};
use rustc_serialize::json;

use hyper::Client;
use hyper::server::{Handler, Request, Response};
use std::collections::HashMap;
use std::io::Read;

fn params<R: Read>(read: &mut R) -> HashMap<String, String> {
    let mut buffer = String::new();
    read.read_to_string(&mut buffer).unwrap();
    let mut params = HashMap::new();
    for (k, v) in url::form_urlencoded::parse(buffer.as_bytes()) {
        params.insert(k, v);
    }
    params
}

pub enum Resp {
    // say reponds in channel
    Say(String),
    // reply responds to caller of command
    Reply(String),
}

pub trait Responder {
    fn respond(&self, response: Resp) -> ();
}

pub struct DefaultResponder {
    response_url: String,
}

// todo: attachments
#[derive(Debug, RustcEncodable)]
pub struct ResponseBody {
    pub text: String,
    pub response_type: Option<String>,
}

impl Responder for DefaultResponder {
    fn respond(&self, response: Resp) {
        let body = match response {
            Resp::Say(text) => {
                ResponseBody {
                    text: text,
                    response_type: Some("in_channel".to_owned()),
                }
            }
            Resp::Reply(text) => {
                ResponseBody {
                    text: text,
                    response_type: None,
                }
            }
        };
        let client = Client::new();
        let _ = client.post(&self.response_url[..])
                      .body(json::encode(&body).unwrap().as_bytes())
                      .send();
    }
}

pub struct DiscardResponder;

impl Responder for DiscardResponder {
    fn respond(&self, _: Resp) {

    }
}

/// A Handle handles matched commands
pub trait Handle: Sync + Send {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Resp>;
}

impl<F> Handle for F
    where F: Fn(&Command, &Option<Captures>, Box<Responder>) -> Option<Resp>,
          F: Send + Sync
{
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Resp> {
        self(cmd, caps, responder)
    }
}

pub struct TokenValidator<H: Handle + 'static> {
    handler: H,
    token: String,
}

impl<H: Handle + 'static> Handle for TokenValidator<H> {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Resp> {
        if cmd.token == self.token {
            self.handler.handle(cmd, caps, responder)
        } else {
            None
        }
    }
}

/// A matcher matches commands
pub trait Matcher: Send + Sync {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool);
}

impl<F> Matcher for F
    where F: Fn(&Command) -> (Option<Captures>, bool),
          F: Send + Sync
{
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        self(cmd)
    }
}

/// A direct command matcher
///
pub struct MatchCommand(String);

impl Matcher for MatchCommand {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        (None, cmd.command == self.0)
    }
}

/// A regex pattern matcher
///
pub struct MatchRegex(Regex);

impl Matcher for MatchRegex {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        if self.0.is_match(cmd.command.as_ref()) {
            (self.0.captures(cmd.command.as_ref()), true)
        } else {
            (None, false)
        }
    }
}

/// A binding between a command handler and which commands its handles
pub struct Route {
    handler: Box<Handle>,
    matcher: Box<Matcher>,
}

///
/// A command de-multiplexor
///
#[derive(Default)]
pub struct Mux {
    routes: Vec<Box<Route>>,
}

impl Mux {
    pub fn command<C, T, H>(&mut self, cmd: C, token: T, handler: H)
        where C: Into<String>,
              T: Into<String>,
              H: Handle + 'static
    {
        self.matching(MatchCommand(cmd.into()),
                      TokenValidator {
                          handler: handler,
                          token: token.into(),
                      })
    }

    pub fn matching<M, H>(&mut self, matcher: M, handler: H)
        where M: Matcher + 'static,
              H: Handle + 'static
    {
        let route = Route {
            handler: Box::new(handler),
            matcher: Box::new(matcher),
        };
        self.route(route)
    }

    ///
    pub fn route(&mut self, route: Route) {
        self.routes.push(Box::new(route));
    }

    pub fn handler<'a>(&self, cmd: &'a Command) -> Option<(Option<Captures<'a>>, &Box<Handle>)> {
        for r in self.routes.iter() {
            if let (captures, true) = r.matcher.matches(cmd) {
                return Some((captures, &r.handler));
            }
        }
        None
    }

    pub fn handle(&self, cmd: &Command) {
        // set up responder
        let responder = DefaultResponder { response_url: cmd.response_url.clone() };
        // handle cmd
        if let &Some((ref captures, handler)) = &self.handler(&cmd) {
            handler.handle(&cmd, &captures, Box::new(responder));
        }
    }
}

#[derive(Default)]
pub struct Command {
    pub token: String,
    pub team_id: String,
    pub team_domain: String,
    pub channel_id: String,
    pub channel_name: String,
    pub user_id: String,
    pub user_name: String,
    pub command: String,
    pub text: String,
    pub response_url: String,
}

impl Command {
    pub fn from_params(params: HashMap<String, String>) -> Option<Command> {
        if let (Some(token),
                Some(team_id),
                Some(team_domain),
                Some(channel_id),
                Some(channel_name),
                Some(user_id),
                Some(user_name),
                Some(command),
                Some(text),
                Some(response_url)) = (params.get("token"),
                                       params.get("team_id"),
                                       params.get("team_domain"),
                                       params.get("channel_id"),
                                       params.get("channel_name"),
                                       params.get("user_id"),
                                       params.get("user_name"),
                                       params.get("command"),
                                       params.get("text"),
                                       params.get("response_url")) {
            Some(Command {
                token: token.clone(),
                team_id: team_id.clone(),
                team_domain: team_domain.clone(),
                channel_id: channel_id.clone(),
                channel_name: channel_name.clone(),
                user_id: user_id.clone(),
                user_name: user_name.clone(),
                command: command.clone(),
                text: text.clone(),
                response_url: response_url.clone(),
            })
        } else {
            None
        }
    }
}

impl Handler for Mux {
    // https://api.slack.com/slash-commands
    fn handle(&self, req: Request, res: Response) {
        let (_, _, _, _, _, mut body) = req.deconstruct();
        // parse params
        let params = params(&mut body);
        // parse cmd
        if let Some(cmd) = Command::from_params(params) {
            self.handle(&cmd)
        }
        let _ = res.send(b"ok");
        ()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::regex::{Regex,Captures};

    #[test]
    fn matches_commands() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (caps, matched) = MatchCommand("/test".to_owned()).matches(&cmd);
        assert!(matched)
    }

    #[test]
    fn matches_regexes() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (caps, matched) = MatchRegex(Regex::new("(test)").unwrap()).matches(&cmd);
        assert!(matched)
    }
}
<commit_msg>change name<commit_after>extern crate hyper;
extern crate rustc_serialize;
extern crate url;
extern crate regex;

use regex::{Captures, Regex};
use rustc_serialize::json;

use hyper::Client;
use hyper::server::{Handler, Request, Response as HyperResponse};
use std::collections::HashMap;
use std::io::Read;

fn params<R: Read>(read: &mut R) -> HashMap<String, String> {
    let mut buffer = String::new();
    read.read_to_string(&mut buffer).unwrap();
    let mut params = HashMap::new();
    for (k, v) in url::form_urlencoded::parse(buffer.as_bytes()) {
        params.insert(k, v);
    }
    params
}

pub enum Response {
    Channel(String),
    Ephemeral(String),
}

pub trait Responder {
    fn respond(&self, response: Response) -> ();
}

pub struct DefaultResponder {
    response_url: String,
}

// todo: attachments
#[derive(Debug, RustcEncodable)]
pub struct ResponseBody {
    pub text: String,
    pub response_type: Option<String>,
}

impl Responder for DefaultResponder {
    fn respond(&self, response: Response) {
        let body = match response {
            Response::Channel(text) => {
                ResponseBody {
                    text: text,
                    response_type: Some("in_channel".to_owned()),
                }
            }
            Response::Ephemeral(text) => {
                ResponseBody {
                    text: text,
                    response_type: None,
                }
            }
        };
        let client = Client::new();
        let _ = client.post(&self.response_url[..])
                      .body(json::encode(&body).unwrap().as_bytes())
                      .send();
    }
}

pub struct DiscardResponder;

impl Responder for DiscardResponder {
    fn respond(&self, _: Response) {

    }
}

/// A Handle handles matched commands
pub trait Handle: Sync + Send {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response>;
}

impl<F> Handle for F
    where F: Fn(&Command, &Option<Captures>, Box<Responder>) -> Option<Response>,
          F: Send + Sync
{
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        self(cmd, caps, responder)
    }
}

pub struct TokenValidator<H: Handle + 'static> {
    handler: H,
    token: String,
}

impl<H: Handle + 'static> Handle for TokenValidator<H> {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        if cmd.token == self.token {
            self.handler.handle(cmd, caps, responder)
        } else {
            None
        }
    }
}

/// A matcher matches commands
pub trait Matcher: Send + Sync {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool);
}

impl<F> Matcher for F
    where F: Fn(&Command) -> (Option<Captures>, bool),
          F: Send + Sync
{
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        self(cmd)
    }
}

/// A direct command matcher
///
pub struct MatchCommand(String);

impl Matcher for MatchCommand {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        (None, cmd.command == self.0)
    }
}

/// A regex pattern matcher
///
pub struct MatchRegex(Regex);

impl Matcher for MatchRegex {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        if self.0.is_match(cmd.command.as_ref()) {
            (self.0.captures(cmd.command.as_ref()), true)
        } else {
            (None, false)
        }
    }
}

/// A binding between a command handler and which commands its handles
pub struct Route {
    handler: Box<Handle>,
    matcher: Box<Matcher>,
}

///
/// A command de-multiplexor
///
#[derive(Default)]
pub struct Mux {
    routes: Vec<Box<Route>>,
}

impl Mux {
    pub fn command<C, T, H>(&mut self, cmd: C, token: T, handler: H)
        where C: Into<String>,
              T: Into<String>,
              H: Handle + 'static
    {
        self.matching(MatchCommand(cmd.into()),
                      TokenValidator {
                          handler: handler,
                          token: token.into(),
                      })
    }

    pub fn matching<M, H>(&mut self, matcher: M, handler: H)
        where M: Matcher + 'static,
              H: Handle + 'static
    {
        let route = Route {
            handler: Box::new(handler),
            matcher: Box::new(matcher),
        };
        self.route(route)
    }

    ///
    pub fn route(&mut self, route: Route) {
        self.routes.push(Box::new(route));
    }

    pub fn handler<'a>(&self, cmd: &'a Command) -> Option<(Option<Captures<'a>>, &Box<Handle>)> {
        for r in self.routes.iter() {
            if let (captures, true) = r.matcher.matches(cmd) {
                return Some((captures, &r.handler));
            }
        }
        None
    }

    pub fn handle(&self, cmd: &Command) {
        // set up responder
        let responder = DefaultResponder { response_url: cmd.response_url.clone() };
        // handle cmd
        if let &Some((ref captures, handler)) = &self.handler(&cmd) {
            handler.handle(&cmd, &captures, Box::new(responder));
        }
    }
}

#[derive(Default)]
pub struct Command {
    pub token: String,
    pub team_id: String,
    pub team_domain: String,
    pub channel_id: String,
    pub channel_name: String,
    pub user_id: String,
    pub user_name: String,
    pub command: String,
    pub text: String,
    pub response_url: String,
}

impl Command {
    pub fn from_params(params: HashMap<String, String>) -> Option<Command> {
        if let (Some(token),
                Some(team_id),
                Some(team_domain),
                Some(channel_id),
                Some(channel_name),
                Some(user_id),
                Some(user_name),
                Some(command),
                Some(text),
                Some(response_url)) = (params.get("token"),
                                       params.get("team_id"),
                                       params.get("team_domain"),
                                       params.get("channel_id"),
                                       params.get("channel_name"),
                                       params.get("user_id"),
                                       params.get("user_name"),
                                       params.get("command"),
                                       params.get("text"),
                                       params.get("response_url")) {
            Some(Command {
                token: token.clone(),
                team_id: team_id.clone(),
                team_domain: team_domain.clone(),
                channel_id: channel_id.clone(),
                channel_name: channel_name.clone(),
                user_id: user_id.clone(),
                user_name: user_name.clone(),
                command: command.clone(),
                text: text.clone(),
                response_url: response_url.clone(),
            })
        } else {
            None
        }
    }
}

impl Handler for Mux {
    // https://api.slack.com/slash-commands
    fn handle(&self, req: Request, res: HyperResponse) {
        let (_, _, _, _, _, mut body) = req.deconstruct();
        // parse params
        let params = params(&mut body);
        // parse cmd
        if let Some(cmd) = Command::from_params(params) {
            self.handle(&cmd)
        }
        let _ = res.send(b"ok");
        ()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::regex::{Regex,Captures};

    #[test]
    fn matches_commands() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (caps, matched) = MatchCommand("/test".to_owned()).matches(&cmd);
        assert!(matched)
    }

    #[test]
    fn matches_regexes() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (caps, matched) = MatchRegex(Regex::new("(test)").unwrap()).matches(&cmd);
        assert!(matched)
    }
}
<|endoftext|>


<commit_before>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate sha1;
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.update("Hello World!".as_bytes());
//! assert_eq!(m.hexdigest().as_slice(),
//!            "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(core, collections)]
#![unstable]

extern crate byteorder;
use std::io::{Cursor,Write};
use std::io::BufWriter;
use std::num::Int;
use byteorder::{BigEndian, WriteBytesExt};

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&format!("{:02x}", *b));
    }
    return s;
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        for i in range(16, 80) {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = n.rotate_left(1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in range(0, 80) {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = a.rotate_left(5)
                .wrapping_add(f)
                .wrapping_add(e)
                .wrapping_add(k)
                .wrapping_add(words[i]);
            e = d;
            d = c;
            c = b.rotate_left(30);
            b = a;
            a = tmp;
        }

        self.state[0] = self.state[0].wrapping_add(a);
        self.state[1] = self.state[1].wrapping_add(b);
        self.state[2] = self.state[2].wrapping_add(c);
        self.state[3] = self.state[3].wrapping_add(d);
        self.state[4] = self.state[4].wrapping_add(e);
    }

    /// Resets the hash object to it's initial state.
    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    /// Update hash with input data.
    pub fn update(&mut self, data: &[u8]) {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(data);

        for chunk in d.chunks(64) {
            if chunk.len() == 64 {
                self.len += chunk.len() as u64;
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state,
            data: Vec::new(),
            len: 0,
        };

        let mut w : Cursor<Vec<u8>> = Cursor::new(Vec::new());
        w.write(&*self.data);
        w.write_all(&[0x80]);
        let padding = 64 - ((self.data.len() + 9) % 64);
        for _ in range(0, padding) {
            w.write(&[0u8]);
        }

        w.write_u64::<BigEndian>((self.data.len() as u64 + self.len) * 8);
        for chunk in w.into_inner().chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_u32::<BigEndian>(n);
        }
    }

    /// Shortcut for getting `output` into a new vector.
    pub fn digest(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut buf);
        buf
    }

    /// Shortcut for getting a hex output of the vector.
    pub fn hexdigest(&self) -> String {
        to_hex(&self.digest())
    }
}

#[test]
fn test_simple() {
    let mut m = Sha1::new();

    let tests = [
        ("The quick brown fox jumps over the lazy dog",
         "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
        ("The quick brown fox jumps over the lazy cog",
         "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
        ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
        ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
        ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
         "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
    ];

    for &(s, ref h) in tests.iter() {
        let data = s.as_bytes();

        m.reset();
        m.update(data);
        let hh = m.hexdigest();

        assert_eq!(hh.len(), h.len());
		assert_eq!(hh, *h);
    }
}

#[test]
fn test_multiple_updates() {
    let mut m = Sha1::new();

    m.reset();
    m.update("The quick brown ".as_bytes());
    m.update("fox jumps over ".as_bytes());
    m.update("the lazy dog".as_bytes());
    let hh = m.hexdigest();

    let h = "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12";
    assert_eq!(hh.len(), h.len());
    assert_eq!(hh, &*h);
}
<commit_msg>Use range syntax<commit_after>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate sha1;
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.update("Hello World!".as_bytes());
//! assert_eq!(m.hexdigest().as_slice(),
//!            "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(core, collections)]
#![unstable]

extern crate byteorder;
use std::io::{Cursor,Write};
use std::io::BufWriter;
use std::num::Int;
use byteorder::{BigEndian, WriteBytesExt};

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&format!("{:02x}", *b));
    }
    return s;
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        for i in 16..80 {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = n.rotate_left(1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in 0..80 {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = a.rotate_left(5)
                .wrapping_add(f)
                .wrapping_add(e)
                .wrapping_add(k)
                .wrapping_add(words[i]);
            e = d;
            d = c;
            c = b.rotate_left(30);
            b = a;
            a = tmp;
        }

        self.state[0] = self.state[0].wrapping_add(a);
        self.state[1] = self.state[1].wrapping_add(b);
        self.state[2] = self.state[2].wrapping_add(c);
        self.state[3] = self.state[3].wrapping_add(d);
        self.state[4] = self.state[4].wrapping_add(e);
    }

    /// Resets the hash object to it's initial state.
    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    /// Update hash with input data.
    pub fn update(&mut self, data: &[u8]) {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(data);

        for chunk in d.chunks(64) {
            if chunk.len() == 64 {
                self.len += chunk.len() as u64;
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state,
            data: Vec::new(),
            len: 0,
        };

        let mut w : Cursor<Vec<u8>> = Cursor::new(Vec::new());
        w.write(&*self.data);
        w.write_all(&[0x80]);
        let padding = 64 - ((self.data.len() + 9) % 64);
        for _ in 0..padding {
            w.write(&[0u8]);
        }

        w.write_u64::<BigEndian>((self.data.len() as u64 + self.len) * 8);
        for chunk in w.into_inner().chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_u32::<BigEndian>(n);
        }
    }

    /// Shortcut for getting `output` into a new vector.
    pub fn digest(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut buf);
        buf
    }

    /// Shortcut for getting a hex output of the vector.
    pub fn hexdigest(&self) -> String {
        to_hex(&self.digest())
    }
}

#[test]
fn test_simple() {
    let mut m = Sha1::new();

    let tests = [
        ("The quick brown fox jumps over the lazy dog",
         "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
        ("The quick brown fox jumps over the lazy cog",
         "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
        ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
        ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
        ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
         "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
    ];

    for &(s, ref h) in tests.iter() {
        let data = s.as_bytes();

        m.reset();
        m.update(data);
        let hh = m.hexdigest();

        assert_eq!(hh.len(), h.len());
		assert_eq!(hh, *h);
    }
}

#[test]
fn test_multiple_updates() {
    let mut m = Sha1::new();

    m.reset();
    m.update("The quick brown ".as_bytes());
    m.update("fox jumps over ".as_bytes());
    m.update("the lazy dog".as_bytes());
    let hh = m.hexdigest();

    let h = "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12";
    assert_eq!(hh.len(), h.len());
    assert_eq!(hh, &*h);
}
<|endoftext|>


<commit_before>
pub fn xor(source: &[u8], key: &[u8]) -> Vec<u8> {
    if source.len() == 0 {
        return Vec::new();
    }
    if key.len() == 0 {
        return source.to_vec();
    }
    let key_iter = InfiniteByteIterator::new(key);
    source.iter().zip(key_iter).map(|(&a, b)| a ^ b).collect()
}

struct InfiniteByteIterator {
    bytes: Vec<u8>,
    index: uint
}

impl InfiniteByteIterator {
    pub fn new(bytes: &[u8]) -> InfiniteByteIterator {
        InfiniteByteIterator {
            bytes: bytes.to_vec(),
            index: 0
        }
    }
}

impl Iterator<u8> for InfiniteByteIterator {
    fn next(&mut self) -> Option<u8> {
        let byte = self.bytes[self.index];
        self.index = next_index(self.index, self.bytes.len());
        Some(byte)
    }
}

fn next_index(current: uint, count: uint) -> uint {
    let index = current + 1;
    if index < count {
        index
    } else {
        0
    }
}

#[cfg(test)]
mod test {

    use super::xor;

    #[test]
    fn test_result() {
        let source = [0, 1, 2, 3];
        let key = [34, 52];
        assert!(xor(source, key) == vec![34, 53, 32, 55]);
    }

    #[test]
    fn test_with_empty_key() {
        let source = [0, 1, 2, 3];
        let key = [];
        assert!(xor(source, key) == vec![0, 1, 2, 3]);
    }

    #[test]
    fn test_with_empty_source() {
        let source = [];
        let key = [45, 32, 56];
        assert!(xor(source, key) == vec![]);
    }
}
<commit_msg>Simplified the 'if' statement.<commit_after>
pub fn xor(source: &[u8], key: &[u8]) -> Vec<u8> {
    if source.len() == 0 || key.len() == 0 {
        return source.to_vec();
    }

    let key_iter = InfiniteByteIterator::new(key);
    source.iter().zip(key_iter).map(|(&a, b)| a ^ b).collect()
}

struct InfiniteByteIterator {
    bytes: Vec<u8>,
    index: uint
}

impl InfiniteByteIterator {
    pub fn new(bytes: &[u8]) -> InfiniteByteIterator {
        InfiniteByteIterator {
            bytes: bytes.to_vec(),
            index: 0
        }
    }
}

impl Iterator<u8> for InfiniteByteIterator {
    fn next(&mut self) -> Option<u8> {
        let byte = self.bytes[self.index];
        self.index = next_index(self.index, self.bytes.len());
        Some(byte)
    }
}

fn next_index(current: uint, count: uint) -> uint {
    let index = current + 1;
    if index < count {
        index
    } else {
        0
    }
}

#[cfg(test)]
mod test {

    use super::xor;

    #[test]
    fn test_result() {
        let source = [0, 1, 2, 3];
        let key = [34, 52];
        assert!(xor(source, key) == vec![34, 53, 32, 55]);
    }

    #[test]
    fn test_with_empty_key() {
        let source = [0, 1, 2, 3];
        let key = [];
        assert!(xor(source, key) == vec![0, 1, 2, 3]);
    }

    #[test]
    fn test_with_empty_source() {
        let source = [];
        let key = [45, 32, 56];
        assert!(xor(source, key) == vec![]);
    }
}
<|endoftext|>


<commit_before>/* Copyright 2015 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

#![feature(coerce_unsized)]
#![feature(std_panic)]
#![feature(recover)]

extern crate libc;
extern crate iup_sys;
extern crate kernel32;

#[cfg(windows)]
fn get_thread_id() -> isize {
    use kernel32::GetCurrentThreadId;
    unsafe { GetCurrentThreadId() as isize }
}

macro_rules! impl_control_traits {
    ($control:ident) => {
        unsafe impl Control for ::$control {
            fn handle(&self) -> *mut Ihandle {
                assert!(self.0.get() != ptr::null_mut(), "attempted to use destroyed control");
                ::check_thread();
                self.0.get()
            }
        }

        unsafe impl UnwrapHandle for ::$control {
            fn try_unwrap_handle(self) -> Result<*mut Ihandle, Self> {
                assert!(self.0.get() != ptr::null_mut(), "attempted to use destroyed control");
                self.0.try_unwrap().map_err(|handle_rc| ::$control(handle_rc))
            }
        }
    };
}

#[macro_use]
mod callbacks;
#[macro_use]
mod containers;

mod attributes;
mod button;
mod dialog;
mod handle_rc;

pub use dialog::{Dialog, ShowCallbackToken, ShowState};
pub use button::Button;
pub use containers::{Container, Fill, Hbox, Vbox};
pub use callbacks::{CallbackAction, Event};

// With this layout, you can glob import this module's contents but selectively import the
// above types if you want.
pub mod common_attrs_cbs {
    pub use attributes::{CommonAttributes, TitleAttribute};
    pub use callbacks::{MenuCommonCallbacks, NonMenuCommonCallbacks, ButtonCallback};
}

use std::ptr;
use std::sync::atomic::{AtomicIsize, Ordering, ATOMIC_ISIZE_INIT};
use libc::{c_char, c_int};
use iup_sys::*;

// returns false if a panic is pending, but cannot be propagated because the main loop level is too high
fn propagate_panic() -> bool {
    if callbacks::is_panic_pending() && main_loop_level() > 0 {
        exit_loop();
        return false;
    }
    if let Some(payload) = callbacks::take_panic_payload() {
        // TODO: once a new nightly is released, use this
        //::std::panic::propagate(payload);
        panic!(payload.downcast_ref::<String>().unwrap_or(&String::new()).clone());
    }
    true
}

pub fn main_loop() {
    unsafe {
        iup_open();

        // Callbacks can be called before main_loop() ever is. If they have been and have
        // panicked, we need to panic without calling IupMainLoop(). (IupMainLoopLevel() will
        // be 0 in a callback if it is running before IupMainLoop() has been called.)
        if !propagate_panic() { return; }
        IupMainLoop();
        propagate_panic();
    }
}

pub fn main_loop_level() -> i32 {
    unsafe {
        IupMainLoopLevel()
    }
}

pub fn exit_loop() {
    unsafe {
        IupExitLoop();
    }
}

fn iup_open() {
    check_thread();
    unsafe {
        IupOpen(ptr::null_mut(), ptr::null_mut());
        attributes::set_str_attribute(ptr::null_mut(), "UTF8MODE", "YES");
        attributes::set_str_attribute(ptr::null_mut(), "UTF8MODE_FILE", "YES");
    }
}

static THREAD_ID: AtomicIsize = ATOMIC_ISIZE_INIT;

fn check_thread() {
    let thread_id = get_thread_id();
    let prev = THREAD_ID.compare_and_swap(0, thread_id, Ordering::SeqCst);
    assert!(prev == 0 || prev == thread_id, "IUP/Clear Coat functions must be called from a single thread");
}

// Part of the contract of implementing this trait is that no invalid handle
// is returned. Either the handle will stay valid for the life of the object or
// the method will panic.
pub unsafe trait Control {
    fn handle(&self) -> *mut Ihandle;

    fn detach(&self) {
        unsafe { IupDetach(self.handle()); }
    }

    fn reparent(&self, new_parent: &Container, ref_child: Option<&Control>) -> Result<(), ()> {
        unsafe {
            let ref_child = ref_child.map(|c| c.handle()).unwrap_or(ptr::null_mut());
            if IupReparent(self.handle(), new_parent.handle(), ref_child) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    fn get_dialog(&self) -> Option<Dialog> {
        unsafe {
            let handle = IupGetDialog(self.handle());
            if handle == ptr::null_mut() {
                None
            } else {
                Some(Dialog::from_handle(handle))
            }
        }
    }
}

// If this wrapper has the only reference, it gives up shared ownership of the *mut Ihandle.
pub unsafe trait UnwrapHandle : Sized {
    fn try_unwrap_handle(self) -> Result<*mut Ihandle, Self>;
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ScreenPosition { // This is the name IUP uses: SCREENPOSITION attribute
    Absolute(i32),
    Left,
    Right,
    Top,
    Bottom,
    Center,
    MousePos,
    CenterParent,
    Current,
}

impl ScreenPosition {
    #[allow(dead_code)]
    fn from_int_x(i: c_int) -> ScreenPosition {
       match i {
           IUP_LEFT => ScreenPosition::Left,
           IUP_RIGHT => ScreenPosition::Right,
           IUP_CENTER => ScreenPosition::Center,
           IUP_MOUSEPOS => ScreenPosition::MousePos,
           IUP_CENTERPARENT => ScreenPosition::CenterParent,
           IUP_CURRENT => ScreenPosition::Current,
           _ => ScreenPosition::Absolute(i),
       }
    }

    #[allow(dead_code)]
    fn from_int_y(i: c_int) -> ScreenPosition {
       match i {
           IUP_TOP => ScreenPosition::Top,
           IUP_BOTTOM => ScreenPosition::Bottom,
           _ => Self::from_int_x(i),
       }
    }

    fn to_int(self) -> c_int {
        match self {
            ScreenPosition::Absolute(i) => i,
            ScreenPosition::Left => IUP_LEFT,
            ScreenPosition::Right => IUP_RIGHT,
            ScreenPosition::Top => IUP_TOP,
            ScreenPosition::Bottom => IUP_BOTTOM,
            ScreenPosition::Center => IUP_CENTER,
            ScreenPosition::MousePos => IUP_MOUSEPOS,
            ScreenPosition::CenterParent => IUP_CENTERPARENT,
            ScreenPosition::Current => IUP_CURRENT,
        }
    }
}

pub trait Popup : Control {
    fn popup(&self, x: ScreenPosition, y: ScreenPosition) -> Result<(), ()> {
        unsafe {
            if IupPopup(self.handle(), x.to_int(), y.to_int()) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }
}

#[derive(Copy,Clone)]
pub enum MouseButton {
    Button1,
    Button2,
    Button3,
    Button4,
    Button5,
}

impl MouseButton {
    fn from_int(i: c_int) -> MouseButton {
        match i {
            IUP_BUTTON1 => MouseButton::Button1,
            IUP_BUTTON2 => MouseButton::Button2,
            IUP_BUTTON3 => MouseButton::Button3,
            IUP_BUTTON4 => MouseButton::Button4,
            IUP_BUTTON5 => MouseButton::Button5,
            _ => panic!("unknown mouse button"),
        }
    }

    #[allow(dead_code)]
    fn to_int(self) -> c_int {
        match self {
            MouseButton::Button1 => IUP_BUTTON1,
            MouseButton::Button2 => IUP_BUTTON2,
            MouseButton::Button3 => IUP_BUTTON3,
            MouseButton::Button4 => IUP_BUTTON4,
            MouseButton::Button5 => IUP_BUTTON5,
        }
    }
}

#[derive(Clone)]
pub struct KeyboardMouseStatus {
    shift_pressed: bool,
    control_pressed: bool,
    alt_pressed: bool,
    sys_pressed: bool,
    button1_pressed: bool,
    button2_pressed: bool,
    button3_pressed: bool,
    button4_pressed: bool,
    button5_pressed: bool,
}

impl KeyboardMouseStatus {
    unsafe fn from_cstr(s: *const c_char) -> KeyboardMouseStatus {
        KeyboardMouseStatus {
            shift_pressed: iup_isshift(s),
            control_pressed: iup_iscontrol(s),
            alt_pressed: iup_isalt(s),
            sys_pressed: iup_issys(s),
            button1_pressed: iup_isbutton1(s),
            button2_pressed: iup_isbutton2(s),
            button3_pressed: iup_isbutton3(s),
            button4_pressed: iup_isbutton4(s),
            button5_pressed: iup_isbutton5(s),
        }
    }
}
<commit_msg>Add doc comment for main_loop<commit_after>/* Copyright 2015 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

#![feature(coerce_unsized)]
#![feature(std_panic)]
#![feature(recover)]

extern crate libc;
extern crate iup_sys;
extern crate kernel32;

#[cfg(windows)]
fn get_thread_id() -> isize {
    use kernel32::GetCurrentThreadId;
    unsafe { GetCurrentThreadId() as isize }
}

macro_rules! impl_control_traits {
    ($control:ident) => {
        unsafe impl Control for ::$control {
            fn handle(&self) -> *mut Ihandle {
                assert!(self.0.get() != ptr::null_mut(), "attempted to use destroyed control");
                ::check_thread();
                self.0.get()
            }
        }

        unsafe impl UnwrapHandle for ::$control {
            fn try_unwrap_handle(self) -> Result<*mut Ihandle, Self> {
                assert!(self.0.get() != ptr::null_mut(), "attempted to use destroyed control");
                self.0.try_unwrap().map_err(|handle_rc| ::$control(handle_rc))
            }
        }
    };
}

#[macro_use]
mod callbacks;
#[macro_use]
mod containers;

mod attributes;
mod button;
mod dialog;
mod handle_rc;

pub use dialog::{Dialog, ShowCallbackToken, ShowState};
pub use button::Button;
pub use containers::{Container, Fill, Hbox, Vbox};
pub use callbacks::{CallbackAction, Event};

// With this layout, you can glob import this module's contents but selectively import the
// above types if you want.
pub mod common_attrs_cbs {
    pub use attributes::{CommonAttributes, TitleAttribute};
    pub use callbacks::{MenuCommonCallbacks, NonMenuCommonCallbacks, ButtonCallback};
}

use std::ptr;
use std::sync::atomic::{AtomicIsize, Ordering, ATOMIC_ISIZE_INIT};
use libc::{c_char, c_int};
use iup_sys::*;

// returns false if a panic is pending, but cannot be propagated because the main loop level is too high
fn propagate_panic() -> bool {
    if callbacks::is_panic_pending() && main_loop_level() > 0 {
        exit_loop();
        return false;
    }
    if let Some(payload) = callbacks::take_panic_payload() {
        // TODO: once a new nightly is released, use this
        //::std::panic::propagate(payload);
        panic!(payload.downcast_ref::<String>().unwrap_or(&String::new()).clone());
    }
    true
}

/// Executes the user interaction until `exit_loop` is called or the last visible dialog is hidden.
///
/// If you cascade many calls to `main_loop`, there must be a `exit_loop` call for each cascade
/// level, as hiding all dialogs will close only one level. Call `main_loop_level` to obtain the
/// current level.
///
/// If `main_loop` is called without any visible dialogs and no active timers, the application will
/// hang, and it will not be possible to close the main loop. The process will have to be
/// interrupted by the system.
///
/// When the last visible dialog is hidden, the `exit_loop` function is automatically called,
/// causing the `main_loop` to return. To avoid that, call `set_lock_loop(true)` before hiding the
/// last dialog.
pub fn main_loop() {
    unsafe {
        iup_open();

        // Callbacks can be called before main_loop() ever is. If they have been and have
        // panicked, we need to panic without calling IupMainLoop(). (IupMainLoopLevel() will
        // be 0 in a callback if it is running before IupMainLoop() has been called.)
        if !propagate_panic() { return; }
        IupMainLoop();
        propagate_panic();
    }
}

pub fn main_loop_level() -> i32 {
    unsafe {
        IupMainLoopLevel()
    }
}

pub fn exit_loop() {
    unsafe {
        IupExitLoop();
    }
}

fn iup_open() {
    check_thread();
    unsafe {
        IupOpen(ptr::null_mut(), ptr::null_mut());
        attributes::set_str_attribute(ptr::null_mut(), "UTF8MODE", "YES");
        attributes::set_str_attribute(ptr::null_mut(), "UTF8MODE_FILE", "YES");
    }
}

static THREAD_ID: AtomicIsize = ATOMIC_ISIZE_INIT;

fn check_thread() {
    let thread_id = get_thread_id();
    let prev = THREAD_ID.compare_and_swap(0, thread_id, Ordering::SeqCst);
    assert!(prev == 0 || prev == thread_id, "IUP/Clear Coat functions must be called from a single thread");
}

// Part of the contract of implementing this trait is that no invalid handle
// is returned. Either the handle will stay valid for the life of the object or
// the method will panic.
pub unsafe trait Control {
    fn handle(&self) -> *mut Ihandle;

    fn detach(&self) {
        unsafe { IupDetach(self.handle()); }
    }

    fn reparent(&self, new_parent: &Container, ref_child: Option<&Control>) -> Result<(), ()> {
        unsafe {
            let ref_child = ref_child.map(|c| c.handle()).unwrap_or(ptr::null_mut());
            if IupReparent(self.handle(), new_parent.handle(), ref_child) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    fn get_dialog(&self) -> Option<Dialog> {
        unsafe {
            let handle = IupGetDialog(self.handle());
            if handle == ptr::null_mut() {
                None
            } else {
                Some(Dialog::from_handle(handle))
            }
        }
    }
}

// If this wrapper has the only reference, it gives up shared ownership of the *mut Ihandle.
pub unsafe trait UnwrapHandle : Sized {
    fn try_unwrap_handle(self) -> Result<*mut Ihandle, Self>;
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ScreenPosition { // This is the name IUP uses: SCREENPOSITION attribute
    Absolute(i32),
    Left,
    Right,
    Top,
    Bottom,
    Center,
    MousePos,
    CenterParent,
    Current,
}

impl ScreenPosition {
    #[allow(dead_code)]
    fn from_int_x(i: c_int) -> ScreenPosition {
       match i {
           IUP_LEFT => ScreenPosition::Left,
           IUP_RIGHT => ScreenPosition::Right,
           IUP_CENTER => ScreenPosition::Center,
           IUP_MOUSEPOS => ScreenPosition::MousePos,
           IUP_CENTERPARENT => ScreenPosition::CenterParent,
           IUP_CURRENT => ScreenPosition::Current,
           _ => ScreenPosition::Absolute(i),
       }
    }

    #[allow(dead_code)]
    fn from_int_y(i: c_int) -> ScreenPosition {
       match i {
           IUP_TOP => ScreenPosition::Top,
           IUP_BOTTOM => ScreenPosition::Bottom,
           _ => Self::from_int_x(i),
       }
    }

    fn to_int(self) -> c_int {
        match self {
            ScreenPosition::Absolute(i) => i,
            ScreenPosition::Left => IUP_LEFT,
            ScreenPosition::Right => IUP_RIGHT,
            ScreenPosition::Top => IUP_TOP,
            ScreenPosition::Bottom => IUP_BOTTOM,
            ScreenPosition::Center => IUP_CENTER,
            ScreenPosition::MousePos => IUP_MOUSEPOS,
            ScreenPosition::CenterParent => IUP_CENTERPARENT,
            ScreenPosition::Current => IUP_CURRENT,
        }
    }
}

pub trait Popup : Control {
    fn popup(&self, x: ScreenPosition, y: ScreenPosition) -> Result<(), ()> {
        unsafe {
            if IupPopup(self.handle(), x.to_int(), y.to_int()) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }
}

#[derive(Copy,Clone)]
pub enum MouseButton {
    Button1,
    Button2,
    Button3,
    Button4,
    Button5,
}

impl MouseButton {
    fn from_int(i: c_int) -> MouseButton {
        match i {
            IUP_BUTTON1 => MouseButton::Button1,
            IUP_BUTTON2 => MouseButton::Button2,
            IUP_BUTTON3 => MouseButton::Button3,
            IUP_BUTTON4 => MouseButton::Button4,
            IUP_BUTTON5 => MouseButton::Button5,
            _ => panic!("unknown mouse button"),
        }
    }

    #[allow(dead_code)]
    fn to_int(self) -> c_int {
        match self {
            MouseButton::Button1 => IUP_BUTTON1,
            MouseButton::Button2 => IUP_BUTTON2,
            MouseButton::Button3 => IUP_BUTTON3,
            MouseButton::Button4 => IUP_BUTTON4,
            MouseButton::Button5 => IUP_BUTTON5,
        }
    }
}

#[derive(Clone)]
pub struct KeyboardMouseStatus {
    shift_pressed: bool,
    control_pressed: bool,
    alt_pressed: bool,
    sys_pressed: bool,
    button1_pressed: bool,
    button2_pressed: bool,
    button3_pressed: bool,
    button4_pressed: bool,
    button5_pressed: bool,
}

impl KeyboardMouseStatus {
    unsafe fn from_cstr(s: *const c_char) -> KeyboardMouseStatus {
        KeyboardMouseStatus {
            shift_pressed: iup_isshift(s),
            control_pressed: iup_iscontrol(s),
            alt_pressed: iup_isalt(s),
            sys_pressed: iup_issys(s),
            button1_pressed: iup_isbutton1(s),
            button2_pressed: iup_isbutton2(s),
            button3_pressed: iup_isbutton3(s),
            button4_pressed: iup_isbutton4(s),
            button5_pressed: iup_isbutton5(s),
        }
    }
}
<|endoftext|>


<commit_before>extern crate hyper;

use hyper::Server;
use hyper::client::request::Request as ClientRequest;
use hyper::server::Request;
use hyper::server::Response;
use hyper::uri::RequestUri;
use hyper::net::Fresh;
use std::io::Read;

fn pass(req: Request, res: Response<Fresh>) {
    let url = match req.uri {
        RequestUri::AbsoluteUri(url) => Some(url),
        _ => None,
    }.unwrap();

    let new_res = ClientRequest::new(req.method, url);
    let mut body = String::new();
    new_res.unwrap().start().unwrap().send().unwrap().read_to_string(&mut body);
    let real = body.replace("Hoe", "Joe");
    println!("{:?}", body);
    res.send(real.as_bytes());
}

pub fn run() {
    Server::http("127.0.0.1:3000").unwrap().handle(pass);
}

#[test]
fn it_works() {
}
<commit_msg>cleaning up code, moving into functions<commit_after>extern crate hyper;

use hyper::Server;
use hyper::Url;
use hyper::client::request::Request as ClientRequest;
use hyper::server::Request;
use hyper::server::Response;
use hyper::uri::RequestUri;
use hyper::net::Fresh;
use std::io::Read;

fn pass(req: Request, res: Response<Fresh>) {
    // Setup a new Request based on the original
    let url = get_url(req.uri).unwrap();
    let new_req = ClientRequest::new(req.method, url);

    // Get the response from the new Request
    let mut new_res = new_req.unwrap().start().unwrap().send().unwrap();

    // Parse out the body and filter it
    let body = get_body(&mut new_res);
    let real = filter_body(&body);

    // Send the filtered response back to the client
    res.send(real.as_bytes());
}

fn filter_body(body: &String) -> String {
    body.replace("Hoe", "Joe")
}

fn get_url(uri: RequestUri) -> Option<Url> {
    match uri {
        RequestUri::AbsoluteUri(url) => Some(url),
        _ => None,
    }
}

fn get_body(res: &mut Read) -> String {
    let mut buffer = String::new();
    res.read_to_string(&mut buffer).unwrap();
    return buffer;
}

pub fn run() {
    Server::http("127.0.0.1:3000").unwrap().handle(pass);
}

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


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

#![crate_name = "cocoa"]
#![crate_type = "rlib"]

#![comment = "The Servo Parallel Browser Project"]
#![license = "MIT"]

#![feature(globs)]

#![allow(non_snake_case_functions)]

extern crate libc;
extern crate std;

#[cfg(target_os="macos")]
pub mod appkit;
#[cfg(target_os="macos")]
pub mod base;

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

#![crate_name = "cocoa"]
#![crate_type = "rlib"]

#![comment = "The Servo Parallel Browser Project"]
#![license = "MIT"]

#![feature(globs)]

#![allow(non_snake_case_functions)]

extern crate libc;

#[cfg(target_os="macos")]
pub mod appkit;
#[cfg(target_os="macos")]
pub mod base;

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Brandon Sanderson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE
 *
 */

use std::cmp::Ordering;

///Type that should be ordered in
///the reverse order of any value it contains.
///
///This only implements the ordering traits
///when V does, and will never implement any traits
///other than PartialEq, PartialOrd, Eq, and Ord.
///Extract the value to use it in other ways.
///Note: revord_var.0 can be used to extract the value
pub struct RevOrd<V>(pub V);

impl<V> PartialEq for RevOrd<V> where V: PartialEq {
  fn eq(&self, other:&RevOrd<V>) -> bool {
    other.0 == self.0
  }
}

impl<V> PartialOrd for RevOrd<V> where V: PartialOrd {
  fn partial_cmp(&self, other:&RevOrd<V>) -> Option<Ordering> {
    (other.0).partial_cmp(&self.0)
  }
}

impl<V> Eq for RevOrd<V> where V: Eq {}

impl<V> Ord for RevOrd<V> where V: Ord {
    fn cmp(&self, other:&RevOrd<V>) -> Ordering {
      other.0.cmp(&self.0)
    }
}

#[cfg(test)]
mod test {

  use super::RevOrd;

  #[test]
  fn int_test() {
    assert!(RevOrd(1) > RevOrd(2));
    assert!(RevOrd(1) < RevOrd(0));
  }
}
<commit_msg>Add stability attribute<commit_after>/*
 * Copyright (c) 2015 Brandon Sanderson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE
 *
 */

use std::cmp::Ordering;

///Type that should be ordered in
///the reverse order of any value it contains.
///
///This only implements the ordering traits
///when V does, and will never implement any traits
///other than PartialEq, PartialOrd, Eq, and Ord.
///Extract the value to use it in other ways.
///Note: revord_var.0 can be used to extract the value
#[unstable]
pub struct RevOrd<V>(pub V);

impl<V> PartialEq for RevOrd<V> where V: PartialEq {
  fn eq(&self, other:&RevOrd<V>) -> bool {
    other.0 == self.0
  }
}

impl<V> PartialOrd for RevOrd<V> where V: PartialOrd {
  fn partial_cmp(&self, other:&RevOrd<V>) -> Option<Ordering> {
    (other.0).partial_cmp(&self.0)
  }
}

impl<V> Eq for RevOrd<V> where V: Eq {}

impl<V> Ord for RevOrd<V> where V: Ord {
    fn cmp(&self, other:&RevOrd<V>) -> Ordering {
      other.0.cmp(&self.0)
    }
}

#[cfg(test)]
mod test {

  use super::RevOrd;

  #[test]
  fn int_test() {
    assert!(RevOrd(1) > RevOrd(2));
    assert!(RevOrd(1) < RevOrd(0));
  }
}
<|endoftext|>


<commit_before>use std::io::{Read, Result, Write};

pub struct TeeReader<R: Read,W: Write> {
    reader: R,
    writer: W
}

impl<R: Read, W: Write> TeeReader<R,W> {
    /// Returns a TeeReader which can be used as Read whose
    /// reads delegate ready bytes read to the provided reader and write to the provided
    /// writer. This write must complete before the read completes.
    ///
    /// Errors reported by the read will be interpreted as Errors for the read
    pub fn new(reader: R, writer: W) -> TeeReader<R,W>  {
        TeeReader { reader: reader, writer: writer }
    }
}

impl<R: Read, W: Write> Read for TeeReader<R,W> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let n = try!(self.reader.read(buf));
        try!(self.writer.write_all(&buf[..n]));
        Ok(n)
    }
}

#[test]
fn it_works() {
}
<commit_msg>struct doc<commit_after>use std::io::{Read, Result, Write};

/// An adapter for readers whose inputs
/// are written to a tee(1)'d writer
pub struct TeeReader<R: Read,W: Write> {
    reader: R,
    writer: W
}

impl<R: Read, W: Write> TeeReader<R,W> {
    /// Returns a TeeReader which can be used as Read whose
    /// reads delegate ready bytes read to the provided reader and write to the provided
    /// writer. This write must complete before the read completes.
    ///
    /// Errors reported by the read will be interpreted as Errors for the read
    pub fn new(reader: R, writer: W) -> TeeReader<R,W>  {
        TeeReader { reader: reader, writer: writer }
    }
}

impl<R: Read, W: Write> Read for TeeReader<R,W> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let n = try!(self.reader.read(buf));
        try!(self.writer.write_all(&buf[..n]));
        Ok(n)
    }
}

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