<commit_before>use std::io::{Read, BufRead, Error as IoError, ErrorKind};
use std::str::{from_utf8, Utf8Error};

use num::bigint::{BigInt, ToBigInt, Sign, ParseBigIntError};
use byteorder::{ReadBytesExt, LittleEndian, Error as ByteorderError};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        ReadError(err: ByteorderError) {
            from()
        }
        IoError(err: IoError) {
            from()
        }
        UnknownOpcode(opcode: u8) {}
        InvalidInt {
            from(Utf8Error)
            from(ParseBigIntError)
        }
        InvalidString
        ExpectedTrailingL
        InvalidLong
    }
}

#[derive(Debug)]
pub enum OpCode {
    Int(BigInt),
    BinInt(i32),
    BinInt1(u8),
    BinInt2(u16),
    Long(BigInt),
    Long1(BigInt),
    Long4(BigInt),

    String(Vec<u8>),
    BinString(Vec<u8>),
    ShortBinString(Vec<u8>),

    None,

    NewTrue,
    NewFalse,

    Unicode(String),
    BinUnicode(String),

    Float(f64),
    BinFloat(f64),

    EmptyList,
    Append,
    Appends,
    List,

    EmptyTuple,
    Tuple,
    Tuple1,
    Tuple2,
    Tuple3,

    EmptyDict,
    Dict,
    SetItem,
    SetItems,

    Pop,
    Dup,
    Mark,
    PopMark,

    Get(usize),
    BinGet(usize),
    LongBinGet(usize),
    Put(usize),
    BinPut(usize),
    LongBinPut(usize),

    Ext1(u8),
    Ext2(u16),
    Ext4(i32),

    Global(Vec<u8>, Vec<u8>),
    Reduce,
    Build,
    Inst(Vec<u8>, Vec<u8>),
    Obj,
    NewObj,
    Proto(u8),
    Stop,
    PersId(Vec<u8>),
    BinPersId,
}

fn read_exact<R>(rd: &mut R, mut buf: &mut [u8]) -> Result<(), IoError> where R: Read {
    while !buf.is_empty() {
        match rd.read(buf) {
            Ok(0) => break,
            Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; }
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(IoError::new(ErrorKind::Other,
                       "failed to fill whole buffer"))
    } else {
        Ok(())
    }
}

pub fn read_until_newline<R>(rd: &mut R) -> Result<Vec<u8>, Error> where R: Read + BufRead {
    let mut buf = Vec::new();
    try!(rd.read_until('\n' as u8, &mut buf));

    // Skip last symbol — \n
    match buf.split_last() {
        None => Err(Error::InvalidString),
        Some((_last, init)) => Ok(init.to_vec()),
    }
}

pub fn read_long<R>(rd: &mut R, length: usize) -> Result<BigInt, Error> where R: Read + BufRead {
    let mut buf = vec![0; length];
    try!(read_exact(rd, buf.as_mut()));

    let mut n = BigInt::from_bytes_le(Sign::Plus, &buf);

    let last = match buf.last_mut() {
        None => return Err(Error::InvalidLong),
        Some(last) => last,
    };

    if *last > 127 {
        n = n - (1.to_bigint().unwrap() << (length * 8))
    }

    Ok(n)
}

pub fn read_opcode<R>(rd: &mut R) -> Result<OpCode, Error> where R: Read + BufRead {
    let marker = try!(rd.read_u8());
    return Ok(match marker {
        73 => {
            let s = try!(read_until_newline(rd));
            OpCode::Int(try!(try!(from_utf8(&s)).parse()))  // http://rust-num.github.io/num/num/bigint/struct.BigInt.html#method.parse_bytes
        },
        74 => OpCode::BinInt(try!(rd.read_i32::<LittleEndian>())),
        75 => OpCode::BinInt1(try!(rd.read_u8())),
        77 => OpCode::BinInt2(try!(rd.read_u16::<LittleEndian>())),
        76 => {
            let s = try!(read_until_newline(rd));

            let init = match s.split_last() {
                None => return Err(Error::InvalidString),
                Some((&76, init)) => init,
                Some(_) => return Err(Error::ExpectedTrailingL),
            };

            OpCode::Long(try!(try!(from_utf8(init)).parse()))
        },
        138 => {
            let length = try!(rd.read_u8());
            OpCode::Long1(try!(read_long(rd, length as usize)))

        },
        139 => {
            let length = try!(rd.read_i32::<LittleEndian>());
            OpCode::Long1(try!(read_long(rd, length as usize)))

        },
        c => return Err(Error::UnknownOpcode(c)),
    })
}

#[cfg(test)]
mod tests {
    use std::io::{Cursor};

    use num::{FromPrimitive};

    use super::{OpCode, Error, read_opcode};

    macro_rules! t {
        ($buffer: expr, $pat:pat, $result:expr) => ({
            match read_opcode(&mut Cursor::new(&$buffer[..])) {
                $pat => $result,
                other => {
                    println!("ERROR {:?}", other);
                    assert!(false)
                },
            }
        })
    }

    #[test]
    fn test_int() {
        t!(b"I", Err(Error::InvalidString), assert!(true));
        t!(b"I\n", Err(Error::InvalidInt), assert!(true));
        t!(b"Iabc\n", Err(Error::InvalidInt), assert!(true));
        t!(b"I123\n", Ok(OpCode::Int(n)), assert_eq!(n, FromPrimitive::from_usize(123).unwrap()));
    }

    #[test]
    fn test_bin_int() {
        t!(b"J\x0a", Err(Error::ReadError(_)), assert!(true));
        t!(b"J\x0a\x00\x00\x00", Ok(OpCode::BinInt(n)), assert_eq!(n, 10));
        t!(b"J\x0a\x00\x00\x01", Ok(OpCode::BinInt(n)), assert_eq!(n, 16777226));
    }

    #[test]
    fn test_bin_int1() {
        t!(b"K", Err(Error::ReadError(_)), assert!(true));
        t!(b"K\x0a", Ok(OpCode::BinInt1(n)), assert_eq!(n, 10));
    }

    #[test]
    fn test_bin_int2() {
        t!(b"M\x0a", Err(Error::ReadError(_)), assert!(true));
        t!(b"M\x0a\x00\x00\x00", Ok(OpCode::BinInt2(n)), assert_eq!(n, 10));
        t!(b"M\x0a\x01\x00\x00", Ok(OpCode::BinInt2(n)), assert_eq!(n, 266));
    }

    #[test]
    fn test_long() {
        t!(b"L", Err(Error::InvalidString), assert!(true));
        t!(b"L\n", Err(Error::InvalidString), assert!(true));
        t!(b"Labc\n", Err(Error::ExpectedTrailingL), assert!(true));
        t!(b"LabcL\n", Err(Error::InvalidInt), assert!(true));
        t!(b"L123L\n", Ok(OpCode::Long(n)), assert_eq!(n, FromPrimitive::from_usize(123).unwrap()));
    }

    #[test]
    fn test_long1() {
        t!(b"\x8a", Err(Error::ReadError(_)), assert!(true));
        t!(b"\x8a\x01\x0a", Ok(OpCode::Long1(n)), assert_eq!(n, FromPrimitive::from_usize(10).unwrap()));
        t!(b"\x8a\x01\xf6", Ok(OpCode::Long1(n)), assert_eq!(n, FromPrimitive::from_isize(-10).unwrap()));
        t!(b"\x8a\x02.\xfb", Ok(OpCode::Long1(n)), assert_eq!(n, FromPrimitive::from_isize(-1234).unwrap()));
    }

    #[test]
    fn test_long4() {
        t!(b"\x8b\x0a", Err(Error::ReadError(_)), assert!(true));
    }
}
<commit_msg>Add long4 tests<commit_after>use std::io::{Read, BufRead, Error as IoError, ErrorKind};
use std::str::{from_utf8, Utf8Error};

use num::bigint::{BigInt, ToBigInt, Sign, ParseBigIntError};
use byteorder::{ReadBytesExt, LittleEndian, Error as ByteorderError};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        ReadError(err: ByteorderError) {
            from()
        }
        IoError(err: IoError) {
            from()
        }
        UnknownOpcode(opcode: u8) {}
        InvalidInt {
            from(Utf8Error)
            from(ParseBigIntError)
        }
        InvalidString
        ExpectedTrailingL
        InvalidLong
    }
}

#[derive(Debug)]
pub enum OpCode {
    Int(BigInt),
    BinInt(i32),
    BinInt1(u8),
    BinInt2(u16),
    Long(BigInt),
    Long1(BigInt),
    Long4(BigInt),

    String(Vec<u8>),
    BinString(Vec<u8>),
    ShortBinString(Vec<u8>),

    None,

    NewTrue,
    NewFalse,

    Unicode(String),
    BinUnicode(String),

    Float(f64),
    BinFloat(f64),

    EmptyList,
    Append,
    Appends,
    List,

    EmptyTuple,
    Tuple,
    Tuple1,
    Tuple2,
    Tuple3,

    EmptyDict,
    Dict,
    SetItem,
    SetItems,

    Pop,
    Dup,
    Mark,
    PopMark,

    Get(usize),
    BinGet(usize),
    LongBinGet(usize),
    Put(usize),
    BinPut(usize),
    LongBinPut(usize),

    Ext1(u8),
    Ext2(u16),
    Ext4(i32),

    Global(Vec<u8>, Vec<u8>),
    Reduce,
    Build,
    Inst(Vec<u8>, Vec<u8>),
    Obj,
    NewObj,
    Proto(u8),
    Stop,
    PersId(Vec<u8>),
    BinPersId,
}

fn read_exact<R>(rd: &mut R, mut buf: &mut [u8]) -> Result<(), IoError> where R: Read {
    while !buf.is_empty() {
        match rd.read(buf) {
            Ok(0) => break,
            Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; }
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(IoError::new(ErrorKind::Other,
                       "failed to fill whole buffer"))
    } else {
        Ok(())
    }
}

pub fn read_until_newline<R>(rd: &mut R) -> Result<Vec<u8>, Error> where R: Read + BufRead {
    let mut buf = Vec::new();
    try!(rd.read_until('\n' as u8, &mut buf));

    // Skip last symbol — \n
    match buf.split_last() {
        None => Err(Error::InvalidString),
        Some((_last, init)) => Ok(init.to_vec()),
    }
}

pub fn read_long<R>(rd: &mut R, length: usize) -> Result<BigInt, Error> where R: Read + BufRead {
    let mut buf = vec![0; length];
    try!(read_exact(rd, buf.as_mut()));

    let mut n = BigInt::from_bytes_le(Sign::Plus, &buf);

    let last = match buf.last_mut() {
        None => return Err(Error::InvalidLong),
        Some(last) => last,
    };

    if *last > 127 {
        n = n - (1.to_bigint().unwrap() << (length * 8))
    }

    Ok(n)
}

pub fn read_opcode<R>(rd: &mut R) -> Result<OpCode, Error> where R: Read + BufRead {
    let marker = try!(rd.read_u8());
    return Ok(match marker {
        73 => {
            let s = try!(read_until_newline(rd));
            OpCode::Int(try!(try!(from_utf8(&s)).parse()))  // http://rust-num.github.io/num/num/bigint/struct.BigInt.html#method.parse_bytes
        },
        74 => OpCode::BinInt(try!(rd.read_i32::<LittleEndian>())),
        75 => OpCode::BinInt1(try!(rd.read_u8())),
        77 => OpCode::BinInt2(try!(rd.read_u16::<LittleEndian>())),
        76 => {
            let s = try!(read_until_newline(rd));

            let init = match s.split_last() {
                None => return Err(Error::InvalidString),
                Some((&76, init)) => init,
                Some(_) => return Err(Error::ExpectedTrailingL),
            };

            OpCode::Long(try!(try!(from_utf8(init)).parse()))
        },
        138 => {
            let length = try!(rd.read_u8());
            OpCode::Long1(try!(read_long(rd, length as usize)))

        },
        139 => {
            let length = try!(rd.read_i32::<LittleEndian>());
            OpCode::Long4(try!(read_long(rd, length as usize)))

        },
        c => return Err(Error::UnknownOpcode(c)),
    })
}

#[cfg(test)]
mod tests {
    use std::io::{Cursor};

    use num::{FromPrimitive};

    use super::{OpCode, Error, read_opcode};

    macro_rules! t {
        ($buffer: expr, $pat:pat, $result:expr) => ({
            match read_opcode(&mut Cursor::new(&$buffer[..])) {
                $pat => $result,
                other => {
                    println!("ERROR {:?}", other);
                    assert!(false)
                },
            }
        })
    }

    #[test]
    fn test_int() {
        t!(b"I", Err(Error::InvalidString), assert!(true));
        t!(b"I\n", Err(Error::InvalidInt), assert!(true));
        t!(b"Iabc\n", Err(Error::InvalidInt), assert!(true));
        t!(b"I123\n", Ok(OpCode::Int(n)), assert_eq!(n, FromPrimitive::from_usize(123).unwrap()));
    }

    #[test]
    fn test_bin_int() {
        t!(b"J\x0a", Err(Error::ReadError(_)), assert!(true));
        t!(b"J\x0a\x00\x00\x00", Ok(OpCode::BinInt(n)), assert_eq!(n, 10));
        t!(b"J\x0a\x00\x00\x01", Ok(OpCode::BinInt(n)), assert_eq!(n, 16777226));
    }

    #[test]
    fn test_bin_int1() {
        t!(b"K", Err(Error::ReadError(_)), assert!(true));
        t!(b"K\x0a", Ok(OpCode::BinInt1(n)), assert_eq!(n, 10));
    }

    #[test]
    fn test_bin_int2() {
        t!(b"M\x0a", Err(Error::ReadError(_)), assert!(true));
        t!(b"M\x0a\x00\x00\x00", Ok(OpCode::BinInt2(n)), assert_eq!(n, 10));
        t!(b"M\x0a\x01\x00\x00", Ok(OpCode::BinInt2(n)), assert_eq!(n, 266));
    }

    #[test]
    fn test_long() {
        t!(b"L", Err(Error::InvalidString), assert!(true));
        t!(b"L\n", Err(Error::InvalidString), assert!(true));
        t!(b"Labc\n", Err(Error::ExpectedTrailingL), assert!(true));
        t!(b"LabcL\n", Err(Error::InvalidInt), assert!(true));
        t!(b"L123L\n", Ok(OpCode::Long(n)), assert_eq!(n, FromPrimitive::from_usize(123).unwrap()));
    }

    #[test]
    fn test_long1() {
        t!(b"\x8a", Err(Error::ReadError(_)), assert!(true));
        t!(b"\x8a\x01\x0a", Ok(OpCode::Long1(n)), assert_eq!(n, FromPrimitive::from_usize(10).unwrap()));
        t!(b"\x8a\x01\xf6", Ok(OpCode::Long1(n)), assert_eq!(n, FromPrimitive::from_isize(-10).unwrap()));
        t!(b"\x8a\x02.\xfb", Ok(OpCode::Long1(n)), assert_eq!(n, FromPrimitive::from_isize(-1234).unwrap()));
    }

    #[test]
    fn test_long4() {
        t!(b"\x8b\x0a", Err(Error::ReadError(_)), assert!(true));
        t!(b"\x8b\x01\x00\x00\x00\x0a", Ok(OpCode::Long4(n)), assert_eq!(n, FromPrimitive::from_usize(10).unwrap()));
        t!(b"\x8b\x01\x00\x00\x00\xf6", Ok(OpCode::Long4(n)), assert_eq!(n, FromPrimitive::from_isize(-10).unwrap()));
        t!(b"\x8b\x02\x00\x00\x00.\xfb", Ok(OpCode::Long4(n)), assert_eq!(n, FromPrimitive::from_isize(-1234).unwrap()));
    }
}
<|endoftext|>


<commit_before>use machine;
use notex::Notex;

const PAGE_TABLE_ENTRIES: usize = 1024;
const PAGE_TABLE_SIZE: usize = 4096;

type PageTable = [u32; PAGE_TABLE_ENTRIES];

// Overallocate. We'll loop through it to get a page-aligned piece of memory
static INITIAL_TABLE_NOTEX: Notex<[u32; PAGE_TABLE_ENTRIES * 3]> = notex!([0; PAGE_TABLE_ENTRIES * 3]);

static NEXT_FRAME_NOTEX: Notex<u32> = notex!(0x100);

fn page_table_for(vaddr: u32, next_frame: &mut u32) -> &'static mut PageTable {
    let pd_index = vaddr >> 22;
    unsafe {
        // PD[1023] -> pd_addr. pd_addr[1023] -> pd_addr
        let pd = 0xFFFFF_000 as *mut PageTable;
        if (*pd)[pd_index as usize] & 1 == 0 {
            (*pd)[pd_index as usize] = (*next_frame << 12) | 0b11;
            *next_frame += 1;
        }
        &mut *((0xFFC00_000 + 0x1_000 * pd_index) as *mut PageTable)
    }
}

#[allow(unused_assignments)]
pub fn make_present(addr: u32) {
    let mut next_frame = *NEXT_FRAME_NOTEX.lock();
    let page_number = (addr >> 12) & 0x3ff;
    let pt = page_table_for(addr, &mut next_frame);
    pt[page_number as usize] = next_frame << 12 | 0b11;
    next_frame += 1;
}

pub fn init() {
    unsafe {
        let initial_table_area = *INITIAL_TABLE_NOTEX.lock();
        let unalligned_pd_addr = initial_table_area[0] as *const u32 as usize;
        let alligned_pd_addr = unalligned_pd_addr +
            (PAGE_TABLE_SIZE -
             (unalligned_pd_addr % PAGE_TABLE_SIZE));
        let pd = alligned_pd_addr as *mut PageTable;

        let first_pt: *mut PageTable = pd.offset(1);
        (*pd)[0] = (first_pt as u32) | 0b11; // Read-write, present

        for frame_num in 0..0x100 {
            (*first_pt)[frame_num as usize] = (frame_num << 12) | 0b11;
        }

        (*pd)[1023] = (alligned_pd_addr as u32) | 0b11; // The "recursive paging trick"
        machine::enable_paging(alligned_pd_addr as *const u32);
    }
}
<commit_msg>Fix awkward paging bug<commit_after>use machine;
use notex::Notex;

const PAGE_TABLE_ENTRIES: usize = 1024;
const PAGE_TABLE_SIZE: usize = 4096;

type PageTable = [u32; PAGE_TABLE_ENTRIES];

// Overallocate. We'll loop through it to get a page-aligned piece of memory
static INITIAL_TABLE_NOTEX: Notex<[u32; PAGE_TABLE_ENTRIES * 3]> = notex!([0; PAGE_TABLE_ENTRIES * 3]);

static NEXT_FRAME_NOTEX: Notex<u32> = notex!(0x100);

fn page_table_for(vaddr: u32, next_frame: &mut u32) -> &'static mut PageTable {
    let pd_index = vaddr >> 22;
    unsafe {
        // PD[1023] -> pd_addr. pd_addr[1023] -> pd_addr
        let pd = 0xFFFFF_000 as *mut PageTable;
        if (*pd)[pd_index as usize] & 1 == 0 {
            (*pd)[pd_index as usize] = (*next_frame << 12) | 0b11;
            *next_frame += 1;
        }
        &mut *((0xFFC00_000 + 0x1_000 * pd_index) as *mut PageTable)
    }
}

#[allow(unused_assignments)]
pub fn make_present(addr: u32) {
    let mut next_frame = NEXT_FRAME_NOTEX.lock();
    let page_number = (addr >> 12) & 0x3ff;
    let pt = page_table_for(addr, &mut *next_frame);
    pt[page_number as usize] = *next_frame << 12 | 0b11;
    *next_frame += 1;
}

pub fn init() {
    unsafe {
        let initial_table_area = *INITIAL_TABLE_NOTEX.lock();
        let unalligned_pd_addr = initial_table_area[0] as *const u32 as usize;
        let alligned_pd_addr = unalligned_pd_addr +
            (PAGE_TABLE_SIZE -
             (unalligned_pd_addr % PAGE_TABLE_SIZE));
        let pd = alligned_pd_addr as *mut PageTable;

        let first_pt: *mut PageTable = pd.offset(1);
        (*pd)[0] = (first_pt as u32) | 0b11; // Read-write, present

        for frame_num in 0..0x100 {
            (*first_pt)[frame_num as usize] = (frame_num << 12) | 0b11;
        }

        (*pd)[1023] = (alligned_pd_addr as u32) | 0b11; // The "recursive paging trick"
        machine::enable_paging(alligned_pd_addr as *const u32);
    }
}
<|endoftext|>


<commit_before>use structs::{Op, OpStream};
use structs::Op::*;

pub fn parse(text: &[u8]) -> Result<Vec<Op>, String> {
    let mut stack = vec![];
    let mut current = vec![];
    let mut line = 1;
    let mut column = 1;

    for c in text {
        match *c {
            b'+' => current.push(Add(0x01)),
            b'-' => current.push(Add(0xff)),
            b'>' => current.push(Mov(1)),
            b'<' => current.push(Mov(-1)),
            b'.' => current.push(Out),
            b',' => current.push(In),
            b'[' => {
                stack.push(current);
                current = vec![];
            }
            b']' => {
                let opstream = OpStream { ops: current };
                current = match stack.pop() {
                    Some(v) => v,
                    None => return Err(format!("Stray ] in line {}, column {}", line, column)),
                };
                current.push(Loop(opstream));
            }
            _ => {}
        }
        if *c == b'\n' {
            line += 1;
            column = 1;
        } else {
            column += 1;
        }
    }
    if !stack.is_empty() {
        return Err(format!("Missing ] in line {}, column {}", line, column));
    }
    Ok(current)
}

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

    use structs::OpStream;
    use structs::Op::*;

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        assert_eq!(parse(&input[..]),
                   Ok(vec![Add(0x01),
                           Add(0xff),
                           Loop(OpStream { ops: vec![Add(1), Out, In] }),
                           Add(0x01)]));
    }

    #[test]
    fn test_parse_stray() {
        let input = include_bytes!("../test_cases/stray.bf");
        assert_eq!(parse(&input[..]),
                   Err("Stray ] in line 3, column 3".to_string()));
    }

    #[test]
    fn test_parse_incomplete() {
        let input = include_bytes!("../test_cases/incomplete.bf");
        assert_eq!(parse(&input[..]),
                   Err("Missing ] in line 4, column 1".to_string()));
    }
}
<commit_msg>test: minimally increase parser coverage<commit_after>use structs::{Op, OpStream};
use structs::Op::*;

pub fn parse(text: &[u8]) -> Result<Vec<Op>, String> {
    let mut stack = vec![];
    let mut current = vec![];
    let mut line = 1;
    let mut column = 1;

    for c in text {
        match *c {
            b'+' => current.push(Add(0x01)),
            b'-' => current.push(Add(0xff)),
            b'>' => current.push(Mov(1)),
            b'<' => current.push(Mov(-1)),
            b'.' => current.push(Out),
            b',' => current.push(In),
            b'[' => {
                stack.push(current);
                current = vec![];
            }
            b']' => {
                let opstream = OpStream { ops: current };
                current = match stack.pop() {
                    Some(v) => v,
                    None => return Err(format!("Stray ] in line {}, column {}", line, column)),
                };
                current.push(Loop(opstream));
            }
            _ => {}
        }
        if *c == b'\n' {
            line += 1;
            column = 1;
        } else {
            column += 1;
        }
    }
    if !stack.is_empty() {
        return Err(format!("Missing ] in line {}, column {}", line, column));
    }
    Ok(current)
}

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

    use structs::OpStream;
    use structs::Op::*;

    #[test]
    fn test_parse() {
        let input = b"+>-[+.,]+<";
        assert_eq!(parse(&input[..]),
                   Ok(vec![Add(0x01),
                           Mov(1),
                           Add(0xff),
                           Loop(OpStream { ops: vec![Add(1), Out, In] }),
                           Add(0x01),
                           Mov(-1)]));
    }

    #[test]
    fn test_parse_stray() {
        let input = include_bytes!("../test_cases/stray.bf");
        assert_eq!(parse(&input[..]),
                   Err("Stray ] in line 3, column 3".to_string()));
    }

    #[test]
    fn test_parse_incomplete() {
        let input = include_bytes!("../test_cases/incomplete.bf");
        assert_eq!(parse(&input[..]),
                   Err("Missing ] in line 4, column 1".to_string()));
    }
}
<|endoftext|>


<commit_before>use ::*;

fn out<S: ToString>(screen : &mut RawTerminal<Stdout>, output : S) {
    write!(*screen, "{}", output.to_string()).unwrap();
}

fn curs(screen : &mut RawTerminal<Stdout>, coord : Coord) {
    out(screen, termion::cursor::Goto(coord.col+1, coord.row+1));
}

pub fn render_loop(
    stop         : Arc<Mutex<bool>>,
    floor        : Arc<Mutex<Floor>>,
    player       : Arc<Mutex<Player>>,
    dirty_coords : Arc<Mutex<Vec<Coord>>>,
    monsters     : Arc<Mutex<Vec<Monster>>>,
) {
    let mut screen = &mut stdout().into_raw_mode().unwrap();
    out(screen, termion::cursor::Hide); // Hide the cursor
    out(screen, termion::clear::All);   // Clear the screen

    // Draw the entire floor
    curs(screen, Coord::new(0,0));
    {
        let floor = floor.lock().unwrap();
        for row in &floor.tiles {
            for tile in row {
                if let Some(ref wall) = tile.wall {
                    out(screen, wall);
                } else {
                    out(screen, " ");
                }
            }
            out(screen, "\r\n");
        }
    }

    // Render Loop
    loop {
        sleep(Duration::from_millis(10));
        {
            if *stop.lock().unwrap() {
                break;
            }
        }

        // Lock floor first...
        let floor = floor.lock().unwrap();

        // Redraw any dirty coordinates with floor tiles
        let mut dirty_coords = dirty_coords.lock().unwrap();
        for coord in dirty_coords.drain(..) {
            curs(screen, coord);
            out(screen, floor.get_symbol(&coord));
        }

        // Render Player
        let mut player = player.lock().unwrap();
        if player.dirty {
            player.dirty = false;
            // Player's sword
            curs(screen, player.sword_coord);
            out(screen, Fg(Red));
            out(screen, sword_symbol(player.facing));
            // Player himself
            curs(screen, player.coord);
            out(screen, Fg(Blue));
            out(screen, &player.symbol);
            out(screen, Fg(Reset));
        }
        // Player Score
        let score_string = format!("Score: {}", player.score);
        curs(screen, Coord::new((floor.cols - score_string.len()) as u16,
                                floor.rows as u16));
        out(screen, score_string);

        // Render Monsters
        {
            let monsters = monsters.lock().unwrap();
            for monster in monsters.iter() {
                curs(screen, monster.coord);
                out(screen, Fg(Green));
                out(screen, &monster.symbol);
                out(screen, Fg(Reset));
            }
        }

        // Game Title
        curs(screen, Coord::new(0, floor.rows as u16));
        out(screen, "Rusty Sword - Game of Infamy!");

        screen.flush().unwrap();
    }

    // Nice cleanup: Move cursor below the floor, so we can see how we finished
    {
        let floor = floor.lock().unwrap();
        curs(screen, Coord::new(0, (floor.rows + 2) as u16));
    }
    out(screen, termion::cursor::Show); // Show the cursor again
    screen.flush().unwrap();
}

<commit_msg>Make game title and score more colorful.<commit_after>use ::*;

fn out<S: ToString>(screen : &mut RawTerminal<Stdout>, output : S) {
    write!(*screen, "{}", output.to_string()).unwrap();
}

fn curs(screen : &mut RawTerminal<Stdout>, coord : Coord) {
    out(screen, termion::cursor::Goto(coord.col+1, coord.row+1));
}

pub fn render_loop(
    stop         : Arc<Mutex<bool>>,
    floor        : Arc<Mutex<Floor>>,
    player       : Arc<Mutex<Player>>,
    dirty_coords : Arc<Mutex<Vec<Coord>>>,
    monsters     : Arc<Mutex<Vec<Monster>>>,
) {
    let mut screen = &mut stdout().into_raw_mode().unwrap();
    out(screen, termion::cursor::Hide); // Hide the cursor
    out(screen, termion::clear::All);   // Clear the screen

    // Draw the entire floor
    curs(screen, Coord::new(0,0));
    {
        let floor = floor.lock().unwrap();
        for row in &floor.tiles {
            for tile in row {
                if let Some(ref wall) = tile.wall {
                    out(screen, wall);
                } else {
                    out(screen, " ");
                }
            }
            out(screen, "\r\n");
        }
    }

    // Render Loop
    loop {
        sleep(Duration::from_millis(10));
        {
            if *stop.lock().unwrap() {
                break;
            }
        }

        // Lock floor first...
        let floor = floor.lock().unwrap();

        // Redraw any dirty coordinates with floor tiles
        let mut dirty_coords = dirty_coords.lock().unwrap();
        for coord in dirty_coords.drain(..) {
            curs(screen, coord);
            out(screen, floor.get_symbol(&coord));
        }

        // Render Player
        let mut player = player.lock().unwrap();
        if player.dirty {
            player.dirty = false;
            // Player's sword
            curs(screen, player.sword_coord);
            out(screen, Fg(Red));
            out(screen, sword_symbol(player.facing));
            // Player himself
            curs(screen, player.coord);
            out(screen, Fg(Blue));
            out(screen, &player.symbol);
            out(screen, Fg(Reset));
        }
        // Player Score
        let score_string = format!("Score: {}", player.score);
        curs(screen, Coord::new((floor.cols - score_string.len()) as u16,
                                floor.rows as u16));
        out(screen, Fg(Blue));
        out(screen, score_string);
        out(screen, Fg(Reset));

        // Render Monsters
        {
            let monsters = monsters.lock().unwrap();
            for monster in monsters.iter() {
                curs(screen, monster.coord);
                out(screen, Fg(Green));
                out(screen, &monster.symbol);
                out(screen, Fg(Reset));
            }
        }

        // Game Title
        curs(screen, Coord::new(0, floor.rows as u16));
        out(screen, Fg(LightWhite));
        out(screen, "Rusty Sword - Game of Infamy!");
        out(screen, Fg(Reset));

        screen.flush().unwrap();
    }

    // Nice cleanup: Move cursor below the floor, so we can see how we finished
    {
        let floor = floor.lock().unwrap();
        curs(screen, Coord::new(0, (floor.rows + 2) as u16));
    }
    out(screen, termion::cursor::Show); // Show the cursor again
    screen.flush().unwrap();
}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::io;

use bytes::Bytes;
use futures::{Async, Future, Stream, Poll};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_core::reactor::Core;
use tokio_core::net::TcpListener;
use tokio_service::Service;
use tokio_proto::streaming::multiplex::{advanced, RequestId};
use tokio_proto::streaming::multiplex::advanced::MultiplexMessage;
use tokio_proto::streaming::Body;

use queues::{HandleJobStorage, SharedJobStorage};
use worker::{SharedWorkers, Wake};
use codec::{PacketCodec, PacketHeader};
use transport::GearmanFramed;
use service::{GearmanBody, GearmanService};

type Request = PacketHeader;
type RequestBody = Bytes;
type Response = PacketHeader;
type ResponseBody = Bytes;

pub struct GearmanServer;

const MAX_IN_FLIGHT_REQUESTS: usize = 32;

struct Dispatch<T>
    where T: AsyncRead + AsyncWrite + 'static,
{
    service: GearmanService,
    transport: GearmanFramed<T>,
    in_flight: Arc<Mutex<Vec<(RequestId, InFlight<<GearmanService as Service>::Future>)>>>,
}

enum InFlight<F: Future> {
    Active(F),
    Done(Result<F::Item, F::Error>),
}

impl<T> Dispatch<T>
    where T: AsyncRead + AsyncWrite + 'static
{
    pub fn new(service: GearmanService,
               transport: GearmanFramed<T>,
               in_flight: Arc<Mutex<Vec<(
                   RequestId, InFlight<<GearmanService as Service>::Future>)>>>) -> Dispatch<T> {
        Dispatch {
            service: service,
            transport: transport,
            in_flight: in_flight,
        }
    }
}

impl<T> advanced::Dispatch for Dispatch<T>
    where T: AsyncRead + AsyncWrite + 'static
{
    type Io = T;
    type In = Response;
    type BodyIn = ResponseBody;
    type Out = Request;
    type BodyOut = RequestBody;
    type Error = io::Error;
    type Stream = GearmanBody;
    type Transport = GearmanFramed<T>;

    fn transport(&mut self) -> &mut GearmanFramed<T> {
        &mut self.transport
    }

    fn dispatch(&mut self,
                message: MultiplexMessage<Self::Out,
                                          Body<Self::BodyOut, Self::Error>,
                                          Self::Error>)
                -> io::Result<()> {
        assert!(self.poll_ready().is_ready());

        let MultiplexMessage { id, message, solo } = message;

        //assert!(!solo);

        if !solo {
            if let Ok(request) = message {
                let response = self.service.call(request);
                let mut in_flight = self.in_flight.lock().unwrap();
                in_flight.push((id, InFlight::Active(response)));
            }
        }

        // TODO: Should the error be handled differently?
        Ok(())
    }

    fn poll(&mut self)
            -> Poll<Option<MultiplexMessage<Self::In, Self::Stream, Self::Error>>, io::Error> {
        let mut in_flight = self.in_flight.lock().unwrap();
        trace!("Dispatch::poll");

        let mut idx = None;

        for (i, &mut (request_id, ref mut slot)) in in_flight.iter_mut().enumerate() {
            trace!("   --> poll; request_id={:?}", request_id);
            if slot.poll() && idx.is_none() {
                idx = Some(i);
            }
        }

        if let Some(idx) = idx {
            let (request_id, message) = in_flight.remove(idx);
            let message = MultiplexMessage {
                id: request_id,
                message: message.unwrap_done(),
                solo: false,
            };

            Ok(Async::Ready(Some(message)))
        } else {
            Ok(Async::NotReady)
        }
    }

    fn poll_ready(&self) -> Async<()> {
        let in_flight = self.in_flight.lock().unwrap();
        if in_flight.len() < MAX_IN_FLIGHT_REQUESTS {
            Async::Ready(())
        } else {
            Async::NotReady
        }
    }

    fn cancel(&mut self, _request_id: RequestId) -> io::Result<()> {
        // todo: implement
        Ok(())
    }
}

impl<F: Future> InFlight<F> {
    fn poll(&mut self) -> bool {
        let res = match *self {
            InFlight::Active(ref mut f) => {
                trace!("   --> polling future");
                match f.poll() {
                    Ok(Async::Ready(e)) => Ok(e),
                    Err(e) => Err(e),
                    Ok(Async::NotReady) => return false,
                }
            }
            _ => return true,
        };

        *self = InFlight::Done(res);
        true
    }

    fn unwrap_done(self) -> Result<F::Item, F::Error> {
        match self {
            InFlight::Done(res) => res,
            _ => panic!("future is not ready"),
        }
    }
}

impl GearmanServer {
    pub fn run(addr: SocketAddr) {
        let mut core = Core::new().unwrap();
        let handle = core.handle();
        let listener = TcpListener::bind(&addr, &handle).unwrap();
        let curr_conn_id = AtomicUsize::new(0);
        let queues = SharedJobStorage::new_job_storage();
        let workers = SharedWorkers::new_workers();
        let job_count = Arc::new(AtomicUsize::new(0));
        let connections = Arc::new(Mutex::new(HashMap::new()));
        let remote = core.remote();
        let service_remote = remote.clone();
        let request_counter = Arc::new(AtomicUsize::new(1)); // 0 reserved for solo-ish
        let job_body_senders = Arc::new(Mutex::new(HashMap::new()));
        let server = listener.incoming().for_each(|(socket, _)| {
            let conn_id = curr_conn_id.fetch_add(1, Ordering::Relaxed);
            let transport = GearmanFramed(socket.framed(PacketCodec::new(request_counter.clone())));
            let service = GearmanService::new(conn_id,
                                              queues.clone(),
                                              workers.clone(),
                                              job_count.clone(),
                                              connections.clone(),
                                              job_body_senders.clone(),
                                              service_remote.clone());
            let in_flight = Arc::new(Mutex::new(Vec::with_capacity(MAX_IN_FLIGHT_REQUESTS)));
            let dispatch = Dispatch::new(service, transport, in_flight.clone());
            let pipeline = advanced::Multiplex::new(dispatch);
            handle.spawn(pipeline.map_err(|_| ()));
            Ok(())
        });
        core.run(server).unwrap();
    }
}
<commit_msg>Report errors during multiplex handling<commit_after>use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::io;

use bytes::Bytes;
use futures::{Async, Future, Stream, Poll};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_core::reactor::Core;
use tokio_core::net::TcpListener;
use tokio_service::Service;
use tokio_proto::streaming::multiplex::{advanced, RequestId};
use tokio_proto::streaming::multiplex::advanced::MultiplexMessage;
use tokio_proto::streaming::Body;

use queues::{HandleJobStorage, SharedJobStorage};
use worker::{SharedWorkers, Wake};
use codec::{PacketCodec, PacketHeader};
use transport::GearmanFramed;
use service::{GearmanBody, GearmanService};

type Request = PacketHeader;
type RequestBody = Bytes;
type Response = PacketHeader;
type ResponseBody = Bytes;

pub struct GearmanServer;

const MAX_IN_FLIGHT_REQUESTS: usize = 32;

struct Dispatch<T>
    where T: AsyncRead + AsyncWrite + 'static,
{
    service: GearmanService,
    transport: GearmanFramed<T>,
    in_flight: Arc<Mutex<Vec<(RequestId, InFlight<<GearmanService as Service>::Future>)>>>,
}

enum InFlight<F: Future> {
    Active(F),
    Done(Result<F::Item, F::Error>),
}

impl<T> Dispatch<T>
    where T: AsyncRead + AsyncWrite + 'static
{
    pub fn new(service: GearmanService,
               transport: GearmanFramed<T>,
               in_flight: Arc<Mutex<Vec<(
                   RequestId, InFlight<<GearmanService as Service>::Future>)>>>) -> Dispatch<T> {
        Dispatch {
            service: service,
            transport: transport,
            in_flight: in_flight,
        }
    }
}

impl<T> advanced::Dispatch for Dispatch<T>
    where T: AsyncRead + AsyncWrite + 'static
{
    type Io = T;
    type In = Response;
    type BodyIn = ResponseBody;
    type Out = Request;
    type BodyOut = RequestBody;
    type Error = io::Error;
    type Stream = GearmanBody;
    type Transport = GearmanFramed<T>;

    fn transport(&mut self) -> &mut GearmanFramed<T> {
        &mut self.transport
    }

    fn dispatch(&mut self,
                message: MultiplexMessage<Self::Out,
                                          Body<Self::BodyOut, Self::Error>,
                                          Self::Error>)
                -> io::Result<()> {
        assert!(self.poll_ready().is_ready());

        let MultiplexMessage { id, message, solo } = message;

        //assert!(!solo);

        if !solo {
            if let Ok(request) = message {
                let response = self.service.call(request);
                let mut in_flight = self.in_flight.lock().unwrap();
                in_flight.push((id, InFlight::Active(response)));
            }
        }

        // TODO: Should the error be handled differently?
        Ok(())
    }

    fn poll(&mut self)
            -> Poll<Option<MultiplexMessage<Self::In, Self::Stream, Self::Error>>, io::Error> {
        let mut in_flight = self.in_flight.lock().unwrap();
        trace!("Dispatch::poll");

        let mut idx = None;

        for (i, &mut (request_id, ref mut slot)) in in_flight.iter_mut().enumerate() {
            trace!("   --> poll; request_id={:?}", request_id);
            if slot.poll() && idx.is_none() {
                idx = Some(i);
            }
        }

        if let Some(idx) = idx {
            let (request_id, message) = in_flight.remove(idx);
            let message = MultiplexMessage {
                id: request_id,
                message: message.unwrap_done(),
                solo: false,
            };

            Ok(Async::Ready(Some(message)))
        } else {
            Ok(Async::NotReady)
        }
    }

    fn poll_ready(&self) -> Async<()> {
        let in_flight = self.in_flight.lock().unwrap();
        if in_flight.len() < MAX_IN_FLIGHT_REQUESTS {
            Async::Ready(())
        } else {
            Async::NotReady
        }
    }

    fn cancel(&mut self, _request_id: RequestId) -> io::Result<()> {
        // todo: implement
        Ok(())
    }
}

impl<F: Future> InFlight<F> {
    fn poll(&mut self) -> bool {
        let res = match *self {
            InFlight::Active(ref mut f) => {
                trace!("   --> polling future");
                match f.poll() {
                    Ok(Async::Ready(e)) => Ok(e),
                    Err(e) => Err(e),
                    Ok(Async::NotReady) => return false,
                }
            }
            _ => return true,
        };

        *self = InFlight::Done(res);
        true
    }

    fn unwrap_done(self) -> Result<F::Item, F::Error> {
        match self {
            InFlight::Done(res) => res,
            _ => panic!("future is not ready"),
        }
    }
}

impl GearmanServer {
    pub fn run(addr: SocketAddr) {
        let mut core = Core::new().unwrap();
        let handle = core.handle();
        let listener = TcpListener::bind(&addr, &handle).unwrap();
        let curr_conn_id = AtomicUsize::new(0);
        let queues = SharedJobStorage::new_job_storage();
        let workers = SharedWorkers::new_workers();
        let job_count = Arc::new(AtomicUsize::new(0));
        let connections = Arc::new(Mutex::new(HashMap::new()));
        let remote = core.remote();
        let service_remote = remote.clone();
        let request_counter = Arc::new(AtomicUsize::new(1)); // 0 reserved for solo-ish
        let job_body_senders = Arc::new(Mutex::new(HashMap::new()));
        let server = listener.incoming().for_each(|(socket, _)| {
            let conn_id = curr_conn_id.fetch_add(1, Ordering::Relaxed);
            let transport = GearmanFramed(socket.framed(PacketCodec::new(request_counter.clone())));
            let service = GearmanService::new(conn_id,
                                              queues.clone(),
                                              workers.clone(),
                                              job_count.clone(),
                                              connections.clone(),
                                              job_body_senders.clone(),
                                              service_remote.clone());
            let in_flight = Arc::new(Mutex::new(Vec::with_capacity(MAX_IN_FLIGHT_REQUESTS)));
            let dispatch = Dispatch::new(service, transport, in_flight.clone());
            let multiplex = advanced::Multiplex::new(dispatch);
            handle.spawn(multiplex.map_err(|e| {
                error!("Error while handling packets: {:?}", e);
            }));
            Ok(())
        });
        core.run(server).unwrap();
    }
}
<|endoftext|>


<commit_before>// Convert hex to base64
// The string:
//
// 49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d
// Should produce:
//
// SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t
// So go ahead and make that happen. You'll need to use this code for the rest of the exercises.
//
// Cryptopals Rule
// Always operate on raw bytes, never on encoded strings. Only use hex and base64 for pretty-printing.

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

#[macro_use]
extern crate log;

use std::ascii::AsciiExt;
use std::num::Int;
use std::str;

#[cfg(not(test))]
fn main() {
	println!("Set 1, Challenge 1");
	let input = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
	println!("input string: {:?}", input);
	let output = hex_to_base64("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d");
	println!("output string: {:?}", output);
}

fn hex_to_base64(hex_string: &str) -> String {
	if hex_string.len() % 2 != 0 {
		panic!("Hex string length should be even.");
	}

	let hex_lower = hex_string.to_ascii_lowercase();

	let bytes = hex_lower.as_bytes();

	let mut shift: i8 = 20;
	let mut string_group = 0;
	let mut output_vec = vec!();

	for &x in bytes.iter() {

		// if x is in the ascii range for numbers, subtract 48,
		// which is '0' in ascii. Otherwise, it should be a lowercase letter.
		// 'a' is 97, so subtract 87.
		let byte = match x < 58 {
			true => x - 48,
			false => x - 87
		};

		let test = (byte as usize) << shift;
		debug!("byte: {:?}, test: {:?}, shift: {:?}", byte, test, shift);
		string_group += test;

		shift -= 4;

		if shift < 0 {
			output_vec.append(&mut convert_string_group(string_group, 3));
			shift = 20;
			string_group = 0;
		}

	}

	if string_group != 0 {
		// assuming an even number of hex chars, shift will either be 12 or 4.
		// if 12, we have 1 significant byte, and if 4 we have 2.
		let significant_bytes: usize = (2 - (shift / 8)) as usize;
		output_vec.append(&mut convert_string_group(string_group, significant_bytes));
	}

	// turn the byte vector into a string
	match str::from_utf8(output_vec.as_slice()) {
	    Ok(v) => {
	        debug!("output string: {:?}", v);
	        return v.to_string();
	    }
	    Err(e) => {
	        panic!("error parsing string: {:?}", e);
    	}
	}
}

fn convert_string_group(group: usize, significant_bytes: usize) -> Vec<u8> {
	let mut converted_vec = vec!();
	let octets = vec!(
		((group & (63 * 64.pow(3))) >> 18) as u8,
		((group & (63 * 64.pow(2))) >> 12) as u8,
		((group & (63 * 64)) >> 6) as u8,
		(group & 63) as u8,
	);
	debug!("group: {:?}", group);
	debug!("octets: {:?}", octets);
	for &octet in octets.iter() {
		converted_vec.push(
			match octet {
				0...25 => octet + 65, // uppercase
				26...51 => octet + 71, // lowercase
				52...61 => octet - 4, // numbers
				62 => 43, // +
				63 => 47, // /
				_ => panic!("Not a valid octet")
			}
		);
	}

	// if we have less than 3 significant bytes, truncate insignificant chars
	// and replace them with '=' characters
	if significant_bytes < 3 {
		converted_vec.truncate(significant_bytes + 1);
		converted_vec.resize(4, 61);
	}

	converted_vec
}

#[cfg(test)]
mod set1challenge1 {

	#[test]
	fn challenge() {
		let output = super::hex_to_base64("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d");
		assert_eq!(output, "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t");
	}

	#[test]
	fn ff() {
		let output = super::hex_to_base64("ff");
		assert_eq!(output, "/w==");
	}

	#[test]
	fn ffff() {
		let output = super::hex_to_base64("ffff");
		assert_eq!(output, "//8=");
	}

	#[test]
	fn uppercase() {
		let output = super::hex_to_base64("4D616E");
		assert_eq!(output, "TWFu");
	}
}
<commit_msg>Don't duplicate the input string in the first challenge<commit_after>// Convert hex to base64
// The string:
//
// 49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d
// Should produce:
//
// SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t
// So go ahead and make that happen. You'll need to use this code for the rest of the exercises.
//
// Cryptopals Rule
// Always operate on raw bytes, never on encoded strings. Only use hex and base64 for pretty-printing.

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

#[macro_use]
extern crate log;

use std::ascii::AsciiExt;
use std::num::Int;
use std::str;

#[cfg(not(test))]
fn main() {
	println!("Set 1, Challenge 1");
	let input = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
	println!("input string: {:?}", input);
	let output = hex_to_base64(input);
	println!("output string: {:?}", output);
}

fn hex_to_base64(hex_string: &str) -> String {
	if hex_string.len() % 2 != 0 {
		panic!("Hex string length should be even.");
	}

	let hex_lower = hex_string.to_ascii_lowercase();

	let bytes = hex_lower.as_bytes();

	let mut shift: i8 = 20;
	let mut string_group = 0;
	let mut output_vec = vec!();

	for &x in bytes.iter() {

		// if x is in the ascii range for numbers, subtract 48,
		// which is '0' in ascii. Otherwise, it should be a lowercase letter.
		// 'a' is 97, so subtract 87.
		let byte = match x < 58 {
			true => x - 48,
			false => x - 87
		};

		let test = (byte as usize) << shift;
		debug!("byte: {:?}, test: {:?}, shift: {:?}", byte, test, shift);
		string_group += test;

		shift -= 4;

		if shift < 0 {
			output_vec.append(&mut convert_string_group(string_group, 3));
			shift = 20;
			string_group = 0;
		}

	}

	if string_group != 0 {
		// assuming an even number of hex chars, shift will either be 12 or 4.
		// if 12, we have 1 significant byte, and if 4 we have 2.
		let significant_bytes: usize = (2 - (shift / 8)) as usize;
		output_vec.append(&mut convert_string_group(string_group, significant_bytes));
	}

	// turn the byte vector into a string
	match str::from_utf8(output_vec.as_slice()) {
	    Ok(v) => {
	        debug!("output string: {:?}", v);
	        return v.to_string();
	    }
	    Err(e) => {
	        panic!("error parsing string: {:?}", e);
    	}
	}
}

fn convert_string_group(group: usize, significant_bytes: usize) -> Vec<u8> {
	let mut converted_vec = vec!();
	let octets = vec!(
		((group & (63 * 64.pow(3))) >> 18) as u8,
		((group & (63 * 64.pow(2))) >> 12) as u8,
		((group & (63 * 64)) >> 6) as u8,
		(group & 63) as u8,
	);
	debug!("group: {:?}", group);
	debug!("octets: {:?}", octets);
	for &octet in octets.iter() {
		converted_vec.push(
			match octet {
				0...25 => octet + 65, // uppercase
				26...51 => octet + 71, // lowercase
				52...61 => octet - 4, // numbers
				62 => 43, // +
				63 => 47, // /
				_ => panic!("Not a valid octet")
			}
		);
	}

	// if we have less than 3 significant bytes, truncate insignificant chars
	// and replace them with '=' characters
	if significant_bytes < 3 {
		converted_vec.truncate(significant_bytes + 1);
		converted_vec.resize(4, 61);
	}

	converted_vec
}

#[cfg(test)]
mod set1challenge1 {

	#[test]
	fn challenge() {
		let output = super::hex_to_base64("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d");
		assert_eq!(output, "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t");
	}

	#[test]
	fn ff() {
		let output = super::hex_to_base64("ff");
		assert_eq!(output, "/w==");
	}

	#[test]
	fn ffff() {
		let output = super::hex_to_base64("ffff");
		assert_eq!(output, "//8=");
	}

	#[test]
	fn uppercase() {
		let output = super::hex_to_base64("4D616E");
		assert_eq!(output, "TWFu");
	}
}
<|endoftext|>


<commit_before>use std::hash::Hash;

use timely::Data;
use timely::progress::Timestamp;
use timely::dataflow::scopes::Child;
use timely::dataflow::{Scope, Stream};
use timely::dataflow::operators::*;

use ::Delta;

/// A mutable collection of values of type `D`
pub struct Collection<G: Scope, D: Data> {
    pub inner: Stream<G, (D, Delta)>
}

impl<G: Scope, D: Data> Collection<G, D> {
    pub fn new(inner: Stream<G, (D, Delta)>) -> Collection<G, D> {
        Collection {
            inner: inner
        }
    }

    pub fn map<D2: Data, L: Fn(D) -> D2 + 'static>(&self, logic: L) -> Collection<G, D2> {
        Collection {
            inner: self.inner.map(move |(data, delta)| (logic(data), delta))
        }
    }

    pub fn map_in_place<L: Fn(&mut D) + 'static>(&self, logic: L) -> Collection<G, D> {
        Collection {
            inner: self.inner.map_in_place(move |&mut (ref mut data, _)| logic(data))
        }
    }

    pub fn filter<L: Fn(&D) -> bool + 'static>(&self, logic: L) -> Collection<G, D> {
        Collection {
            inner: self.inner.filter(move |&(ref data, _)| logic(data))
        }
    }

    pub fn concat(&self, other: &Collection<G, D>) -> Collection<G, D> {
        Collection {
            inner: self.inner.concat(&other.inner)
        }
    }

    pub fn enter<T: Timestamp>(&self, child: &Child<G, T>) -> Collection<Child<G, T>, D> {
        Collection {
            inner: self.inner.enter(child)
        }
    }

    pub fn enter_at<T: Timestamp, F: Fn(&(D, Delta)) -> T + 'static>(&self, child: &Child<G, T>, initial: F) -> Collection<Child<G, T>, D> where G::Timestamp: Hash, T: Hash {
        Collection {
            inner: self.inner.enter_at(child, initial)
        }
    }

    pub fn inspect<F: FnMut(&(D, Delta))+'static>(&self, func: F) -> Collection<G, D> {
        Collection {
            inner: self.inner.inspect(func)
        }
    }

    pub fn inspect_batch<F: FnMut(&G::Timestamp, &[(D, Delta)])+'static>(&self, func: F) -> Collection<G, D> {
        Collection {
            inner: self.inner.inspect_batch(func)
        }
    }

    pub fn probe(&self) -> (probe::Handle<G::Timestamp>, Collection<G, D>) {
        let (handle, stream) = self.inner.probe();
        (handle, Collection {
            inner: stream
        })
    }

    pub fn scope(&self) -> G {
        self.inner.scope()
    }
}

impl<G: Scope, T: Timestamp, D: Data> Collection<Child<G, T>, D> {
    pub fn leave(&self) -> Collection<G, D> {
        Collection {
            inner: self.inner.leave()
        }
    }
}
<commit_msg>added Clone for Collection<commit_after>use std::hash::Hash;

use timely::Data;
use timely::progress::Timestamp;
use timely::dataflow::scopes::Child;
use timely::dataflow::{Scope, Stream};
use timely::dataflow::operators::*;

use ::Delta;

/// A mutable collection of values of type `D`
#[derive(Clone)]
pub struct Collection<G: Scope, D: Data> {
    pub inner: Stream<G, (D, Delta)>
}

impl<G: Scope, D: Data> Collection<G, D> {
    pub fn new(inner: Stream<G, (D, Delta)>) -> Collection<G, D> {
        Collection {
            inner: inner
        }
    }

    pub fn map<D2: Data, L: Fn(D) -> D2 + 'static>(&self, logic: L) -> Collection<G, D2> {
        Collection {
            inner: self.inner.map(move |(data, delta)| (logic(data), delta))
        }
    }

    pub fn map_in_place<L: Fn(&mut D) + 'static>(&self, logic: L) -> Collection<G, D> {
        Collection {
            inner: self.inner.map_in_place(move |&mut (ref mut data, _)| logic(data))
        }
    }

    pub fn filter<L: Fn(&D) -> bool + 'static>(&self, logic: L) -> Collection<G, D> {
        Collection {
            inner: self.inner.filter(move |&(ref data, _)| logic(data))
        }
    }

    pub fn concat(&self, other: &Collection<G, D>) -> Collection<G, D> {
        Collection {
            inner: self.inner.concat(&other.inner)
        }
    }

    pub fn enter<T: Timestamp>(&self, child: &Child<G, T>) -> Collection<Child<G, T>, D> {
        Collection {
            inner: self.inner.enter(child)
        }
    }

    pub fn enter_at<T: Timestamp, F: Fn(&(D, Delta)) -> T + 'static>(&self, child: &Child<G, T>, initial: F) -> Collection<Child<G, T>, D> where G::Timestamp: Hash, T: Hash {
        Collection {
            inner: self.inner.enter_at(child, initial)
        }
    }

    pub fn inspect<F: FnMut(&(D, Delta))+'static>(&self, func: F) -> Collection<G, D> {
        Collection {
            inner: self.inner.inspect(func)
        }
    }

    pub fn inspect_batch<F: FnMut(&G::Timestamp, &[(D, Delta)])+'static>(&self, func: F) -> Collection<G, D> {
        Collection {
            inner: self.inner.inspect_batch(func)
        }
    }

    pub fn probe(&self) -> (probe::Handle<G::Timestamp>, Collection<G, D>) {
        let (handle, stream) = self.inner.probe();
        (handle, Collection {
            inner: stream
        })
    }

    pub fn scope(&self) -> G {
        self.inner.scope()
    }
}

impl<G: Scope, T: Timestamp, D: Data> Collection<Child<G, T>, D> {
    pub fn leave(&self) -> Collection<G, D> {
        Collection {
            inner: self.inner.leave()
        }
    }
}
<|endoftext|>


<commit_before>//! Licensed under the Apache License, Version 2.0
//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license
//! http://opensource.org/licenses/MIT, at your
//! option. This file may not be copied, modified, or distributed
//! except according to those terms.

use std::fmt;
use std::kinds;
use std::mem;
use std::num;

/// Similar to the slice iterator, but with a certain number of steps
/// (stride) skipped per iteration.
///
/// Does not support zero-sized `A`.
///
/// Iterator element type is `&'a A`
pub struct Stride<'a, A> {
    /// base pointer -- does not change during iteration
    begin: *const A,
    /// current offset from begin
    offset: int,
    /// offset where we end (exclusive end).
    end: int,
    stride: int,
    life: kinds::marker::ContravariantLifetime<'a>,
}

/// Stride with mutable elements
///
/// Iterator element type is `&'a mut A`
pub struct StrideMut<'a, A> {
    begin: *mut A,
    offset: int,
    end: int,
    stride: int,
    life: kinds::marker::ContravariantLifetime<'a>,
    nocopy: kinds::marker::NoCopy
}

impl<'a, A> Stride<'a, A>
{
    /// Create Stride iterator from a raw pointer.
    pub unsafe fn from_ptr_len(begin: *const A, nelem: uint, stride: int) -> Stride<'a, A>
    {
        Stride {
            begin: begin,
            offset: 0,
            end: stride * nelem as int,
            stride: stride,
            life: kinds::marker::ContravariantLifetime,
        }
    }
}

impl<'a, A> StrideMut<'a, A>
{
    /// Create Stride iterator from a raw pointer.
    pub unsafe fn from_ptr_len(begin: *mut A, nelem: uint, stride: int) -> StrideMut<'a, A>
    {
        StrideMut {
            begin: begin,
            offset: 0,
            end: stride * nelem as int,
            stride: stride,
            life: kinds::marker::ContravariantLifetime,
            nocopy: kinds::marker::NoCopy,
        }
    }
}

macro_rules! stride_impl {
    (struct $name:ident -> $slice:ty, $getptr:ident, $ptr:ty, $elem:ty) => {
        impl<'a, A> $name<'a, A>
        {
            /// Create Stride iterator from a slice and the element step count.
            ///
            /// If `step` is negative, start from the back.
            ///
            /// ## Example
            ///
            /// ```
            /// use itertools::Stride;
            ///
            /// let xs = [0i, 1, 2, 3, 4, 5];
            ///
            /// let mut front = Stride::from_slice(xs.as_slice(), 2);
            /// assert_eq!(front[0], 0);
            /// assert_eq!(front[1], 2);
            ///
            /// let mut back = Stride::from_slice(xs.as_slice(), -2);
            /// assert_eq!(back[0], 5);
            /// assert_eq!(back[1], 3);
            /// ```
            #[inline]
            pub fn from_slice(xs: $slice, step: int) -> $name<'a, A>
            {
                assert!(mem::size_of::<A>() != 0);
                let ustep = if step < 0 { -step } else { step } as uint;
                let nelem = if ustep <= 1 {
                    xs.len()
                } else {
                    let (d, r) = num::div_rem(xs.len(), ustep);
                    d + if r > 0 { 1 } else { 0 }
                };
                let mut begin = xs. $getptr ();
                unsafe {
                    if step > 0 {
                        $name::from_ptr_len(begin, nelem, step)
                    } else {
                        if nelem != 0 {
                            begin = begin.offset(xs.len() as int - 1)
                        }
                        $name::from_ptr_len(begin, nelem, step)
                    }
                }
            }

            /// Create Stride iterator from an existing Stride iterator
            #[inline]
            pub fn from_stride(mut it: $name<'a, A>, mut step: int) -> $name<'a, A>
            {
                assert!(step != 0);
                if step < 0 {
                    it.swap_ends();
                    step = -step;
                }
                let len = (it.end - it.offset) / it.stride;
                let newstride = it.stride * step;
                let (d, r) = num::div_rem(len as uint, step as uint);
                let len = d as uint + if r > 0 { 1 } else { 0 };
                unsafe {
                    $name::from_ptr_len(it.begin, len, newstride)
                }
            }

            /// Swap the begin and end and reverse the stride,
            /// in effect reversing the iterator.
            #[inline]
            pub fn swap_ends(&mut self) {
                let len = (self.end - self.offset) / self.stride;
                if len > 0 {
                    unsafe {
                        let endptr = self.begin.offset((len - 1) * self.stride);
                        *self = $name::from_ptr_len(endptr, len as uint, -self.stride);
                    }
                }
            }
        }

        impl<'a, A> Iterator<$elem> for $name<'a, A>
        {
            #[inline]
            fn next(&mut self) -> Option<$elem>
            {
                if self.offset == self.end {
                    None
                } else {
                    unsafe {
                        let elt: $elem =
                            mem::transmute(self.begin.offset(self.offset));
                        self.offset += self.stride;
                        Some(elt)
                    }
                }
            }

            #[inline]
            fn size_hint(&self) -> (uint, Option<uint>) {
                let len = ((self.end - self.offset) / self.stride) as uint;
                (len, Some(len))
            }
        }

        impl<'a, A> DoubleEndedIterator<$elem> for $name<'a, A>
        {
            #[inline]
            fn next_back(&mut self) -> Option<$elem>
            {
                if self.offset == self.end {
                    None
                } else {
                    unsafe {
                        self.end -= self.stride;
                        let elt = mem::transmute(self.begin.offset(self.end));
                        Some(elt)
                    }
                }
            }
        }

        impl<'a, A> ExactSizeIterator<$elem> for $name<'a, A> { }

        impl<'a, A> Index<uint, A> for $name<'a, A>
        {
            fn index<'b>(&'b self, i: &uint) -> &'b A
            {
                assert!(*i < self.size_hint().val0());
                unsafe {
                    let ptr = self.begin.offset(self.offset + self.stride * (*i as int));
                    mem::transmute(ptr)
                }
            }
        }

        impl<'a, A: fmt::Show> fmt::Show for $name<'a, A>
        {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
            {
                try!(write!(f, "["));
                for i in range(0, self.len()) {
                    if i != 0 {
                        try!(write!(f, ", "));
                    }
                    try!(write!(f, "{}", (*self)[i]));
                }
                write!(f, "]")
            }
        }
    }
}

stride_impl!{struct Stride -> &'a [A], as_ptr, *const A, &'a A}
stride_impl!{struct StrideMut -> &'a mut [A], as_mut_ptr, *mut A, &'a mut A}

impl<'a, A> Clone for Stride<'a, A>
{
    fn clone(&self) -> Stride<'a, A>
    {
        *self
    }
}

impl<'a, A> IndexMut<uint, A> for StrideMut<'a, A>
{
    fn index_mut<'b>(&'b mut self, i: &uint) -> &'b mut A
    {
        assert!(*i < self.size_hint().val0());
        unsafe {
            let ptr = self.begin.offset(self.offset + self.stride * (*i as int));
            mem::transmute(ptr)
        }
    }
}
<commit_msg>stride: Add method .len() to Stride and StrideMut<commit_after>//! Licensed under the Apache License, Version 2.0
//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license
//! http://opensource.org/licenses/MIT, at your
//! option. This file may not be copied, modified, or distributed
//! except according to those terms.

use std::fmt;
use std::kinds;
use std::mem;
use std::num;

/// Similar to the slice iterator, but with a certain number of steps
/// (stride) skipped per iteration.
///
/// Does not support zero-sized `A`.
///
/// Iterator element type is `&'a A`
pub struct Stride<'a, A> {
    /// base pointer -- does not change during iteration
    begin: *const A,
    /// current offset from begin
    offset: int,
    /// offset where we end (exclusive end).
    end: int,
    stride: int,
    life: kinds::marker::ContravariantLifetime<'a>,
}

/// Stride with mutable elements
///
/// Iterator element type is `&'a mut A`
pub struct StrideMut<'a, A> {
    begin: *mut A,
    offset: int,
    end: int,
    stride: int,
    life: kinds::marker::ContravariantLifetime<'a>,
    nocopy: kinds::marker::NoCopy
}

impl<'a, A> Stride<'a, A>
{
    /// Create Stride iterator from a raw pointer.
    pub unsafe fn from_ptr_len(begin: *const A, nelem: uint, stride: int) -> Stride<'a, A>
    {
        Stride {
            begin: begin,
            offset: 0,
            end: stride * nelem as int,
            stride: stride,
            life: kinds::marker::ContravariantLifetime,
        }
    }
}

impl<'a, A> StrideMut<'a, A>
{
    /// Create Stride iterator from a raw pointer.
    pub unsafe fn from_ptr_len(begin: *mut A, nelem: uint, stride: int) -> StrideMut<'a, A>
    {
        StrideMut {
            begin: begin,
            offset: 0,
            end: stride * nelem as int,
            stride: stride,
            life: kinds::marker::ContravariantLifetime,
            nocopy: kinds::marker::NoCopy,
        }
    }
}

macro_rules! stride_impl {
    (struct $name:ident -> $slice:ty, $getptr:ident, $ptr:ty, $elem:ty) => {
        impl<'a, A> $name<'a, A>
        {
            /// Create Stride iterator from a slice and the element step count.
            ///
            /// If `step` is negative, start from the back.
            ///
            /// ## Example
            ///
            /// ```
            /// use itertools::Stride;
            ///
            /// let xs = [0i, 1, 2, 3, 4, 5];
            ///
            /// let mut front = Stride::from_slice(xs.as_slice(), 2);
            /// assert_eq!(front[0], 0);
            /// assert_eq!(front[1], 2);
            ///
            /// let mut back = Stride::from_slice(xs.as_slice(), -2);
            /// assert_eq!(back[0], 5);
            /// assert_eq!(back[1], 3);
            /// ```
            #[inline]
            pub fn from_slice(xs: $slice, step: int) -> $name<'a, A>
            {
                assert!(mem::size_of::<A>() != 0);
                let ustep = if step < 0 { -step } else { step } as uint;
                let nelem = if ustep <= 1 {
                    xs.len()
                } else {
                    let (d, r) = num::div_rem(xs.len(), ustep);
                    d + if r > 0 { 1 } else { 0 }
                };
                let mut begin = xs. $getptr ();
                unsafe {
                    if step > 0 {
                        $name::from_ptr_len(begin, nelem, step)
                    } else {
                        if nelem != 0 {
                            begin = begin.offset(xs.len() as int - 1)
                        }
                        $name::from_ptr_len(begin, nelem, step)
                    }
                }
            }

            /// Create Stride iterator from an existing Stride iterator
            #[inline]
            pub fn from_stride(mut it: $name<'a, A>, mut step: int) -> $name<'a, A>
            {
                assert!(step != 0);
                if step < 0 {
                    it.swap_ends();
                    step = -step;
                }
                let len = (it.end - it.offset) / it.stride;
                let newstride = it.stride * step;
                let (d, r) = num::div_rem(len as uint, step as uint);
                let len = d as uint + if r > 0 { 1 } else { 0 };
                unsafe {
                    $name::from_ptr_len(it.begin, len, newstride)
                }
            }

            /// Swap the begin and end and reverse the stride,
            /// in effect reversing the iterator.
            #[inline]
            pub fn swap_ends(&mut self) {
                let len = (self.end - self.offset) / self.stride;
                if len > 0 {
                    unsafe {
                        let endptr = self.begin.offset((len - 1) * self.stride);
                        *self = $name::from_ptr_len(endptr, len as uint, -self.stride);
                    }
                }
            }

            /// Return the number of elements in the iterator.
            #[inline]
            pub fn len(&self) -> uint {
                ((self.end - self.offset) / self.stride) as uint
            }
        }

        impl<'a, A> Iterator<$elem> for $name<'a, A>
        {
            #[inline]
            fn next(&mut self) -> Option<$elem>
            {
                if self.offset == self.end {
                    None
                } else {
                    unsafe {
                        let elt: $elem =
                            mem::transmute(self.begin.offset(self.offset));
                        self.offset += self.stride;
                        Some(elt)
                    }
                }
            }

            #[inline]
            fn size_hint(&self) -> (uint, Option<uint>) {
                let len = self.len();
                (len, Some(len))
            }
        }

        impl<'a, A> DoubleEndedIterator<$elem> for $name<'a, A>
        {
            #[inline]
            fn next_back(&mut self) -> Option<$elem>
            {
                if self.offset == self.end {
                    None
                } else {
                    unsafe {
                        self.end -= self.stride;
                        let elt = mem::transmute(self.begin.offset(self.end));
                        Some(elt)
                    }
                }
            }
        }

        impl<'a, A> ExactSizeIterator<$elem> for $name<'a, A> { }

        impl<'a, A> Index<uint, A> for $name<'a, A>
        {
            fn index<'b>(&'b self, i: &uint) -> &'b A
            {
                assert!(*i < self.len());
                unsafe {
                    let ptr = self.begin.offset(self.offset + self.stride * (*i as int));
                    mem::transmute(ptr)
                }
            }
        }

        impl<'a, A: fmt::Show> fmt::Show for $name<'a, A>
        {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
            {
                try!(write!(f, "["));
                for i in range(0, self.len()) {
                    if i != 0 {
                        try!(write!(f, ", "));
                    }
                    try!(write!(f, "{}", (*self)[i]));
                }
                write!(f, "]")
            }
        }
    }
}

stride_impl!{struct Stride -> &'a [A], as_ptr, *const A, &'a A}
stride_impl!{struct StrideMut -> &'a mut [A], as_mut_ptr, *mut A, &'a mut A}

impl<'a, A> Clone for Stride<'a, A>
{
    fn clone(&self) -> Stride<'a, A>
    {
        *self
    }
}

impl<'a, A> IndexMut<uint, A> for StrideMut<'a, A>
{
    fn index_mut<'b>(&'b mut self, i: &uint) -> &'b mut A
    {
        assert!(*i < self.len());
        unsafe {
            let ptr = self.begin.offset(self.offset + self.stride * (*i as int));
            mem::transmute(ptr)
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::{BufRead, BufReader};
use std::path::{PathBuf, Path};
use std::fs::File;
use std::collections::HashSet;
use object::Object;
use object::File as OFile;
use memmap::{Mmap, Protection};
use gimli::*;
use regex::Regex;

#[derive(Debug, Clone)]
pub struct Branch {

}

#[derive(Debug, Clone)]
pub struct TracerData {
    pub path: PathBuf,
    pub line: u64,
    pub address: u64,
    pub branch_data: Option<Branch>,
    pub hits: u64,
}

fn line_is_traceable(file: &PathBuf, line: u64) -> bool {
    let mut result = false;
    // Module imports are flagged as debuggable. But are always ran so meaningless!
    let reg: Regex = Regex::new(r"(:?^|\s)mod\s+\w+;").unwrap();
    if let Ok(f) = File::open(file) {
        let reader = BufReader::new(&f);
        if let Some(Ok(l)) = reader.lines().nth((line - 1) as usize) {
            result = !reg.is_match(l.as_ref());
        }
    }
    result
}

fn get_line_addresses<Endian: Endianity>(project: &Path, obj: &OFile) -> Vec<TracerData>  {
    let mut result: Vec<TracerData> = Vec::new();

    let debug_line = obj.get_section(".debug_line").unwrap_or(&[]);
    let debug_line = DebugLine::<Endian>::new(debug_line);
    // TODO get address size and DebugLineOffset properly!
    if let Ok(prog) = debug_line.program(DebugLineOffset(0), 8, None, None) {
        if let Ok((cprog, seq)) = prog.sequences() {
            for s in &seq {
                let mut sm = cprog.resume_from(s);
                while let Ok(Some((ref header, &ln_row))) = sm.next_row() {
                    if let Some(file) = ln_row.file(header) {
                        let mut path = PathBuf::new();

                        if let Some(dir) = file.directory(header) {
                            if let Ok(temp) = String::from_utf8(dir.to_bytes().to_vec()) {
                                path.push(temp);
                            }
                        }
                        // Source is part of project so we cover it.
                        if path.starts_with(project) {
                            if let Some(file) = ln_row.file(header) {
                                // If we can't map to line, we can't trace it.
                                let line = ln_row.line().unwrap_or(0);
                                if line == 0 {
                                    continue;
                                }
                                let file = file.path_name();
                                // We now need to filter out lines which are meaningless to trace.

                                if let Ok(file) = String::from_utf8(file.to_bytes().to_vec()) {
                                    path.push(file);
                                    if !line_is_traceable(&path, line) {
                                        continue;
                                    }
                                    let data = TracerData {
                                        path: path,
                                        line: line,
                                        address: ln_row.address(),
                                        branch_data: None,
                                        hits: 0u64
                                    };
                                    result.push(data);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    // Due to rust being a higher level language multiple instructions may map
    // to the same line. This prunes these to just the first instruction address
    let mut check: HashSet<(&Path, u64)> = HashSet::new();
    let result = result.iter()
                       .filter(|x| check.insert((x.path.as_path(), x.line)))
                       .map(|x| x.clone())
                       .collect::<Vec<TracerData>>();
    result
}

pub fn generate_tracer_data(manifest: &Path, test: &Path) -> io::Result<Vec<TracerData>> {
    let file = File::open(test)?;
    let file = Mmap::open(&file, Protection::Read)?;
    if let Ok(obj) = OFile::parse(unsafe {file.as_slice() }) {

        let data = if obj.is_little_endian() {
            get_line_addresses::<LittleEndian>(manifest, &obj)
        } else {
            get_line_addresses::<BigEndian>(manifest, &obj)
        };
        Ok(data)
    } else {
        Err(io::Error::new(io::ErrorKind::InvalidData, "Unable to parse binary."))
    }
}
<commit_msg>Refactored tracer.rs.<commit_after>use std::io;
use std::io::{BufRead, BufReader};
use std::path::{PathBuf, Path};
use std::fs::File;
use std::collections::HashSet;
use object::Object;
use object::File as OFile;
use memmap::{Mmap, Protection};
use gimli::*;
use regex::Regex;

/// So far from my tests the test executable is the first compilation unit in
/// the DWARF debug information with the future ones being libraries and rustc.
const TEST_CU_OFFSET: usize = 0;

#[derive(Debug, Clone)]
pub struct Branch {

}

#[derive(Debug, Clone)]
pub struct TracerData {
    pub path: PathBuf,
    pub line: u64,
    pub address: u64,
    pub branch_data: Option<Branch>,
    pub hits: u64,
}

fn line_is_traceable(file: &PathBuf, line: u64) -> bool {
    let mut result = false;
    if line > 0 {
        // Module imports are flagged as debuggable. But are always ran so meaningless!
        let reg: Regex = Regex::new(r"(:?^|\s)mod\s+\w+;").unwrap();
        if let Ok(f) = File::open(file) {
            let reader = BufReader::new(&f);
            if let Some(Ok(l)) = reader.lines().nth((line - 1) as usize) {
                result = !reg.is_match(l.as_ref());
            }
        }
    }
    result
}

fn get_address_size<Endian: Endianity>(obj: &OFile) -> Result<u8> {
    let debug_info = obj.get_section(".debug_info").unwrap_or(&[]);
    let debug_info = DebugInfo::<Endian>::new(debug_info);

    let cu = debug_info.header_from_offset(DebugInfoOffset(TEST_CU_OFFSET))?;
    Ok(cu.address_size())
}

fn get_line_addresses<Endian: Endianity>(project: &Path, obj: &OFile) -> Result<Vec<TracerData>>  {
    let mut result: Vec<TracerData> = Vec::new();

    let addr_size = get_address_size::<Endian>(obj)?;

    let debug_line = obj.get_section(".debug_line").unwrap_or(&[]);
    let debug_line = DebugLine::<Endian>::new(debug_line);

    let prog = debug_line.program(DebugLineOffset(TEST_CU_OFFSET), addr_size, None, None)?;
    let (cprog, seq) = prog.sequences()?;
    for s in &seq {
        let mut sm = cprog.resume_from(s);
        while let Ok(Some((ref header, &ln_row))) = sm.next_row() {
            if let Some(file) = ln_row.file(header) {
                let mut path = PathBuf::new();

                if let Some(dir) = file.directory(header) {
                    if let Ok(temp) = String::from_utf8(dir.to_bytes().to_vec()) {
                        path.push(temp);
                    }
                }
                // Source is part of project so we cover it.
                if path.starts_with(project) {
                    if let Some(file) = ln_row.file(header) {
                        // If we can't map to line, we can't trace it.
                        let line = ln_row.line().unwrap_or(0);
                        let file = file.path_name();
                        // We now need to filter out lines which are meaningless to trace.

                        if let Ok(file) = String::from_utf8(file.to_bytes().to_vec()) {
                            path.push(file);
                            if !line_is_traceable(&path, line) {
                                continue;
                            }
                            let data = TracerData {
                                path: path,
                                line: line,
                                address: ln_row.address(),
                                branch_data: None,
                                hits: 0u64
                            };
                            result.push(data);
                        }
                    }
                }
            }
        }
    }

    // Due to rust being a higher level language multiple instructions may map
    // to the same line. This prunes these to just the first instruction address
    let mut check: HashSet<(&Path, u64)> = HashSet::new();
    let result = result.iter()
                       .filter(|x| check.insert((x.path.as_path(), x.line)))
                       .map(|x| x.clone())
                       .collect::<Vec<TracerData>>();
    Ok(result)
}

pub fn generate_tracer_data(manifest: &Path, test: &Path) -> io::Result<Vec<TracerData>> {
    let file = File::open(test)?;
    let file = Mmap::open(&file, Protection::Read)?;
    if let Ok(obj) = OFile::parse(unsafe {file.as_slice() }) {

        let data = if obj.is_little_endian() {
            get_line_addresses::<LittleEndian>(manifest, &obj)
        } else {
            get_line_addresses::<BigEndian>(manifest, &obj)
        };
        data.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Error while parsing"))
    } else {
        Err(io::Error::new(io::ErrorKind::InvalidData, "Unable to parse binary."))
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{Result, Write};
use std::path::Path;

use super::Object::*;
use super::{Dictionary, Document, Object, Stream, StringFormat};
use crate::xref::*;

impl Document {
	/// Save PDF document to specified file path.
	#[inline]
	pub fn save<P: AsRef<Path>>(&mut self, path: P) -> Result<File> {
		let mut file = File::create(path)?;
		self.save_internal(&mut file)?;
		Ok(file)
	}

	/// Save PDF to arbitrary target
	#[inline]
	pub fn save_to<W: Write>(&mut self, target: &mut W) -> Result<()> {
		self.save_internal(target)
	}

	fn save_internal<W: Write>(&mut self, target: &mut W) -> Result<()> {
		let mut target = CountingWrite { inner: target, bytes_written: 0 };
		let mut xref = Xref::new(self.max_id + 1);
		write!(target, "%PDF-{}\n", self.version)?;

		for (&(id, generation), object) in &self.objects {
			if object.type_name().map(|name| ["ObjStm", "XRef", "Linearized"].contains(&name)) != Some(true) {
				Writer::write_indirect_object(&mut target, id, generation, object, &mut xref)?;
			}
		}

		let xref_start = target.bytes_written;
		Writer::write_xref(&mut target, &xref)?;
		self.write_trailer(&mut target)?;
		write!(target, "\nstartxref\n{}\n%%EOF", xref_start)?;

		Ok(())
	}

	fn write_trailer(&mut self, file: &mut dyn Write) -> Result<()> {
		self.trailer.set("Size", i64::from(self.max_id + 1));
		file.write_all(b"trailer\n")?;
		Writer::write_dictionary(file, &self.trailer)?;
		Ok(())
	}
}

pub struct Writer;

impl Writer {
	fn need_separator(object: &Object) -> bool {
		match *object {
			Null => true,
			Boolean(_) => true,
			Integer(_) => true,
			Real(_) => true,
			Reference(_) => true,
			_ => false,
		}
	}

	fn need_end_separator(object: &Object) -> bool {
		match *object {
			Null => true,
			Boolean(_) => true,
			Integer(_) => true,
			Real(_) => true,
			Name(_) => true,
			Reference(_) => true,
			Object::Stream(_) => true,
			_ => false,
		}
	}

	fn write_xref(file: &mut dyn Write, xref: &Xref) -> Result<()> {
		file.write_all(b"xref\n")?;
		write!(file, "0 {}\n", xref.size)?;

		let mut write_xref_entry = |offset: u32, generation: u16, kind: char| write!(file, "{:>010} {:>05} {} \n", offset, generation, kind);
		write_xref_entry(0, 65535, 'f')?;

		let mut obj_id = 1;
		while obj_id < xref.size {
			if let Some(entry) = xref.get(obj_id) {
				if let XrefEntry::Normal { offset, generation } = *entry {
					write_xref_entry(offset, generation, 'n')?;
				};
			} else {
				write_xref_entry(0, 65535, 'f')?;
			}
			obj_id += 1;
		}
		Ok(())
	}

	fn write_indirect_object<W: Write>(file: &mut CountingWrite<&mut W>, id: u32, generation: u16, object: &Object, xref: &mut Xref) -> Result<()> {
		let offset = file.bytes_written as u32;
		xref.insert(id, XrefEntry::Normal { offset, generation });
		write!(file, "{} {} obj{}", id, generation, if Writer::need_separator(object) { " " } else { "" })?;
		Writer::write_object(file, object)?;
		write!(file, "{}endobj\n", if Writer::need_end_separator(object) { " " } else { "" })?;
		Ok(())
	}

	pub fn write_object(file: &mut dyn Write, object: &Object) -> Result<()> {
		match *object {
			Null => file.write_all(b"null"),
			Boolean(ref value) => if *value {
				file.write_all(b"true")
			} else {
				file.write_all(b"false")
			},
			Integer(ref value) => {
				let _ = itoa::write(file, *value);
				Ok(())
			}
			Real(ref value) => {
				let _ = dtoa::write(file, *value);
				Ok(())
			}
			Name(ref name) => Writer::write_name(file, name),
			String(ref text, ref format) => Writer::write_string(file, text, format),
			Array(ref array) => Writer::write_array(file, array),
			Object::Dictionary(ref dict) => Writer::write_dictionary(file, dict),
			Object::Stream(ref stream) => Writer::write_stream(file, stream),
			Reference(ref id) => write!(file, "{} {} R", id.0, id.1),
		}
	}

	fn write_name(file: &mut dyn Write, name: &[u8]) -> Result<()> {
		file.write_all(b"/")?;
		for &byte in name {
			// white-space and delimiter chars are encoded to # sequences
			// also encode bytes outside of the range 33 (!) to 126 (~)
			if b" \t\n\r\x0C()<>[]{}/%#".contains(&byte) || byte < 33 || byte > 126 {
				write!(file, "#{:02X}", byte)?;
			} else {
				file.write_all(&[byte])?;
			}
		}
		Ok(())
	}

	fn write_string(file: &mut dyn Write, text: &[u8], format: &StringFormat) -> Result<()> {
		match *format {
			// Within a Literal string, backslash (\) and unbalanced parentheses should be escaped.
			// This rule apply to each individual byte in a string object,
			// whether the string is interpreted as single-byte or multiple-byte character codes.
			// If an end-of-line marker appears within a literal string without a preceding backslash, the result is equivalent to \n.
			// So \r also need be escaped.
			StringFormat::Literal => {
				let mut escape_indice = Vec::new();
				let mut parentheses = Vec::new();
				for (index, &byte) in text.iter().enumerate() {
					match byte {
						b'(' => parentheses.push(index),
						b')' => {
							if !parentheses.is_empty() {
								parentheses.pop();
							} else {
								escape_indice.push(index);
							}
						}
						b'\\' | b'\r' => escape_indice.push(index),
						_ => continue,
					}
				}
				escape_indice.append(&mut parentheses);

				file.write_all(b"(")?;
				if !escape_indice.is_empty() {
					for (index, &byte) in text.iter().enumerate() {
						if escape_indice.contains(&index) {
							file.write_all(b"\\")?;
							file.write_all(&[if byte == b'\r' { b'r' } else { byte }])?;
						} else {
							file.write_all(&[byte])?;
						}
					}
				} else {
					file.write_all(text)?;
				}
				file.write_all(b")")?;
			}
			StringFormat::Hexadecimal => {
				file.write_all(b"<")?;
				for &byte in text {
					write!(file, "{:02X}", byte)?;
				}
				file.write_all(b">")?;
			}
		}
		Ok(())
	}

	fn write_array(file: &mut dyn Write, array: &[Object]) -> Result<()> {
		file.write_all(b"[")?;
		let mut first = true;
		for object in array {
			if first {
				first = false;
			} else if Writer::need_separator(object) {
				file.write_all(b" ")?;
			}
			Writer::write_object(file, object)?;
		}
		file.write_all(b"]")?;
		Ok(())
	}

	fn write_dictionary(file: &mut dyn Write, dictionary: &Dictionary) -> Result<()> {
		file.write_all(b"<<")?;
		for (key, value) in dictionary {
			Writer::write_name(file, key)?;
			if Writer::need_separator(value) {
				file.write_all(b" ")?;
			}
			Writer::write_object(file, value)?;
		}
		file.write_all(b">>")?;
		Ok(())
	}

	fn write_stream(file: &mut dyn Write, stream: &Stream) -> Result<()> {
		Writer::write_dictionary(file, &stream.dict)?;
		file.write_all(b"stream\n")?;
		file.write_all(&stream.content)?;
		file.write_all(b"endstream")?;
		Ok(())
	}
}

pub struct CountingWrite<W: Write> {
	inner: W,
	bytes_written: usize,
}

impl<W: Write> Write for CountingWrite<W> {
	#[inline]
	fn write(&mut self, buffer: &[u8]) -> Result<usize> {
		let result = self.inner.write(buffer);
		if let Ok(bytes) = result {
			self.bytes_written += bytes;
		}
		result
	}

	#[inline]
	fn write_all(&mut self, buffer: &[u8]) -> Result<()> {
		self.bytes_written += buffer.len();
		// If this returns `Err` we can’t know how many bytes were actually written (if any)
		// but that doesn’t matter since we’re gonna abort the entire PDF generation anyway.
		self.inner.write_all(buffer)
	}

	#[inline]
	fn flush(&mut self) -> Result<()> {
		self.inner.flush()
	}
}

#[test]
fn save_document() {
	let mut doc = Document::with_version("1.5");
	doc.objects.insert((1, 0), Null);
	doc.objects.insert((2, 0), Boolean(true));
	doc.objects.insert((3, 0), Integer(3));
	doc.objects.insert((4, 0), Real(0.5));
	doc.objects.insert((5, 0), String("text((\r)".as_bytes().to_vec(), StringFormat::Literal));
	doc.objects.insert((6, 0), String("text((\r)".as_bytes().to_vec(), StringFormat::Hexadecimal));
	doc.objects.insert((7, 0), Name(b"name \t".to_vec()));
	doc.objects.insert((8, 0), Reference((1, 0)));
	doc.objects.insert((9, 2), Array(vec![Integer(1), Integer(2), Integer(3)]));
	doc.objects.insert((11, 0), Stream(Stream::new(Dictionary::new(), vec![0x41, 0x42, 0x43])));
	let mut dict = Dictionary::new();
	dict.set("A", Null);
	dict.set("B", false);
	dict.set("C", Name(b"name".to_vec()));
	doc.objects.insert((12, 0), Object::Dictionary(dict));
	doc.max_id = 12;

	doc.save("test_0_save.pdf").unwrap();
}
<commit_msg>Use a BufWriter when saving to path.<commit_after>use std::fs::File;
use std::io::{BufWriter, Result, Write};
use std::path::Path;

use super::Object::*;
use super::{Dictionary, Document, Object, Stream, StringFormat};
use crate::xref::*;

impl Document {
	/// Save PDF document to specified file path.
	#[inline]
	pub fn save<P: AsRef<Path>>(&mut self, path: P) -> Result<File> {
		let mut file = BufWriter::new(File::create(path)?);
		self.save_internal(&mut file)?;
		Ok(file.into_inner()?)
	}

	/// Save PDF to arbitrary target
	#[inline]
	pub fn save_to<W: Write>(&mut self, target: &mut W) -> Result<()> {
		self.save_internal(target)
	}

	fn save_internal<W: Write>(&mut self, target: &mut W) -> Result<()> {
		let mut target = CountingWrite { inner: target, bytes_written: 0 };
		let mut xref = Xref::new(self.max_id + 1);
		write!(target, "%PDF-{}\n", self.version)?;

		for (&(id, generation), object) in &self.objects {
			if object.type_name().map(|name| ["ObjStm", "XRef", "Linearized"].contains(&name)) != Some(true) {
				Writer::write_indirect_object(&mut target, id, generation, object, &mut xref)?;
			}
		}

		let xref_start = target.bytes_written;
		Writer::write_xref(&mut target, &xref)?;
		self.write_trailer(&mut target)?;
		write!(target, "\nstartxref\n{}\n%%EOF", xref_start)?;

		Ok(())
	}

	fn write_trailer(&mut self, file: &mut dyn Write) -> Result<()> {
		self.trailer.set("Size", i64::from(self.max_id + 1));
		file.write_all(b"trailer\n")?;
		Writer::write_dictionary(file, &self.trailer)?;
		Ok(())
	}
}

pub struct Writer;

impl Writer {
	fn need_separator(object: &Object) -> bool {
		match *object {
			Null => true,
			Boolean(_) => true,
			Integer(_) => true,
			Real(_) => true,
			Reference(_) => true,
			_ => false,
		}
	}

	fn need_end_separator(object: &Object) -> bool {
		match *object {
			Null => true,
			Boolean(_) => true,
			Integer(_) => true,
			Real(_) => true,
			Name(_) => true,
			Reference(_) => true,
			Object::Stream(_) => true,
			_ => false,
		}
	}

	fn write_xref(file: &mut dyn Write, xref: &Xref) -> Result<()> {
		file.write_all(b"xref\n")?;
		write!(file, "0 {}\n", xref.size)?;

		let mut write_xref_entry = |offset: u32, generation: u16, kind: char| write!(file, "{:>010} {:>05} {} \n", offset, generation, kind);
		write_xref_entry(0, 65535, 'f')?;

		let mut obj_id = 1;
		while obj_id < xref.size {
			if let Some(entry) = xref.get(obj_id) {
				if let XrefEntry::Normal { offset, generation } = *entry {
					write_xref_entry(offset, generation, 'n')?;
				};
			} else {
				write_xref_entry(0, 65535, 'f')?;
			}
			obj_id += 1;
		}
		Ok(())
	}

	fn write_indirect_object<W: Write>(file: &mut CountingWrite<&mut W>, id: u32, generation: u16, object: &Object, xref: &mut Xref) -> Result<()> {
		let offset = file.bytes_written as u32;
		xref.insert(id, XrefEntry::Normal { offset, generation });
		write!(file, "{} {} obj{}", id, generation, if Writer::need_separator(object) { " " } else { "" })?;
		Writer::write_object(file, object)?;
		write!(file, "{}endobj\n", if Writer::need_end_separator(object) { " " } else { "" })?;
		Ok(())
	}

	pub fn write_object(file: &mut dyn Write, object: &Object) -> Result<()> {
		match *object {
			Null => file.write_all(b"null"),
			Boolean(ref value) => if *value {
				file.write_all(b"true")
			} else {
				file.write_all(b"false")
			},
			Integer(ref value) => {
				let _ = itoa::write(file, *value);
				Ok(())
			}
			Real(ref value) => {
				let _ = dtoa::write(file, *value);
				Ok(())
			}
			Name(ref name) => Writer::write_name(file, name),
			String(ref text, ref format) => Writer::write_string(file, text, format),
			Array(ref array) => Writer::write_array(file, array),
			Object::Dictionary(ref dict) => Writer::write_dictionary(file, dict),
			Object::Stream(ref stream) => Writer::write_stream(file, stream),
			Reference(ref id) => write!(file, "{} {} R", id.0, id.1),
		}
	}

	fn write_name(file: &mut dyn Write, name: &[u8]) -> Result<()> {
		file.write_all(b"/")?;
		for &byte in name {
			// white-space and delimiter chars are encoded to # sequences
			// also encode bytes outside of the range 33 (!) to 126 (~)
			if b" \t\n\r\x0C()<>[]{}/%#".contains(&byte) || byte < 33 || byte > 126 {
				write!(file, "#{:02X}", byte)?;
			} else {
				file.write_all(&[byte])?;
			}
		}
		Ok(())
	}

	fn write_string(file: &mut dyn Write, text: &[u8], format: &StringFormat) -> Result<()> {
		match *format {
			// Within a Literal string, backslash (\) and unbalanced parentheses should be escaped.
			// This rule apply to each individual byte in a string object,
			// whether the string is interpreted as single-byte or multiple-byte character codes.
			// If an end-of-line marker appears within a literal string without a preceding backslash, the result is equivalent to \n.
			// So \r also need be escaped.
			StringFormat::Literal => {
				let mut escape_indice = Vec::new();
				let mut parentheses = Vec::new();
				for (index, &byte) in text.iter().enumerate() {
					match byte {
						b'(' => parentheses.push(index),
						b')' => {
							if !parentheses.is_empty() {
								parentheses.pop();
							} else {
								escape_indice.push(index);
							}
						}
						b'\\' | b'\r' => escape_indice.push(index),
						_ => continue,
					}
				}
				escape_indice.append(&mut parentheses);

				file.write_all(b"(")?;
				if !escape_indice.is_empty() {
					for (index, &byte) in text.iter().enumerate() {
						if escape_indice.contains(&index) {
							file.write_all(b"\\")?;
							file.write_all(&[if byte == b'\r' { b'r' } else { byte }])?;
						} else {
							file.write_all(&[byte])?;
						}
					}
				} else {
					file.write_all(text)?;
				}
				file.write_all(b")")?;
			}
			StringFormat::Hexadecimal => {
				file.write_all(b"<")?;
				for &byte in text {
					write!(file, "{:02X}", byte)?;
				}
				file.write_all(b">")?;
			}
		}
		Ok(())
	}

	fn write_array(file: &mut dyn Write, array: &[Object]) -> Result<()> {
		file.write_all(b"[")?;
		let mut first = true;
		for object in array {
			if first {
				first = false;
			} else if Writer::need_separator(object) {
				file.write_all(b" ")?;
			}
			Writer::write_object(file, object)?;
		}
		file.write_all(b"]")?;
		Ok(())
	}

	fn write_dictionary(file: &mut dyn Write, dictionary: &Dictionary) -> Result<()> {
		file.write_all(b"<<")?;
		for (key, value) in dictionary {
			Writer::write_name(file, key)?;
			if Writer::need_separator(value) {
				file.write_all(b" ")?;
			}
			Writer::write_object(file, value)?;
		}
		file.write_all(b">>")?;
		Ok(())
	}

	fn write_stream(file: &mut dyn Write, stream: &Stream) -> Result<()> {
		Writer::write_dictionary(file, &stream.dict)?;
		file.write_all(b"stream\n")?;
		file.write_all(&stream.content)?;
		file.write_all(b"endstream")?;
		Ok(())
	}
}

pub struct CountingWrite<W: Write> {
	inner: W,
	bytes_written: usize,
}

impl<W: Write> Write for CountingWrite<W> {
	#[inline]
	fn write(&mut self, buffer: &[u8]) -> Result<usize> {
		let result = self.inner.write(buffer);
		if let Ok(bytes) = result {
			self.bytes_written += bytes;
		}
		result
	}

	#[inline]
	fn write_all(&mut self, buffer: &[u8]) -> Result<()> {
		self.bytes_written += buffer.len();
		// If this returns `Err` we can’t know how many bytes were actually written (if any)
		// but that doesn’t matter since we’re gonna abort the entire PDF generation anyway.
		self.inner.write_all(buffer)
	}

	#[inline]
	fn flush(&mut self) -> Result<()> {
		self.inner.flush()
	}
}

#[test]
fn save_document() {
	let mut doc = Document::with_version("1.5");
	doc.objects.insert((1, 0), Null);
	doc.objects.insert((2, 0), Boolean(true));
	doc.objects.insert((3, 0), Integer(3));
	doc.objects.insert((4, 0), Real(0.5));
	doc.objects.insert((5, 0), String("text((\r)".as_bytes().to_vec(), StringFormat::Literal));
	doc.objects.insert((6, 0), String("text((\r)".as_bytes().to_vec(), StringFormat::Hexadecimal));
	doc.objects.insert((7, 0), Name(b"name \t".to_vec()));
	doc.objects.insert((8, 0), Reference((1, 0)));
	doc.objects.insert((9, 2), Array(vec![Integer(1), Integer(2), Integer(3)]));
	doc.objects.insert((11, 0), Stream(Stream::new(Dictionary::new(), vec![0x41, 0x42, 0x43])));
	let mut dict = Dictionary::new();
	dict.set("A", Null);
	dict.set("B", false);
	dict.set("C", Name(b"name".to_vec()));
	doc.objects.insert((12, 0), Object::Dictionary(dict));
	doc.max_id = 12;

	doc.save("test_0_save.pdf").unwrap();
}
<|endoftext|>


<commit_before>use std::io::{Write, Error, ErrorKind};
use std::io;
use InflateStream;

pub struct InflateWriter<W: Write> {
    inflater: InflateStream,
    writer: W
}

impl<W: Write> InflateWriter<W> {
    pub fn new(w: W) -> InflateWriter<W> {
        InflateWriter { inflater: InflateStream::new(), writer: w }
    }

    pub fn finish(mut self) -> io::Result<W> {
        self.flush()?;
        Ok(self.writer)
    }
}

fn update<'a>(inflater: &'a mut InflateStream, buf: &[u8]) -> io::Result<(usize, &'a [u8])>  {
    match inflater.update(buf) {
        Ok(res) => Ok(res),
        Err(m) => return Err(Error::new(ErrorKind::Other, m)),
    }
}
impl<W: Write> Write for InflateWriter<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut n = 0;
        while n < buf.len() {
            let (num_bytes_read, result) = update(&mut self.inflater, &buf[n..])?;
            n += num_bytes_read;
            self.writer.write(result)?;
        }
        Ok(n)
    }

    fn flush(&mut self) -> io::Result<()> {
        let (_, result) = update(&mut self.inflater, &[])?;
        self.writer.write(result)?;
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::InflateWriter;
    use std::io::Write;

    #[test]
    fn inflate_writer() {
       let encoded = [243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0];
       let mut decoder = InflateWriter::new(Vec::new());
       decoder.write(&encoded).unwrap();
       let decoded = decoder.finish().unwrap();
       assert!(String::from_utf8(decoded).unwrap() == "Hello, world");
    }
}
<commit_msg>Use try! instead of ?<commit_after>use std::io::{Write, Error, ErrorKind};
use std::io;
use InflateStream;

pub struct InflateWriter<W: Write> {
    inflater: InflateStream,
    writer: W
}

impl<W: Write> InflateWriter<W> {
    pub fn new(w: W) -> InflateWriter<W> {
        InflateWriter { inflater: InflateStream::new(), writer: w }
    }

    pub fn finish(mut self) -> io::Result<W> {
        try!(self.flush());
        Ok(self.writer)
    }
}

fn update<'a>(inflater: &'a mut InflateStream, buf: &[u8]) -> io::Result<(usize, &'a [u8])>  {
    match inflater.update(buf) {
        Ok(res) => Ok(res),
        Err(m) => return Err(Error::new(ErrorKind::Other, m)),
    }
}
impl<W: Write> Write for InflateWriter<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut n = 0;
        while n < buf.len() {
            let (num_bytes_read, result) = try!(update(&mut self.inflater, &buf[n..]));
            n += num_bytes_read;
            self.writer.write(result)?;
        }
        Ok(n)
    }

    fn flush(&mut self) -> io::Result<()> {
        let (_, result) = try!(update(&mut self.inflater, &[]));
        try!(self.writer.write(result));
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::InflateWriter;
    use std::io::Write;

    #[test]
    fn inflate_writer() {
       let encoded = [243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0];
       let mut decoder = InflateWriter::new(Vec::new());
       decoder.write(&encoded).unwrap();
       let decoded = decoder.finish().unwrap();
       assert!(String::from_utf8(decoded).unwrap() == "Hello, world");
    }
}
<|endoftext|>