<commit_before>//! Provides abstractions for working with bytes.
//!
//! The `bytes` crate provides an efficient byte buffer structure
//! ([`Bytes`](struct.Bytes.html)) and traits for working with buffer
//! implementations ([`Buf`], [`BufMut`]).
//!
//! [`Buf`]: trait.Buf.html
//! [`BufMut`]: trait.BufMut.html
//!
//! # `Bytes`
//!
//! `Bytes` is an efficient container for storing and operating on continguous
//! slices of memory. It is intended for use primarily in networking code, but
//! could have applications elsewhere as well.
//!
//! `Bytes` values facilitate zero-copy network programming by allowing multiple
//! `Bytes` objects to point to the same underlying memory. This is managed by
//! using a reference count to track when the memory is no longer needed and can
//! be freed.
//!
//! A `Bytes` handle can be created directly from an existing byte store (such as &[u8]
//! or Vec<u8>), but usually a `BytesMut` is used first and written to. For
//! example:
//!
//! ```rust
//! use bytes::{BytesMut, BufMut, BigEndian};
//!
//! let mut buf = BytesMut::with_capacity(1024);
//! buf.put(&b"hello world"[..]);
//! buf.put_u16::<BigEndian>(1234);
//!
//! let a = buf.take();
//! assert_eq!(a, b"hello world\x04\xD2"[..]);
//!
//! buf.put(&b"goodbye world"[..]);
//!
//! let b = buf.take();
//! assert_eq!(b, b"goodbye world"[..]);
//!
//! assert_eq!(buf.capacity(), 998);
//! ```
//!
//! In the above example, only a single buffer of 1024 is allocated. The handles
//! `a` and `b` will share the underlying buffer and maintain indices tracking
//! the view into the buffer represented by the handle.
//!
//! See the [struct docs] for more details.
//!
//! [struct docs]: struct.Bytes.html
//!
//! # `Buf`, `BufMut`
//!
//! These two traits provide read and write access to buffers. The underlying
//! storage may or may not be in contiguous memory. For example, `Bytes` is a
//! buffer that guarantees contiguous memory, but a [rope] stores the bytes in
//! disjoint chunks. `Buf` and `BufMut` maintain cursors tracking the current
//! position in the underlying byte storage. When bytes are read or written, the
//! cursor is advanced.
//!
//! [rope]: https://en.wikipedia.org/wiki/Rope_(data_structure)
//!
//! ## Relation with `Read` and `Write`
//!
//! At first glance, it may seem that `Buf` and `BufMut` overlap in
//! functionality with `std::io::Ready` and `std::io::Write`. However, they
//! serve different purposes. A buffer is the value that is provided as an
//! argument to `Read::read` and `Write::write`. `Read` and `Write` may then
//! perform a syscall, which has the potential of failing. Operations on `Buf`
//! and `BufMut` are infallible.

#![deny(warnings, missing_docs, missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/bytes/0.4")]

extern crate byteorder;
extern crate iovec;

pub mod buf;
pub use buf::{
    Buf,
    BufMut,
    IntoBuf,
};
#[deprecated(since = "0.4.1", note = "moved to `buf` module")]
#[doc(hidden)]
pub use buf::{
    Reader,
    Writer,
    Take,
};

mod bytes;
mod debug;
pub use bytes::{Bytes, BytesMut};

pub use byteorder::{ByteOrder, BigEndian, LittleEndian};

// Optional Serde support
#[cfg(feature = "serde")]
#[doc(hidden)]
pub mod serde;
<commit_msg>fix a docs typo (#115)<commit_after>//! Provides abstractions for working with bytes.
//!
//! The `bytes` crate provides an efficient byte buffer structure
//! ([`Bytes`](struct.Bytes.html)) and traits for working with buffer
//! implementations ([`Buf`], [`BufMut`]).
//!
//! [`Buf`]: trait.Buf.html
//! [`BufMut`]: trait.BufMut.html
//!
//! # `Bytes`
//!
//! `Bytes` is an efficient container for storing and operating on continguous
//! slices of memory. It is intended for use primarily in networking code, but
//! could have applications elsewhere as well.
//!
//! `Bytes` values facilitate zero-copy network programming by allowing multiple
//! `Bytes` objects to point to the same underlying memory. This is managed by
//! using a reference count to track when the memory is no longer needed and can
//! be freed.
//!
//! A `Bytes` handle can be created directly from an existing byte store (such as &[u8]
//! or Vec<u8>), but usually a `BytesMut` is used first and written to. For
//! example:
//!
//! ```rust
//! use bytes::{BytesMut, BufMut, BigEndian};
//!
//! let mut buf = BytesMut::with_capacity(1024);
//! buf.put(&b"hello world"[..]);
//! buf.put_u16::<BigEndian>(1234);
//!
//! let a = buf.take();
//! assert_eq!(a, b"hello world\x04\xD2"[..]);
//!
//! buf.put(&b"goodbye world"[..]);
//!
//! let b = buf.take();
//! assert_eq!(b, b"goodbye world"[..]);
//!
//! assert_eq!(buf.capacity(), 998);
//! ```
//!
//! In the above example, only a single buffer of 1024 is allocated. The handles
//! `a` and `b` will share the underlying buffer and maintain indices tracking
//! the view into the buffer represented by the handle.
//!
//! See the [struct docs] for more details.
//!
//! [struct docs]: struct.Bytes.html
//!
//! # `Buf`, `BufMut`
//!
//! These two traits provide read and write access to buffers. The underlying
//! storage may or may not be in contiguous memory. For example, `Bytes` is a
//! buffer that guarantees contiguous memory, but a [rope] stores the bytes in
//! disjoint chunks. `Buf` and `BufMut` maintain cursors tracking the current
//! position in the underlying byte storage. When bytes are read or written, the
//! cursor is advanced.
//!
//! [rope]: https://en.wikipedia.org/wiki/Rope_(data_structure)
//!
//! ## Relation with `Read` and `Write`
//!
//! At first glance, it may seem that `Buf` and `BufMut` overlap in
//! functionality with `std::io::Read` and `std::io::Write`. However, they
//! serve different purposes. A buffer is the value that is provided as an
//! argument to `Read::read` and `Write::write`. `Read` and `Write` may then
//! perform a syscall, which has the potential of failing. Operations on `Buf`
//! and `BufMut` are infallible.

#![deny(warnings, missing_docs, missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/bytes/0.4")]

extern crate byteorder;
extern crate iovec;

pub mod buf;
pub use buf::{
    Buf,
    BufMut,
    IntoBuf,
};
#[deprecated(since = "0.4.1", note = "moved to `buf` module")]
#[doc(hidden)]
pub use buf::{
    Reader,
    Writer,
    Take,
};

mod bytes;
mod debug;
pub use bytes::{Bytes, BytesMut};

pub use byteorder::{ByteOrder, BigEndian, LittleEndian};

// Optional Serde support
#[cfg(feature = "serde")]
#[doc(hidden)]
pub mod serde;
<|endoftext|>


<commit_before>extern crate libc;
extern crate "posix-ipc" as ipc;

use std::os;
use std::ptr;
use std::default::Default;
use std::vec::Vec;
use std::mem;
use std::iter;
use std::num::FromPrimitive;

pub type Address = u64;
pub type Word = u64;

pub enum Action {
  Allow,
  Kill
}

#[derive(Show)]
pub enum Request {
  TraceMe = 0,
  PeekText = 1,
  PeekData = 2,
  PeekUser = 3,
  PokeText = 4,
  PokeData = 5,
  PokeUser = 6,
  Continue = 7,
  Kill = 8,
  SingleStep = 9,
  GetRegs = 12,
  Attach = 16,
  Detatch = 17,
  SetOptions = 0x4200
}

#[derive(Show, FromPrimitive)]
pub enum Event {
  Fork = 1,
  VFork = 2,
  Clone = 3,
  Exec = 4,
  VForkDone = 5,
  Exit = 6,
  Seccomp = 7,
  Stop = 128
}

#[derive(Default, Show)]
pub struct Registers {
  pub r15: Word,
  pub r14: Word,
  pub r13: Word,
  pub r12: Word,
  pub rbp: Word,
  pub rbx: Word,
  pub r11: Word,
  pub r10: Word,
  pub r9: Word,
  pub r8: Word,
  pub rax: Word,
  pub rcx: Word,
  pub rdx: Word,
  pub rsi: Word,
  pub rdi: Word,
  pub orig_rax: Word,
  pub rip: Word,
  pub cs: Word,
  pub eflags: Word,
  pub rsp: Word,
  pub ss: Word,
  pub fs_base: Word,
  pub gs_base: Word,
  pub ds: Word,
  pub es: Word,
  pub fs: Word,
  pub gs: Word
}

bitflags! {
  flags Options: u32 {
    const SysGood = 1,
    const TraceFork = 1 << 1,
    const TraceVFork = 1 << 2,
    const TraceClone = 1 << 3,
    const TraceExec = 1 << 4,
    const TraceVForkDone = 1 << 5,
    const TraceExit = 1 << 6,
    const TraceSeccomp = 1 << 7,
    const ExitKill = 1 << 20
  }
}

pub fn setoptions(pid: libc::pid_t, opts: Options) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::SetOptions, pid, ptr::null_mut(), opts.bits as *mut
    libc::c_void)
  }
}

pub fn getregs(pid: libc::pid_t) -> Registers {
  let mut buf: Registers = Default::default();
  let buf_mut: *mut Registers = &mut buf;

  unsafe {
    raw (Request::GetRegs, pid, ptr::null_mut(), buf_mut as *mut libc::c_void);
  }

  return buf;
}

pub fn attach(pid: libc::pid_t) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::Attach, pid, ptr::null_mut(), ptr::null_mut())
  }
}

pub fn release(pid: libc::pid_t, signal: ipc::signals::Signal) {
  unsafe {
    raw (Request::Detatch, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void);
  }
}

pub fn cont(pid: libc::pid_t, signal: ipc::signals::Signal) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::Continue, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void)
  }
}

pub fn traceme() {
  unsafe {
    raw (Request::TraceMe, 0, ptr::null_mut(), ptr::null_mut());
  }
}

unsafe fn raw(request: Request,
       pid: libc::pid_t,
       addr: *mut libc::c_void,
       data: *mut libc::c_void) -> Result<libc::c_long, usize> {
  let v = ptrace (request as libc::c_int, pid, addr, data);
  match v {
      -1 => Result::Err(os::errno()),
      _ => Result::Ok(v)
  }
}

extern {
  fn ptrace(request: libc::c_int,
            pid: libc::pid_t,
            addr: *mut libc::c_void,
            data: *mut libc::c_void) -> libc::c_long;
}

#[derive(Show)]
pub struct Syscall {
  pub args: [Word; 6],
  pub call: u64,
  pub pid: libc::pid_t,
  pub returnVal: Word
}

impl Syscall {
  pub fn from_pid(pid: libc::pid_t) -> Syscall {
    let regs = getregs (pid);
    Syscall {
      pid: pid,
      call: regs.orig_rax,
      args: [regs.rdi, regs.rsi, regs.rdx, regs.rcx, regs.r8, regs.r9],
      returnVal: 0
    }
  }
}

pub struct Reader {
  pub pid: libc::pid_t
}

impl Reader {
  pub fn new(pid: libc::pid_t) -> Reader {
    Reader {
      pid: pid
    }
  }

    pub fn peek_data(&self, address: Address) -> Result<Word, usize> {
        let l;
        unsafe {
            l = raw (Request::PeekData, self.pid, address as *mut libc::c_void, ptr::null_mut())
        }
        match l {
            Result::Err(e) => Result::Err(e),
            _ => Result::Ok(l.unwrap() as Word)
        }
    }

    pub fn read_string(&self, address: Address) -> Vec<u8> {
        let mut end_of_str = false;
        let mut buf: Vec<u8> = Vec::with_capacity(1024);
        let max_addr = address + buf.capacity() as Address;
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        'finish: for read_addr in iter::range_step(address, align_end, mem::size_of::<Word>() as Address) {
            let d = self.peek_data(read_addr).ok().expect("Could not read");
            for word_idx in iter::range(0, mem::size_of::<Word>()) {
                let chr = ((d >> (word_idx*8) as uint) & 0xff) as u8;
                buf.push (chr);
                if chr == 0 {
                    end_of_str = true;
                    break 'finish;
                }
            }
        }
        if !end_of_str {
            let d = self.peek_data(align_end).ok().expect("Could not read");
            for word_idx in range(0, mem::size_of::<Word>()) {
                let chr = ((d >> (word_idx*8) as uint) & 0xff) as u8;
                buf.push (chr);
                if chr == 0 {
                    break;
                }
            }
        }
        return buf;
    }
}
<commit_msg>Implement seize; let traceme return a result<commit_after>extern crate libc;
extern crate "posix-ipc" as ipc;

use std::os;
use std::ptr;
use std::default::Default;
use std::vec::Vec;
use std::mem;
use std::iter;
use std::num::FromPrimitive;

pub type Address = u64;
pub type Word = u64;

pub enum Action {
  Allow,
  Kill
}

#[derive(Show)]
pub enum Request {
  TraceMe = 0,
  PeekText = 1,
  PeekData = 2,
  PeekUser = 3,
  PokeText = 4,
  PokeData = 5,
  PokeUser = 6,
  Continue = 7,
  Kill = 8,
  SingleStep = 9,
  GetRegs = 12,
  Attach = 16,
  Detatch = 17,
  SetOptions = 0x4200,
  Seize = 0x4206
}

#[derive(Show, FromPrimitive)]
pub enum Event {
  Fork = 1,
  VFork = 2,
  Clone = 3,
  Exec = 4,
  VForkDone = 5,
  Exit = 6,
  Seccomp = 7,
  Stop = 128
}

#[derive(Default, Show)]
pub struct Registers {
  pub r15: Word,
  pub r14: Word,
  pub r13: Word,
  pub r12: Word,
  pub rbp: Word,
  pub rbx: Word,
  pub r11: Word,
  pub r10: Word,
  pub r9: Word,
  pub r8: Word,
  pub rax: Word,
  pub rcx: Word,
  pub rdx: Word,
  pub rsi: Word,
  pub rdi: Word,
  pub orig_rax: Word,
  pub rip: Word,
  pub cs: Word,
  pub eflags: Word,
  pub rsp: Word,
  pub ss: Word,
  pub fs_base: Word,
  pub gs_base: Word,
  pub ds: Word,
  pub es: Word,
  pub fs: Word,
  pub gs: Word
}

bitflags! {
  flags Options: u32 {
    const SysGood = 1,
    const TraceFork = 1 << 1,
    const TraceVFork = 1 << 2,
    const TraceClone = 1 << 3,
    const TraceExec = 1 << 4,
    const TraceVForkDone = 1 << 5,
    const TraceExit = 1 << 6,
    const TraceSeccomp = 1 << 7,
    const ExitKill = 1 << 20
  }
}

pub fn setoptions(pid: libc::pid_t, opts: Options) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::SetOptions, pid, ptr::null_mut(), opts.bits as *mut
    libc::c_void)
  }
}

pub fn getregs(pid: libc::pid_t) -> Registers {
  let mut buf: Registers = Default::default();
  let buf_mut: *mut Registers = &mut buf;

  unsafe {
    raw (Request::GetRegs, pid, ptr::null_mut(), buf_mut as *mut libc::c_void);
  }

  return buf;
}

pub fn seize(pid: libc::pid_t) -> Result<libc::c_long, usize> {
    unsafe {
        raw (Request::Seize, pid, ptr::null_mut(), ptr::null_mut())
    }
}

pub fn attach(pid: libc::pid_t) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::Attach, pid, ptr::null_mut(), ptr::null_mut())
  }
}

pub fn release(pid: libc::pid_t, signal: ipc::signals::Signal) {
  unsafe {
    raw (Request::Detatch, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void);
  }
}

pub fn cont(pid: libc::pid_t, signal: ipc::signals::Signal) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::Continue, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void)
  }
}

pub fn traceme() -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::TraceMe, 0, ptr::null_mut(), ptr::null_mut())
  }
}

unsafe fn raw(request: Request,
       pid: libc::pid_t,
       addr: *mut libc::c_void,
       data: *mut libc::c_void) -> Result<libc::c_long, usize> {
  let v = ptrace (request as libc::c_int, pid, addr, data);
  match v {
      -1 => Result::Err(os::errno()),
      _ => Result::Ok(v)
  }
}

extern {
  fn ptrace(request: libc::c_int,
            pid: libc::pid_t,
            addr: *mut libc::c_void,
            data: *mut libc::c_void) -> libc::c_long;
}

#[derive(Show)]
pub struct Syscall {
  pub args: [Word; 6],
  pub call: u64,
  pub pid: libc::pid_t,
  pub returnVal: Word
}

impl Syscall {
  pub fn from_pid(pid: libc::pid_t) -> Syscall {
    let regs = getregs (pid);
    Syscall {
      pid: pid,
      call: regs.orig_rax,
      args: [regs.rdi, regs.rsi, regs.rdx, regs.rcx, regs.r8, regs.r9],
      returnVal: 0
    }
  }
}

pub struct Reader {
  pub pid: libc::pid_t
}

impl Reader {
  pub fn new(pid: libc::pid_t) -> Reader {
    Reader {
      pid: pid
    }
  }

    pub fn peek_data(&self, address: Address) -> Result<Word, usize> {
        let l;
        unsafe {
            l = raw (Request::PeekData, self.pid, address as *mut libc::c_void, ptr::null_mut())
        }
        match l {
            Result::Err(e) => Result::Err(e),
            _ => Result::Ok(l.unwrap() as Word)
        }
    }

    pub fn read_string(&self, address: Address) -> Vec<u8> {
        let mut end_of_str = false;
        let mut buf: Vec<u8> = Vec::with_capacity(1024);
        let max_addr = address + buf.capacity() as Address;
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        'finish: for read_addr in iter::range_step(address, align_end, mem::size_of::<Word>() as Address) {
            let d = self.peek_data(read_addr).ok().expect("Could not read");
            for word_idx in iter::range(0, mem::size_of::<Word>()) {
                let chr = ((d >> (word_idx*8) as uint) & 0xff) as u8;
                buf.push (chr);
                if chr == 0 {
                    end_of_str = true;
                    break 'finish;
                }
            }
        }
        if !end_of_str {
            let d = self.peek_data(align_end).ok().expect("Could not read");
            for word_idx in range(0, mem::size_of::<Word>()) {
                let chr = ((d >> (word_idx*8) as uint) & 0xff) as u8;
                buf.push (chr);
                if chr == 0 {
                    break;
                }
            }
        }
        return buf;
    }
}
<|endoftext|>


<commit_before>extern crate getopts;
use getopts::{optflag,getopts,OptGroup,usage};
use std::os;

use std::num::FromPrimitive;
use std::num::Int;
use std::char;
use std::old_io;
use std::old_io::{IoResult, IoError};
use std::old_io::BufferedReader;
use std::old_io::File;
use std::old_io::stdio;

pub fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", usage(brief.as_slice(), opts));
}

pub fn cat(v: &Vec<String>, options: &getopts::Matches) {
    if options.opt_present("u") {
        let writer = Box::new(stdio::stdout_raw());
        stdio::set_stdout(writer);
    }
    if v.is_empty() {
        cat_stdin(options);
    }
    else {
        // read files
        cat_files(v, options);
    }
}

fn cat_files(v: &Vec<String>, options: &getopts::Matches) {
    let mut linenum = 1u32;
    for filename in v.iter() {
        let path = Path::new(filename);
        match File::open(&path) {
            Ok(fh) => {
                let mut file = BufferedReader::new(fh);
                linenum = cat_file(file, options, linenum);
            },
            Err(f) => {
                println!("{}", f);
            }
        }
    }
}

fn cat_stdin(options: &getopts::Matches) {
    let mut linenum = 1u32;
    let mut printempty: bool = false;
    for line in old_io::stdin().lock().lines() {
        let (a, b) = handle_line(line.unwrap(), &mut printempty, linenum, options);
        printempty = a;
        linenum = b;
    }
}

fn cat_file<'a>(
    mut file: old_io::BufferedReader<std::old_io::fs::File>,
    options: &getopts::Matches,
    mut linenum: u32,
    ) -> u32 {
    let mut printempty: bool = false;
    let mut read_buf = [0, 4096];
    let mut out_buf: Vec<u8> = vec![];
    loop {
        match file.read(&mut read_buf) {
            Ok(n) => {
                for c in read_buf[..n].iter() {
                    out_buf.push(*c);
                    if is_nl(c) {
                        let (a, b) = handle_buf(&out_buf, &mut printempty, linenum, options);
                        printempty = a;
                        linenum = b;
                        out_buf.clear();
                    }
                }
            },
            Err(f) => {
                let mut o = 0u32;
                if out_buf.len() > 0 {
                    handle_buf(&out_buf, &mut printempty, linenum, options);
                }
                break
            }
        }
    }
    linenum
}

fn handle_line<'a>(
    linestr: String,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty(&linestr) {
            if *printempty == true {
                println!("");
            }
            linenum = print_string(&linestr, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_string(&linestr, linenum, options);
    }
    (*printempty, linenum)
}

fn handle_buf<'a>(
    out_buf: &Vec<u8>,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty_out_buf(out_buf) {
            if *printempty == true {
                if options.opt_present("n") {
                    println!("     {}\t", linenum);
                    linenum = linenum + 1;
                }
                else {
                    println!("");
                }
            }
            linenum = print_buf(&out_buf, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_buf(&out_buf, linenum, options);
    }
    (*printempty, linenum)
}

fn print_string<'a>(s: &String, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty(s) {
            print_numbered(s, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered(s, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered(s, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered(s, options);
    }
    linenum
}

fn print_buf<'a>(out_buf: &Vec<u8>, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty_out_buf(out_buf) {
            print_numbered_buf(out_buf, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered_buf(out_buf, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered_buf(out_buf, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered_buf(out_buf, options);
    }
    linenum
}

fn print_numbered<'a>(s: &String, linenum: u32, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("     {}\t{}", linenum, s);
    }
}

fn print_numbered_buf<'a>(out_buf: &Vec<u8>, linenum: u32, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        let mut t = 0u32;
        for b in out_buf.iter() {
            if t > 0 {
                t = t + *b as u32;
                // print!("t: {} ", t);
                print!("{}", char::from_u32(t).unwrap());
                t = 0;
            }
            else {
                if *b > 160 {
                    t = *b as u32;
                }
                else {
                    print_byte(b, options);
                }
            }
        }
    // }
}

fn print_unnumbered(s: &String, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("{}", s);
    }
}

fn print_unnumbered_buf(out_buf: &Vec<u8>, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        let mut t = 0;
        let mut buf: Vec<u8> = vec![];
        for b in out_buf.iter() {
            if t > 0 {
                buf.push(*b);
                t = t - 1;
                if t == 0 {
                    print_u8_buf(&mut buf, options);
                    buf.clear();
                }
            }
            else {
                if *b >= 240 {
                    //4th byte
                    t = 3;
                    buf.push(*b);
                }
                else if *b >= 224 {
                    t = 2;
                    buf.push(*b);
                }
                else if *b >= 192 {
                    t = 1;
                    buf.push(*b);
                }
                else {
                    print_byte(b, options);
                }
            }
        }
    // }
    // else {
        // print!("{}", s);
    // }
}

fn print_u8_buf(buf: &mut Vec<u8>, options: &getopts::Matches) {
    let o = convert_buf_to_codepoint(buf);
    match char::from_u32(o) {
        Some(c) => print!("{}", c),
        None => {
            for b in buf.iter() {
                print_byte(b, options);
            }
        }

    }
}

fn convert_buf_to_codepoint(buf: &mut Vec<u8>) -> u32 {
    let mut s = 0u32;
    let mut l = buf.len();
    let orig_l = l;
    for b in buf.iter() {
        if l == 4 {
            s = s + ((*b as u32 | 240) - 240) << 19;
        }
        else if l == 3 {
            s = s + ((*b as u32 | 224) - 224) << 12
        }
        else if l == 2 {
            s = s + (((*b as u32 | 192) - 192) << 6);
        }
        else if l == 1 {
            if orig_l > 1 {
                s = s + ((*b as u32 | 128) - 128);
            }
            else {
                s = s + ((*b as u32 | 192) - 192);
            }
        }
        l = l - 1;
    }
    s
}

fn is_empty(line: &String) -> bool {
    let newline_str = "\n".to_string();
    let crlf_str = "\r\n".to_string();
    if line.is_empty() {
        true
    }
    else if line.eq(&newline_str) || line.eq(&crlf_str) {
        true
    }
    else {
        false
    }
}

fn is_empty_out_buf(v: &Vec<u8>) -> bool {
    if v.len() > 1 {
        false
    }
    else if is_nl(&v[0]) {
        true
    }
    else {
        false
    }
}

fn is_nl(c: &u8) -> bool {
    *c == 10u8
}

fn print_byte(b: &u8, options: &getopts::Matches) {
    if (*b > 31 && *b < 127) || *b == 10 || *b == 9 {
        if options.opt_present("t") && *b == 9 {
            print_tab();
        }
        else {
            print!("{}", *b as char);
        }
    }
    else {
        if options.opt_present("v") || options.opt_present("t") {
            if *b < 32 {
                print!("^{}", (*b + 64) as char);
            }
            else if *b == 127 {
                // del char
                print!("^?");
            }
            else if *b > 127 {
                if *b == 255 {
                    print!("M-^?");
                }
                else {
                    let x = *b - 128;
                    if x < 32 {
                        print!("M-^{}", (x + 64) as char);
                    }
                    else {
                        print!("M-{}", (*b - 128) as char);
                    }
                }
            }
        }
    }
}

fn print_tab() {
    print!("^I");
}

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

    #[test]
    fn assert_is_empty() {
        let s = "".to_string();
        assert!(is_empty(&s));
    }
    #[test]
    fn assert_is_empty_newline() {
        let s = "\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_crlf() {
        let s = "\r\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_char() {
        let s = "d".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_is_empty_ctrl_char() {
        let s = "".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_buf_to_codepoint_24() {
        let mut b = vec![24u8];
        assert_eq!(convert_buf_to_codepoint(&mut b), 24u32);
    }

    #[test]
    fn assert_buf_to_codepoint_36() {
        let mut b = vec![164u8];
        assert_eq!(convert_buf_to_codepoint(&mut b), 36);
    }

    #[test]
    fn assert_buf_to_codepoint_162() {
        // ¢
        // C2 A2
        // 11000010 10100010
        // 00010100010
        let mut b = vec![194u8, 162];
        assert_eq!(convert_buf_to_codepoint(&mut b), 162);
    }

    #[test]
    fn assert_buf_to_codepoint_8364() {
        // €
        // E2 82 AC
        // 11100010 10000010 10101100
        // 0010000010101100
        let mut b = vec![226u8, 130, 172];
        assert_eq!(convert_buf_to_codepoint(&mut b), 8364);
    }

    #[test]
    fn assert_buf_to_codepoint_294() {
        // c4 a6
        // 11000100 10100110
        // 00100100110
        let mut b = vec![196u8, 166];
        assert_eq!(convert_buf_to_codepoint(&mut b), 294);
    }

    #[test]
    fn assert_buf_to_codepoint_66376() {
        // F0 90 8D 88
        // 11110000 10010000 10001101 10001000
        // 00001 00000011 01001000
        let mut b = vec![240u8, 144, 141, 136];
        assert_eq!(convert_buf_to_codepoint(&mut b), 66376);
    }

}
<commit_msg>wip, main test still fails<commit_after>extern crate getopts;
use getopts::{optflag,getopts,OptGroup,usage};
use std::os;

use std::num::FromPrimitive;
use std::num::Int;
use std::char;
use std::old_io;
use std::old_io::{IoResult, IoError};
use std::old_io::BufferedReader;
use std::old_io::File;
use std::old_io::stdio;

pub fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", usage(brief.as_slice(), opts));
}

pub fn cat(v: &Vec<String>, options: &getopts::Matches) {
    if options.opt_present("u") {
        let writer = Box::new(stdio::stdout_raw());
        stdio::set_stdout(writer);
    }
    if v.is_empty() {
        cat_stdin(options);
    }
    else {
        // read files
        cat_files(v, options);
    }
}

fn cat_files(v: &Vec<String>, options: &getopts::Matches) {
    let mut linenum = 1u32;
    for filename in v.iter() {
        let path = Path::new(filename);
        match File::open(&path) {
            Ok(fh) => {
                let mut file = BufferedReader::new(fh);
                linenum = cat_file(file, options, linenum);
            },
            Err(f) => {
                println!("{}", f);
            }
        }
    }
}

fn cat_stdin(options: &getopts::Matches) {
    let mut linenum = 1u32;
    let mut printempty: bool = false;
    for line in old_io::stdin().lock().lines() {
        let (a, b) = handle_line(line.unwrap(), &mut printempty, linenum, options);
        printempty = a;
        linenum = b;
    }
}

fn cat_file<'a>(
    mut file: old_io::BufferedReader<std::old_io::fs::File>,
    options: &getopts::Matches,
    mut linenum: u32,
    ) -> u32 {
    let mut printempty: bool = false;
    let mut read_buf = [0, 4096];
    let mut out_buf: Vec<u8> = vec![];
    loop {
        match file.read(&mut read_buf) {
            Ok(n) => {
                for c in read_buf[..n].iter() {
                    out_buf.push(*c);
                    if is_nl(c) {
                        let (a, b) = handle_buf(&out_buf, &mut printempty, linenum, options);
                        printempty = a;
                        linenum = b;
                        out_buf.clear();
                    }
                }
            },
            Err(f) => {
                let mut o = 0u32;
                if out_buf.len() > 0 {
                    handle_buf(&out_buf, &mut printempty, linenum, options);
                }
                break
            }
        }
    }
    linenum
}

fn handle_line<'a>(
    linestr: String,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty(&linestr) {
            if *printempty == true {
                println!("");
            }
            linenum = print_string(&linestr, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_string(&linestr, linenum, options);
    }
    (*printempty, linenum)
}

fn handle_buf<'a>(
    out_buf: &Vec<u8>,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty_out_buf(out_buf) {
            if *printempty == true {
                if options.opt_present("n") {
                    println!("     {}\t", linenum);
                    linenum = linenum + 1;
                }
                else {
                    println!("");
                }
            }
            linenum = print_buf(&out_buf, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_buf(&out_buf, linenum, options);
    }
    (*printempty, linenum)
}

fn print_string<'a>(s: &String, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty(s) {
            print_numbered(s, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered(s, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered(s, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered(s, options);
    }
    linenum
}

fn print_buf<'a>(out_buf: &Vec<u8>, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty_out_buf(out_buf) {
            print_numbered_buf(out_buf, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered_buf(out_buf, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered_buf(out_buf, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered_buf(out_buf, options);
    }
    linenum
}

fn print_numbered<'a>(s: &String, linenum: u32, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("     {}\t{}", linenum, s);
    }
}

fn print_numbered_buf<'a>(out_buf: &Vec<u8>, linenum: u32, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        let mut t = 0u32;
        for b in out_buf.iter() {
            if t > 0 {
                t = t + *b as u32;
                // print!("t: {} ", t);
                print!("{}", char::from_u32(t).unwrap());
                t = 0;
            }
            else {
                if *b > 160 {
                    t = *b as u32;
                }
                else {
                    print_byte(b, options);
                }
            }
        }
    // }
}

fn print_unnumbered(s: &String, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("{}", s);
    }
}

fn print_unnumbered_buf(out_buf: &Vec<u8>, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        let mut t = 0;
        let mut buf: Vec<u8> = vec![];
        for b in out_buf.iter() {
            if t > 0 {
                buf.push(*b);
                t = t - 1;
                if t == 0 {
                    print_u8_buf(&mut buf, options);
                    buf.clear();
                }
            }
            else {
                if *b >= 240 {
                    //4th byte
                    t = 3;
                    buf.push(*b);
                }
                else if *b >= 224 {
                    t = 2;
                    buf.push(*b);
                }
                else if *b >= 192 {
                    t = 1;
                    buf.push(*b);
                }
                else {
                    print_byte(b, options);
                }
            }
        }
    // }
    // else {
        // print!("{}", s);
    // }
}

fn print_u8_buf(buf: &mut Vec<u8>, options: &getopts::Matches) {
    match convert_buf_to_codepoint(buf) {
        Ok(codepoint) => {
            match char::from_u32(codepoint) {
                Some(c) => print!("{}", c),
                None => {
                    for b in buf.iter() {
                        print_byte(b, options);
                    }
                }

            }
        },
        Err(_) => {
            for b in buf.iter() {
                print_byte(b, options);
            }
        }
    }
}

fn convert_buf_to_codepoint(buf: &mut Vec<u8>) -> Result<u32, String> {
    let mut s = 0u32;
    let mut l = buf.len();
    let orig_l = l;
    for b in buf.iter() {
        if l == 4 {
            s = s + ((*b as u32 | 240) - 240) << 19;
        }
        else if l == 3 {
            if orig_l == 4 && *b > 191 {
                return Err("Couldn't parse".to_string());
            }
            else {
                s = s + ((*b as u32 | 224) - 224) << 12;
            }
        }
        else if l == 2 {
            if (orig_l == 4 || orig_l == 3) && *b > 191 {
                return Err("Couldn't parse".to_string());
            }
            else {
                s = s + (((*b as u32 | 192) - 192) << 6);
            }
        }
        else if l == 1 {
            if orig_l > 1 {
                s = s + ((*b as u32 | 128) - 128);
            }
            else {
                s = s + ((*b as u32 | 192) - 192);
            }
        }
        l = l - 1;
    }
    Ok(s)
}

fn is_empty(line: &String) -> bool {
    let newline_str = "\n".to_string();
    let crlf_str = "\r\n".to_string();
    if line.is_empty() {
        true
    }
    else if line.eq(&newline_str) || line.eq(&crlf_str) {
        true
    }
    else {
        false
    }
}

fn is_empty_out_buf(v: &Vec<u8>) -> bool {
    if v.len() > 1 {
        false
    }
    else if is_nl(&v[0]) {
        true
    }
    else {
        false
    }
}

fn is_nl(c: &u8) -> bool {
    *c == 10u8
}

fn print_byte(b: &u8, options: &getopts::Matches) {
    if (*b > 31 && *b < 127) || *b == 10 || *b == 9 {
        if options.opt_present("t") && *b == 9 {
            print_tab();
        }
        else {
            print!("{}", *b as char);
        }
    }
    else {
        if options.opt_present("v") || options.opt_present("t") {
            if *b < 32 {
                print!("^{}", (*b + 64) as char);
            }
            else if *b == 127 {
                // del char
                print!("^?");
            }
            else if *b > 127 {
                if *b == 255 {
                    print!("M-^?");
                }
                else {
                    let x = *b - 128;
                    if x < 32 {
                        print!("M-^{}", (x + 64) as char);
                    }
                    else {
                        print!("M-{}", (*b - 128) as char);
                    }
                }
            }
        }
    }
}

fn print_tab() {
    print!("^I");
}

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

    #[test]
    fn assert_is_empty() {
        let s = "".to_string();
        assert!(is_empty(&s));
    }
    #[test]
    fn assert_is_empty_newline() {
        let s = "\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_crlf() {
        let s = "\r\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_char() {
        let s = "d".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_is_empty_ctrl_char() {
        let s = "".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_buf_to_codepoint_24() {
        let mut b = vec![24u8];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 24u32);
    }

    #[test]
    fn assert_buf_to_codepoint_36() {
        let mut b = vec![164u8];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 36);
    }

    #[test]
    fn assert_buf_to_codepoint_162() {
        // ¢
        // C2 A2
        // 11000010 10100010
        // 00010100010
        let mut b = vec![194u8, 162];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 162);
    }

    #[test]
    fn assert_buf_to_codepoint_8364() {
        // €
        // E2 82 AC
        // 11100010 10000010 10101100
        // 0010000010101100
        let mut b = vec![226u8, 130, 172];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 8364);
    }

    #[test]
    fn assert_buf_to_codepoint_294() {
        // c4 a6
        // 11000100 10100110
        // 00100100110
        let mut b = vec![196u8, 166];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 294);
    }

    #[test]
    fn assert_buf_to_codepoint_66376() {
        // F0 90 8D 88
        // 11110000 10010000 10001101 10001000
        // 00001 00000011 01001000
        let mut b = vec![240u8, 144, 141, 136];
        assert_eq!(convert_buf_to_codepoint(&mut b).unwrap(), 66376);
    }

}
<|endoftext|>


<commit_before>#![crate_name = "rustless"]
#![crate_type = "rlib"]
#![feature(plugin)]
#![feature(collections)]
#![feature(core)]
#![feature(io)]
#![feature(std_misc)]
#![feature(env)]
#![feature(path)]
// #![deny(warnings)]
#![deny(bad_style)]

#[plugin] #[no_link]
extern crate regex_macros;
extern crate regex;
extern crate hyper;
extern crate "rustc-serialize" as serialize;
extern crate url;
extern crate error;
extern crate cookie;

extern crate iron;
extern crate typemap;
extern crate plugin;

extern crate collections;
extern crate valico;
extern crate queryst;
extern crate jsonway;

#[macro_use]
extern crate log;

#[macro_use] #[no_link]
extern crate mopa;

pub use backend::{Request, SimpleRequest, Response, Handler, HandleResult, HandleSuccessResult};
pub use errors::{ErrorResponse};
pub use framework::{
    Endpoint, Client, Api, Application, Namespace, Nesting, Media, Versioning
};

pub mod prelude {
    pub use {Nesting, Extensible};
}

pub trait Extensible {
    fn ext(&self) -> &::typemap::TypeMap;
    fn ext_mut(&mut self) -> &mut ::typemap::TypeMap;
}

macro_rules! impl_extensible {
    ($t:ty) => (
        impl $crate::Extensible for $t {
            fn ext(&self) -> &::typemap::TypeMap { &self.ext }
            fn ext_mut(&mut self) -> &mut ::typemap::TypeMap { &mut self.ext }
        }
    )
}

#[macro_use] pub mod errors;
#[macro_use] pub mod backend;
pub mod server;
pub mod framework;
pub mod batteries;<commit_msg>(fix) use new plugin syntax<commit_after>#![crate_name = "rustless"]
#![crate_type = "rlib"]
#![feature(plugin)]
#![feature(collections)]
#![feature(core)]
#![feature(io)]
#![feature(std_misc)]
#![feature(env)]
#![feature(path)]
// #![deny(warnings)]
#![deny(bad_style)]

#![plugin(regex_macros)]
extern crate regex_macros;
extern crate regex;
extern crate hyper;
extern crate "rustc-serialize" as serialize;
extern crate url;
extern crate error;
extern crate cookie;

extern crate iron;
extern crate typemap;
extern crate plugin;

extern crate collections;
extern crate valico;
extern crate queryst;
extern crate jsonway;

#[macro_use]
extern crate log;

#[macro_use] #[no_link]
extern crate mopa;

pub use backend::{Request, SimpleRequest, Response, Handler, HandleResult, HandleSuccessResult};
pub use errors::{ErrorResponse};
pub use framework::{
    Endpoint, Client, Api, Application, Namespace, Nesting, Media, Versioning
};

pub mod prelude {
    pub use {Nesting, Extensible};
}

pub trait Extensible {
    fn ext(&self) -> &::typemap::TypeMap;
    fn ext_mut(&mut self) -> &mut ::typemap::TypeMap;
}

macro_rules! impl_extensible {
    ($t:ty) => (
        impl $crate::Extensible for $t {
            fn ext(&self) -> &::typemap::TypeMap { &self.ext }
            fn ext_mut(&mut self) -> &mut ::typemap::TypeMap { &mut self.ext }
        }
    )
}

#[macro_use] pub mod errors;
#[macro_use] pub mod backend;
pub mod server;
pub mod framework;
pub mod batteries;<|endoftext|>


<commit_before>//! indicatif is a library for Rust that helps you build command line
//! interfaces that report progress to users.  It comes with various
//! tools and utilities for formatting anything that indicates progress.
//!
//! Platform support:
//!
//! * Linux
//! * OS X
//! * Windows (colors require Windows 10)
//!
//! Best paired with other libraries in the family:
//!
//! * [console](https://docs.rs/console)
//! * [dialoguer](https://docs.rs/dialoguer)
//!
//! # Crate Contents
//!
//! * **Progress bars**
//!   * [`ProgressBar`](struct.ProgressBar.html) for bars and spinners
//!   * [`MultiProgress`](struct.MultiProgress.html) for multiple bars
//! * **Data Formatting**
//!   * [`HumanBytes`](struct.HumanBytes.html) for formatting bytes
//!   * [`DecimalBytes`](struct.DecimalBytes.html) for formatting bytes using SI prefixes
//!   * [`BinaryBytes`](struct.BinaryBytes.html) for formatting bytes using ISO/IEC prefixes
//!   * [`HumanDuration`](struct.HumanDuration.html) for formatting durations
//!
//! # Progress Bars and Spinners
//!
//! indicatif comes with a `ProgressBar` type that supports both bounded
//! progress bar uses as well as unbounded "spinner" type progress reports.
//! Progress bars are `Sync` and `Send` objects which means that they are
//! internally locked and can be passed from thread to thread.
//!
//! Additionally a `MultiProgress` utility is provided that can manage
//! rendering multiple progress bars at once (eg: from multiple threads).
//!
//! To whet your appetite, this is what this can look like:
//!
//!
//!
//! Progress bars are manually advanced and by default draw to stderr.
//! When you are done, the progress bar can be finished either visibly
//! (eg: the progress bar stays on the screen) or cleared (the progress
//! bar will be removed).
//!
//! ```rust
//! use indicatif::ProgressBar;
//!
//! let bar = ProgressBar::new(1000);
//! for _ in 0..1000 {
//!     bar.inc(1);
//!     // ...
//! }
//! bar.finish();
//! ```
//!
//! General progress bar behaviors:
//!
//! * if a non terminal is detected the progress bar will be completely
//!   hidden.  This makes piping programs to logfiles make sense out of
//!   the box.
//! * a progress bar only starts drawing when `set_message`, `inc`, `set_position`
//!   or `tick` are called.  In some situations you might have to call `tick`
//!   once to draw it.
//! * progress bars should be explicitly finished to reset the rendering
//!   for others.  Either by also clearing them or by replacing them with
//!   a new message / retaining the current message.
//! * the default template renders neither message nor prefix.
//!
//! # Iterators
//!
//! Similar to [tqdm](https://github.com/tqdm/tqdm), progress bars can be
//! associated with an iterator. For example:
//!
//! ```rust
//! use indicatif::ProgressIterator;
//!
//! for _ in (0..1000).progress() {
//!     // ...
//! }
//! ```
//!
//! See the [`ProgressIterator`](trait.ProgressIterator.html) trait for more
//! methods to configure the number of elements in the iterator or change
//! the progress bar style. Indicatif also has optional support for parallel
//! iterators with [Rayon](https://github.com/rayon-rs/rayon). In your
//! `Cargo.toml`, use the "rayon" feature:
//!
//! ```toml
//! [dependencies]
//! indicatif = {version = "*", features = ["rayon"]}
//! ```
//!
//! And then use it like this:
//!
//! ```rust,ignore
//! # extern crate rayon;
//! use indicatif::ParallelProgressIterator;
//! use rayon::iter::{ParallelIterator, IntoParallelRefIterator};
//!
//! let v: Vec<_> = (0..100000).collect();
//! let v2: Vec<_> = v.par_iter().progress_count(v.len() as u64).map(|i| i + 1).collect();
//! assert_eq!(v2[0], 1);
//! ```
//!
//! Or if you'd like to customize the progress bar:
//!
//! ```rust,ignore
//! # extern crate rayon;
//! use indicatif::{ProgressBar, ParallelProgressIterator, ProgressStyle};
//! use rayon::iter::{ParallelIterator, IntoParallelRefIterator};
//!
//! // Alternatively, use `ProgressBar::new().with_style()`
//! let style = ProgressStyle::default_bar();
//! let v: Vec<_> = (0..100000).collect();
//! let v2: Vec<_> = v.par_iter().progress_with_style(style).map(|i| i + 1).collect();
//! assert_eq!(v2[0], 1);
//! ```
//!
//! # Templates
//!
//! Progress bars can be styled with simple format strings similar to the
//! ones in Rust itself.  The format for a placeholder is `{key:options}`
//! where the `options` part is optional.  If provided the format is this:
//!
//! ```text
//! [<^>]           for an optional alignment specification
//! WIDTH           an optional width as positive integer
//! !               an optional exclamation mark to enable truncation
//! .STYLE          an optional dot separated style string
//! /STYLE          an optional dot separated alternative style string
//! ```
//!
//! For the style component see [`Style::from_dotted_str`](https://docs.rs/console/0.7.5/console/struct.Style.html#method.from_dotted_str)
//! for more information.  Indicatif uses the `console` base crate for all
//! colorization and formatting options.
//!
//! Some examples for templates:
//!
//! ```text
//! [{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}
//! ```
//!
//! This sets a progress bar that is 40 characters wide and has cyan
//! as primary style color and blue as alternative style color.
//! Alternative styles are currently only used for progress bars.
//!
//! Example configuration:
//!
//! ```rust
//! # use indicatif::{ProgressBar, ProgressStyle};
//! # let bar = ProgressBar::new(0);
//! bar.set_style(ProgressStyle::default_bar()
//!     .template("[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}")
//!     .progress_chars("##-"));
//! ```
//!
//! The following keys exist:
//!
//! * `bar`: renders a progress bar. By default 20 characters wide.  The
//!   style string is used to color the elapsed part, the alternative
//!   style is used for the bar that is yet to render.
//! * `wide_bar`: like `bar` but always fills the remaining space.
//! * `spinner`: renders the spinner (current tick string).
//! * `prefix`: renders the prefix set on the progress bar.
//! * `msg`: renders the currently set message on the progress bar.
//! * `wide_msg`: like `msg` but always fills the remaining space and truncates.
//! * `pos`: renders the current position of the bar as integer
//! * `len`: renders the total length of the bar as integer
//! * `bytes`: renders the current position of the bar as bytes.
//! * `percent`: renders the current position of the bar as a percentage of the total length.
//! * `total_bytes`: renders the total length of the bar as bytes.
//! * `elapsed_precise`: renders the elapsed time as `HH:MM:SS`.
//! * `elapsed`: renders the elapsed time as `42s`, `1m` etc.
//! * `per_sec`: renders the speed in steps per second.
//! * `bytes_per_sec`: renders the speed in bytes per second.
//! * `binary_bytes_per_sec`: renders the speed in bytes per second using
//!   power-of-two units, i.e. `MiB`, `KiB`, etc.
//! * `eta_precise`: the remaining time (like `elapsed_precise`).
//! * `eta`: the remaining time (like `elapsed`).
//! * `duration_precise`: the extrapolated total duration (like `elapsed_precise`).
//! * `duration`: the extrapolated total duration time (like `elapsed`).

//!
//! The design of the progress bar can be altered with the integrated
//! template functionality.  The template can be set by changing a
//! `ProgressStyle` and attaching it to the progress bar.
//!
//! # Human Readable Formatting
//!
//! There are some formatting wrappers for showing elapsed time and
//! file sizes for human users:
//!
//! ```rust
//! # use std::time::Duration;
//! use indicatif::{HumanDuration, HumanBytes};
//!
//! assert_eq!("3.00MiB", HumanBytes(3*1024*1024).to_string());
//! assert_eq!("8 seconds", HumanDuration(Duration::from_secs(8)).to_string());
//! ```
//!
//! # Feature Flags
//!
//! * `rayon`: adds rayon support
//! * `improved_unicode`: adds improved unicode support (graphemes, better width calculation)

mod draw_target;
mod format;
mod iter;
mod progress_bar;
#[cfg(feature = "rayon")]
mod rayon;
mod state;
mod style;

pub use crate::draw_target::{MultiProgressAlignment, ProgressDrawTarget};
pub use crate::format::{BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanDuration};
pub use crate::iter::{ProgressBarIter, ProgressIterator};
pub use crate::progress_bar::{MultiProgress, ProgressBar, WeakProgressBar};
pub use crate::style::{ProgressFinish, ProgressStyle};

#[cfg(feature = "rayon")]
pub use crate::rayon::ParallelProgressIterator;
<commit_msg>Document interaction between `wide_bar` and `wide_msg`<commit_after>//! indicatif is a library for Rust that helps you build command line
//! interfaces that report progress to users.  It comes with various
//! tools and utilities for formatting anything that indicates progress.
//!
//! Platform support:
//!
//! * Linux
//! * OS X
//! * Windows (colors require Windows 10)
//!
//! Best paired with other libraries in the family:
//!
//! * [console](https://docs.rs/console)
//! * [dialoguer](https://docs.rs/dialoguer)
//!
//! # Crate Contents
//!
//! * **Progress bars**
//!   * [`ProgressBar`](struct.ProgressBar.html) for bars and spinners
//!   * [`MultiProgress`](struct.MultiProgress.html) for multiple bars
//! * **Data Formatting**
//!   * [`HumanBytes`](struct.HumanBytes.html) for formatting bytes
//!   * [`DecimalBytes`](struct.DecimalBytes.html) for formatting bytes using SI prefixes
//!   * [`BinaryBytes`](struct.BinaryBytes.html) for formatting bytes using ISO/IEC prefixes
//!   * [`HumanDuration`](struct.HumanDuration.html) for formatting durations
//!
//! # Progress Bars and Spinners
//!
//! indicatif comes with a `ProgressBar` type that supports both bounded
//! progress bar uses as well as unbounded "spinner" type progress reports.
//! Progress bars are `Sync` and `Send` objects which means that they are
//! internally locked and can be passed from thread to thread.
//!
//! Additionally a `MultiProgress` utility is provided that can manage
//! rendering multiple progress bars at once (eg: from multiple threads).
//!
//! To whet your appetite, this is what this can look like:
//!
//!
//!
//! Progress bars are manually advanced and by default draw to stderr.
//! When you are done, the progress bar can be finished either visibly
//! (eg: the progress bar stays on the screen) or cleared (the progress
//! bar will be removed).
//!
//! ```rust
//! use indicatif::ProgressBar;
//!
//! let bar = ProgressBar::new(1000);
//! for _ in 0..1000 {
//!     bar.inc(1);
//!     // ...
//! }
//! bar.finish();
//! ```
//!
//! General progress bar behaviors:
//!
//! * if a non terminal is detected the progress bar will be completely
//!   hidden.  This makes piping programs to logfiles make sense out of
//!   the box.
//! * a progress bar only starts drawing when `set_message`, `inc`, `set_position`
//!   or `tick` are called.  In some situations you might have to call `tick`
//!   once to draw it.
//! * progress bars should be explicitly finished to reset the rendering
//!   for others.  Either by also clearing them or by replacing them with
//!   a new message / retaining the current message.
//! * the default template renders neither message nor prefix.
//!
//! # Iterators
//!
//! Similar to [tqdm](https://github.com/tqdm/tqdm), progress bars can be
//! associated with an iterator. For example:
//!
//! ```rust
//! use indicatif::ProgressIterator;
//!
//! for _ in (0..1000).progress() {
//!     // ...
//! }
//! ```
//!
//! See the [`ProgressIterator`](trait.ProgressIterator.html) trait for more
//! methods to configure the number of elements in the iterator or change
//! the progress bar style. Indicatif also has optional support for parallel
//! iterators with [Rayon](https://github.com/rayon-rs/rayon). In your
//! `Cargo.toml`, use the "rayon" feature:
//!
//! ```toml
//! [dependencies]
//! indicatif = {version = "*", features = ["rayon"]}
//! ```
//!
//! And then use it like this:
//!
//! ```rust,ignore
//! # extern crate rayon;
//! use indicatif::ParallelProgressIterator;
//! use rayon::iter::{ParallelIterator, IntoParallelRefIterator};
//!
//! let v: Vec<_> = (0..100000).collect();
//! let v2: Vec<_> = v.par_iter().progress_count(v.len() as u64).map(|i| i + 1).collect();
//! assert_eq!(v2[0], 1);
//! ```
//!
//! Or if you'd like to customize the progress bar:
//!
//! ```rust,ignore
//! # extern crate rayon;
//! use indicatif::{ProgressBar, ParallelProgressIterator, ProgressStyle};
//! use rayon::iter::{ParallelIterator, IntoParallelRefIterator};
//!
//! // Alternatively, use `ProgressBar::new().with_style()`
//! let style = ProgressStyle::default_bar();
//! let v: Vec<_> = (0..100000).collect();
//! let v2: Vec<_> = v.par_iter().progress_with_style(style).map(|i| i + 1).collect();
//! assert_eq!(v2[0], 1);
//! ```
//!
//! # Templates
//!
//! Progress bars can be styled with simple format strings similar to the
//! ones in Rust itself.  The format for a placeholder is `{key:options}`
//! where the `options` part is optional.  If provided the format is this:
//!
//! ```text
//! [<^>]           for an optional alignment specification
//! WIDTH           an optional width as positive integer
//! !               an optional exclamation mark to enable truncation
//! .STYLE          an optional dot separated style string
//! /STYLE          an optional dot separated alternative style string
//! ```
//!
//! For the style component see [`Style::from_dotted_str`](https://docs.rs/console/0.7.5/console/struct.Style.html#method.from_dotted_str)
//! for more information.  Indicatif uses the `console` base crate for all
//! colorization and formatting options.
//!
//! Some examples for templates:
//!
//! ```text
//! [{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}
//! ```
//!
//! This sets a progress bar that is 40 characters wide and has cyan
//! as primary style color and blue as alternative style color.
//! Alternative styles are currently only used for progress bars.
//!
//! Example configuration:
//!
//! ```rust
//! # use indicatif::{ProgressBar, ProgressStyle};
//! # let bar = ProgressBar::new(0);
//! bar.set_style(ProgressStyle::default_bar()
//!     .template("[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}")
//!     .progress_chars("##-"));
//! ```
//!
//! The following keys exist:
//!
//! * `bar`: renders a progress bar. By default 20 characters wide.  The
//!   style string is used to color the elapsed part, the alternative
//!   style is used for the bar that is yet to render.
//! * `wide_bar`: like `bar` but always fills the remaining space. It should not be used with
//! `wide_msg`.
//! * `spinner`: renders the spinner (current tick string).
//! * `prefix`: renders the prefix set on the progress bar.
//! * `msg`: renders the currently set message on the progress bar.
//! * `wide_msg`: like `msg` but always fills the remaining space and truncates. It should not be used
//! with `wide_bar`.
//! * `pos`: renders the current position of the bar as integer
//! * `len`: renders the total length of the bar as integer
//! * `bytes`: renders the current position of the bar as bytes.
//! * `percent`: renders the current position of the bar as a percentage of the total length.
//! * `total_bytes`: renders the total length of the bar as bytes.
//! * `elapsed_precise`: renders the elapsed time as `HH:MM:SS`.
//! * `elapsed`: renders the elapsed time as `42s`, `1m` etc.
//! * `per_sec`: renders the speed in steps per second.
//! * `bytes_per_sec`: renders the speed in bytes per second.
//! * `binary_bytes_per_sec`: renders the speed in bytes per second using
//!   power-of-two units, i.e. `MiB`, `KiB`, etc.
//! * `eta_precise`: the remaining time (like `elapsed_precise`).
//! * `eta`: the remaining time (like `elapsed`).
//! * `duration_precise`: the extrapolated total duration (like `elapsed_precise`).
//! * `duration`: the extrapolated total duration time (like `elapsed`).

//!
//! The design of the progress bar can be altered with the integrated
//! template functionality.  The template can be set by changing a
//! `ProgressStyle` and attaching it to the progress bar.
//!
//! # Human Readable Formatting
//!
//! There are some formatting wrappers for showing elapsed time and
//! file sizes for human users:
//!
//! ```rust
//! # use std::time::Duration;
//! use indicatif::{HumanDuration, HumanBytes};
//!
//! assert_eq!("3.00MiB", HumanBytes(3*1024*1024).to_string());
//! assert_eq!("8 seconds", HumanDuration(Duration::from_secs(8)).to_string());
//! ```
//!
//! # Feature Flags
//!
//! * `rayon`: adds rayon support
//! * `improved_unicode`: adds improved unicode support (graphemes, better width calculation)

mod draw_target;
mod format;
mod iter;
mod progress_bar;
#[cfg(feature = "rayon")]
mod rayon;
mod state;
mod style;

pub use crate::draw_target::{MultiProgressAlignment, ProgressDrawTarget};
pub use crate::format::{BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanDuration};
pub use crate::iter::{ProgressBarIter, ProgressIterator};
pub use crate::progress_bar::{MultiProgress, ProgressBar, WeakProgressBar};
pub use crate::style::{ProgressFinish, ProgressStyle};

#[cfg(feature = "rayon")]
pub use crate::rayon::ParallelProgressIterator;
<|endoftext|>


<commit_before>extern crate graphics;
extern crate input;

use graphics::{ Context, Graphics };
use input::{ GenericEvent };

mod drawutils;

pub struct Timeline {
    pub frames: u32,
    pub current_frame: u32,
    pub hover_frame: Option<u32>,
    pub start_frame: u32,
    pub bounds: [u32; 4],
    pub settings: TimelineSettings,
    pub hover_goto_start: bool,
    pub hover_goto_end: bool,
}

pub struct TimelineSettings {
    pub left_to_frame: f64,
    pub right_to_frame: f64,
    pub top_to_frame: f64,
    pub frame_size: [f64; 2],
    pub frame_offset_x: f64,
    pub left_to_goto_start: f64,
    pub right_to_goto_end: f64,
    pub lift_hover_frame: f64,
}

pub struct ComputedTimelineSettings {
    pub width_for_frames: f64,
    pub max_visible_frames: u32,
    pub end_frame: u32,
}

impl TimelineSettings {
    pub fn new() -> TimelineSettings {
        TimelineSettings {
            left_to_frame: 20.0,
            right_to_frame: 20.0,
            top_to_frame: 15.0,
            frame_size: [10.0, 10.0],
            frame_offset_x: 5.0,
            left_to_goto_start: 5.0,
            right_to_goto_end: 5.0,
            lift_hover_frame: 10.0,
        }
    }
}

impl ComputedTimelineSettings {
    pub fn new(timeline: &Timeline, settings: &TimelineSettings)
        -> ComputedTimelineSettings
    {
        use std::cmp::min;

        let width_for_frames = timeline.bounds[2] as f64
            - settings.left_to_frame - settings.right_to_frame;
        let max_visible_frames: u32 =
            if width_for_frames < settings.frame_size[0] {
                0
            } else {
                1
                + (
                    (width_for_frames - settings.frame_size[0])
                    / (settings.frame_size[0] + settings.frame_offset_x)
                ) as u32
            };
        let end_frame = min(
            timeline.frames,
            timeline.start_frame + max_visible_frames
        );

        ComputedTimelineSettings {
            width_for_frames: width_for_frames,
            max_visible_frames: max_visible_frames,
            end_frame: end_frame
        }
    }
}

impl Timeline {
    pub fn new_frames_bounds(frames: u32, bounds: [u32; 4]) -> Timeline {
        Timeline {
            frames: frames,
            current_frame: 0,
            hover_frame: None,
            start_frame: 0,
            bounds: bounds,
            settings: TimelineSettings::new(),
            hover_goto_start: false,
            hover_goto_end: false,
        }
    }

    pub fn event<E: GenericEvent>(&mut self, e: &E) {
        use input::{ MouseCursorEvent, PressEvent };

        if let Some(pos) = e.mouse_cursor_args() {
            // Detect hover frame.
            {
                let computed_settings = ComputedTimelineSettings::new(self,
                    &self.settings);

                let left_to_frame: f64 = self.settings.left_to_frame;
                let frame_width: f64 = self.settings.frame_size[0];
                let frame_offset_x: f64 = self.settings.frame_offset_x;

                let end_frame: u32 = computed_settings.end_frame;

                let (x, y) = (pos[0], pos[1]);

                let left = self.bounds[0] as f64 + left_to_frame;
                let right = left + end_frame as f64 * (frame_width + frame_offset_x);
                let top = self.bounds[1] as f64;
                let bottom = top + self.bounds[3] as f64;

                if x < left || x > right
                || y < top || y > bottom {
                    self.hover_frame = None;
                } else {
                    let i: u32 = ((x - left) / (frame_width + frame_offset_x)) as u32;
                    self.hover_frame = Some(i);
                }
            }

            // Detect hover over goto start and goto end buttons.
            {
                let left_to_goto_start = self.settings.left_to_goto_start;
                let right_to_goto_end = self.settings.right_to_goto_end;
                let top_to_frame = self.settings.top_to_frame;
                let frame_width = self.settings.frame_size[0];
                let frame_height = self.settings.frame_size[1];

                let outside = |bounds: [f64; 4]| {
                    let (x, y) = (pos[0], pos[1]);
                    (x < bounds[0] || y < bounds[1]
                    || x > bounds[0] + bounds[2] || y > bounds[1] + bounds[3])
                };

                self.hover_goto_start = !outside([
                    self.bounds[0] as f64 + left_to_goto_start,
                    self.bounds[1] as f64 + top_to_frame,
                    frame_width,
                    frame_height
                ]);
                self.hover_goto_end = !outside([
                    self.bounds[0] as f64 + self.bounds[2] as f64
                        - right_to_goto_end - frame_width,
                    self.bounds[1] as f64 + top_to_frame,
                    frame_width,
                    frame_height
                ]);
            }
        }

        if let Some(button) = e.press_args() {
            use input::{ Button, MouseButton };

            if button == Button::Mouse(MouseButton::Left) {
                if self.hover_goto_start {
                    println!("TEST goto start");
                } else if self.hover_goto_end {
                    println!("TEST goto end");
                }
            }
        }
    }

    pub fn draw_timeline<G: Graphics>(&self, c: &Context, g: &mut G) {
        use std::cmp::min;

        let left_to_frame: f64 = self.settings.left_to_frame;
        let right_to_frame: f64 = self.settings.right_to_frame;
        let top_to_frame: f64 = self.settings.top_to_frame;
        let frame_width: f64 = self.settings.frame_size[0];
        let frame_height: f64 = self.settings.frame_size[1];
        let frame_offset_x: f64 = self.settings.frame_offset_x;
        let left_to_goto_start: f64 = self.settings.left_to_goto_start;
        let right_to_goto_end: f64 = self.settings.right_to_goto_end;
        let lift_hover_frame: f64 = self.settings.lift_hover_frame;

        let computed_settings = ComputedTimelineSettings::new(self, &self.settings);

        let slide_offset: f64 = 0.0;

        let width_for_frames = computed_settings.width_for_frames;
        let max_visible_frames: u32 = computed_settings.max_visible_frames;
        let end_frame = computed_settings.end_frame;

        let blue = [0.0, 0.0, 1.0, 1.0];
        let red = [1.0, 0.0, 0.0, 1.0];

        // Draw bounds to see where the control is.
        {
            use graphics::Rectangle;

            let bounds = [
                    self.bounds[0] as f64,
                    self.bounds[1] as f64,
                    self.bounds[2] as f64,
                    self.bounds[3] as f64
                ];
            Rectangle::new_border([0.0, 0.0, 1.0, 1.0], 0.5)
                .draw(bounds, &c.draw_state, c.transform, g);
        }

        // Draw a sequence of squares for each frame.
        {
            use graphics::Rectangle;

            let frame_bounds = |i: u32, lift: f64| [
                self.bounds[0] as f64 + left_to_frame
                    + i as f64 * (frame_width + frame_offset_x)
                    - slide_offset,
                self.bounds[1] as f64 + top_to_frame - lift,
                frame_width,
                frame_height
            ];

            let rect = Rectangle::new_border(blue, 0.5);
            for i in 0..end_frame - self.start_frame {
                // Don't draw the hover frame.
                if Some(i) == self.hover_frame { continue; }

                let bounds = frame_bounds(i, 0.0);
                rect.draw(bounds, &c.draw_state, c.transform, g);
            }

            if let Some(i) = self.hover_frame {
                let bounds = frame_bounds(i, lift_hover_frame);
                rect.draw(bounds, &c.draw_state, c.transform, g);
            }
        }

        // Draw navigate to start or end buttons.
        {
            use graphics::Line;
            use graphics::math::*;

            let line = Line::new([0.0, 0.0, 1.0, 1.0], 0.5);

            let at_beginning: bool = self.start_frame == 0;
            drawutils::draw_goto_end(
                at_beginning,
                [
                    self.bounds[0] as f64 + left_to_goto_start + frame_width,
                    self.bounds[1] as f64 + top_to_frame
                ],
                [
                    -frame_width * 0.5,
                    frame_height
                ],
                &Line::new(if self.hover_goto_start { red } else { blue }, 0.5),
                c, g
            );

            let at_end: bool = end_frame >= self.frames;
            drawutils::draw_goto_end(
                at_end,
                [
                    self.bounds[0] as f64 + self.bounds[2] as f64
                        - right_to_goto_end - frame_width,
                    self.bounds[1] as f64 + top_to_frame
                ],
                [
                    frame_width * 0.5,
                    frame_height
                ],
                &Line::new(if self.hover_goto_end { red } else { blue }, 0.5),
                c, g
            );
        }
    }

    pub fn draw_drag<G: Graphics>(&self, c: &Context, g: &mut G) {

    }
}
<commit_msg>Refactored to `Offset`<commit_after>extern crate graphics;
extern crate input;

use graphics::{ Context, Graphics };
use input::{ GenericEvent };

mod drawutils;

pub struct Timeline {
    pub frames: u32,
    pub current_frame: u32,
    pub hover_frame: Option<u32>,
    pub start_frame: u32,
    pub bounds: [u32; 4],
    pub settings: TimelineSettings,
    pub hover_goto_start: bool,
    pub hover_goto_end: bool,
}

pub struct TimelineSettings {
    pub offset: Offset,
    pub frame_size: [f64; 2],
    pub frame_offset_x: f64,
    pub left_to_goto_start: f64,
    pub right_to_goto_end: f64,
    pub lift_hover_frame: f64,
}

pub struct Offset {
    pub left: f64,
    pub right: f64,
    pub top: f64,
}

pub struct ComputedTimelineSettings {
    pub width_for_frames: f64,
    pub max_visible_frames: u32,
    pub end_frame: u32,
}

impl TimelineSettings {
    pub fn new() -> TimelineSettings {
        TimelineSettings {
            offset: Offset {
                left: 20.0, right: 20.0, top: 15.0,
            },
            frame_size: [10.0, 10.0],
            frame_offset_x: 5.0,
            left_to_goto_start: 5.0,
            right_to_goto_end: 5.0,
            lift_hover_frame: 10.0,
        }
    }
}

impl ComputedTimelineSettings {
    pub fn new(timeline: &Timeline, settings: &TimelineSettings)
        -> ComputedTimelineSettings
    {
        use std::cmp::min;

        let width_for_frames = timeline.bounds[2] as f64
            - settings.offset.left - settings.offset.right;
        let max_visible_frames: u32 =
            if width_for_frames < settings.frame_size[0] {
                0
            } else {
                1
                + (
                    (width_for_frames - settings.frame_size[0])
                    / (settings.frame_size[0] + settings.frame_offset_x)
                ) as u32
            };
        let end_frame = min(
            timeline.frames,
            timeline.start_frame + max_visible_frames
        );

        ComputedTimelineSettings {
            width_for_frames: width_for_frames,
            max_visible_frames: max_visible_frames,
            end_frame: end_frame
        }
    }
}

impl Timeline {
    pub fn new_frames_bounds(frames: u32, bounds: [u32; 4]) -> Timeline {
        Timeline {
            frames: frames,
            current_frame: 0,
            hover_frame: None,
            start_frame: 0,
            bounds: bounds,
            settings: TimelineSettings::new(),
            hover_goto_start: false,
            hover_goto_end: false,
        }
    }

    pub fn event<E: GenericEvent>(&mut self, e: &E) {
        use input::{ MouseCursorEvent, PressEvent };

        if let Some(pos) = e.mouse_cursor_args() {
            // Detect hover frame.
            {
                let computed_settings = ComputedTimelineSettings::new(self,
                    &self.settings);

                let left_to_frame: f64 = self.settings.offset.left;
                let frame_width: f64 = self.settings.frame_size[0];
                let frame_offset_x: f64 = self.settings.frame_offset_x;

                let end_frame: u32 = computed_settings.end_frame;

                let (x, y) = (pos[0], pos[1]);

                let left = self.bounds[0] as f64 + left_to_frame;
                let right = left + end_frame as f64 * (frame_width + frame_offset_x);
                let top = self.bounds[1] as f64;
                let bottom = top + self.bounds[3] as f64;

                if x < left || x > right
                || y < top || y > bottom {
                    self.hover_frame = None;
                } else {
                    let i: u32 = ((x - left) / (frame_width + frame_offset_x)) as u32;
                    self.hover_frame = Some(i);
                }
            }

            // Detect hover over goto start and goto end buttons.
            {
                let left_to_goto_start = self.settings.left_to_goto_start;
                let right_to_goto_end = self.settings.right_to_goto_end;
                let top_to_frame = self.settings.offset.top;
                let frame_width = self.settings.frame_size[0];
                let frame_height = self.settings.frame_size[1];

                let outside = |bounds: [f64; 4]| {
                    let (x, y) = (pos[0], pos[1]);
                    (x < bounds[0] || y < bounds[1]
                    || x > bounds[0] + bounds[2] || y > bounds[1] + bounds[3])
                };

                self.hover_goto_start = !outside([
                    self.bounds[0] as f64 + left_to_goto_start,
                    self.bounds[1] as f64 + top_to_frame,
                    frame_width,
                    frame_height
                ]);
                self.hover_goto_end = !outside([
                    self.bounds[0] as f64 + self.bounds[2] as f64
                        - right_to_goto_end - frame_width,
                    self.bounds[1] as f64 + top_to_frame,
                    frame_width,
                    frame_height
                ]);
            }
        }

        if let Some(button) = e.press_args() {
            use input::{ Button, MouseButton };

            if button == Button::Mouse(MouseButton::Left) {
                if self.hover_goto_start {
                    println!("TEST goto start");
                } else if self.hover_goto_end {
                    println!("TEST goto end");
                }
            }
        }
    }

    pub fn draw_timeline<G: Graphics>(&self, c: &Context, g: &mut G) {
        use std::cmp::min;

        let left_to_frame: f64 = self.settings.offset.left;
        let right_to_frame: f64 = self.settings.offset.right;
        let top_to_frame: f64 = self.settings.offset.top;
        let frame_width: f64 = self.settings.frame_size[0];
        let frame_height: f64 = self.settings.frame_size[1];
        let frame_offset_x: f64 = self.settings.frame_offset_x;
        let left_to_goto_start: f64 = self.settings.left_to_goto_start;
        let right_to_goto_end: f64 = self.settings.right_to_goto_end;
        let lift_hover_frame: f64 = self.settings.lift_hover_frame;

        let computed_settings = ComputedTimelineSettings::new(self, &self.settings);

        let slide_offset: f64 = 0.0;

        let width_for_frames = computed_settings.width_for_frames;
        let max_visible_frames: u32 = computed_settings.max_visible_frames;
        let end_frame = computed_settings.end_frame;

        let blue = [0.0, 0.0, 1.0, 1.0];
        let red = [1.0, 0.0, 0.0, 1.0];

        // Draw bounds to see where the control is.
        {
            use graphics::Rectangle;

            let bounds = [
                    self.bounds[0] as f64,
                    self.bounds[1] as f64,
                    self.bounds[2] as f64,
                    self.bounds[3] as f64
                ];
            Rectangle::new_border([0.0, 0.0, 1.0, 1.0], 0.5)
                .draw(bounds, &c.draw_state, c.transform, g);
        }

        // Draw a sequence of squares for each frame.
        {
            use graphics::Rectangle;

            let frame_bounds = |i: u32, lift: f64| [
                self.bounds[0] as f64 + left_to_frame
                    + i as f64 * (frame_width + frame_offset_x)
                    - slide_offset,
                self.bounds[1] as f64 + top_to_frame - lift,
                frame_width,
                frame_height
            ];

            let rect = Rectangle::new_border(blue, 0.5);
            for i in 0..end_frame - self.start_frame {
                // Don't draw the hover frame.
                if Some(i) == self.hover_frame { continue; }

                let bounds = frame_bounds(i, 0.0);
                rect.draw(bounds, &c.draw_state, c.transform, g);
            }

            if let Some(i) = self.hover_frame {
                let bounds = frame_bounds(i, lift_hover_frame);
                rect.draw(bounds, &c.draw_state, c.transform, g);
            }
        }

        // Draw navigate to start or end buttons.
        {
            use graphics::Line;
            use graphics::math::*;

            let line = Line::new([0.0, 0.0, 1.0, 1.0], 0.5);

            let at_beginning: bool = self.start_frame == 0;
            drawutils::draw_goto_end(
                at_beginning,
                [
                    self.bounds[0] as f64 + left_to_goto_start + frame_width,
                    self.bounds[1] as f64 + top_to_frame
                ],
                [
                    -frame_width * 0.5,
                    frame_height
                ],
                &Line::new(if self.hover_goto_start { red } else { blue }, 0.5),
                c, g
            );

            let at_end: bool = end_frame >= self.frames;
            drawutils::draw_goto_end(
                at_end,
                [
                    self.bounds[0] as f64 + self.bounds[2] as f64
                        - right_to_goto_end - frame_width,
                    self.bounds[1] as f64 + top_to_frame
                ],
                [
                    frame_width * 0.5,
                    frame_height
                ],
                &Line::new(if self.hover_goto_end { red } else { blue }, 0.5),
                c, g
            );
        }
    }

    pub fn draw_drag<G: Graphics>(&self, c: &Context, g: &mut G) {

    }
}
<|endoftext|>


<commit_before>mod convert;

///# aHash
///
/// This hashing algorithm is intended to be a DOS resistant, hardware specific, alternative to FxHash.
/// It provides a high speed hash algorithm, but unlike FxHash it is a Keyed hash. This allows it to be used
/// in a HashMap without allowing for the possibility that an malicious user can induce a collision.
///
/// # How aHash works
///
/// aHash uses the hardware AES instruction on x86 processors to provide a keyed hash function.
/// It uses two rounds of AES per hash. So it should not be considered cryptographically secure.

use crate::convert::Convert;
use std::collections::{HashMap};
use std::default::Default;
use std::hash::{BuildHasherDefault, Hasher};
use std::mem::transmute;

/// A builder for an AHasher that uses a thread local random number to generate the keys.
/// To controll the keys uses instead call [AHasher](struct.AHasher.html#method.new_with_keys)
pub type ABuildHasher = BuildHasherDefault<AHasher>;

/// A `HashMap` using a default aHash hasher.
pub type AHashMap<K, V> = HashMap<K, V, ABuildHasher>;

const DEFAULT_KEYS: [u64; 2] = [0x6c62_272e_07bb_0142, 0x517c_c1b7_2722_0a95];

#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: [u64; 2],
}

impl AHasher {
    pub fn new_with_keys(key0: u64, key1: u64) -> AHasher {
        AHasher { buffer:[key0, key1] }
    }
}

impl Default for AHasher {
    #[inline]
    fn default() -> AHasher {
        AHasher { buffer: [DEFAULT_KEYS[0], DEFAULT_KEYS[1]] }
    }
}

macro_rules! as_array {
    ($input:expr, $len:expr) => {{
        {
            #[inline]
            fn as_array<T>(slice: &[T]) -> &[T; $len] {
                assert_eq!(slice.len(), $len);
                unsafe {
                    &*(slice.as_ptr() as *const [_; $len])
                }
            }
            as_array($input)
        }
    }}
}

//Note that each of the write_XX methods passes the arguments slightly differently to hash.
//This is done so that an u8 and a u64 that both contain the same value will produce different hashes.
impl Hasher for AHasher {
    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.buffer = hash([self.buffer[1], self.buffer[0] ^ i as u64].convert(), self.buffer.convert()).convert();

    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.buffer = hash([self.buffer[1] ^ i as u64, self.buffer[0]].convert(), self.buffer.convert()).convert();

    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.buffer = hash([self.buffer[0], self.buffer[1]  ^ i as u64].convert(), self.buffer.convert()).convert();
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        let buffer: u128 = self.buffer.convert();
        self.buffer = hash((buffer ^ i).convert(), self.buffer.convert()).convert();
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.buffer = hash([self.buffer[0] ^ i, self.buffer[1]].convert(), self.buffer.convert()).convert();
    }
    #[inline]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let mut remainder_low: u64 = self.buffer[0];
        let mut remainder_hi: u64 = self.buffer[1];
        if data.len() >= 16 {
            while data.len() >= 16 {
                let (block, rest) = data.split_at(16);
                let block: &[u8; 16] = as_array!(block, 16);
                self.buffer = hash(self.buffer.convert(), *block).convert();
                data = rest;
            }
            self.buffer = hash(self.buffer.convert(), self.buffer.convert()).convert();
        }
        if data.len() >= 8 {
            let (block, rest) = data.split_at(8);
            let val: u64 = as_array!(block, 8).convert();
            remainder_hi ^= val;
            remainder_hi = remainder_hi.rotate_left(32);
            data = rest;
        }
        if data.len() >= 4 {
            let (block, rest) = data.split_at(4);
            let val: u32 = as_array!(block, 4).convert();
            remainder_low ^= val as u64;
            remainder_low = remainder_low.rotate_left(32);
            data = rest;
        }
        if data.len() >= 2 {
            let (block, rest) = data.split_at(2);
            let val: u16 = as_array!(block, 2).convert();
            remainder_low ^= val as u64;
            remainder_low = remainder_low.rotate_left(16);
            data = rest;
        }
        if data.len() >= 1 {
            remainder_low ^= data[0] as u64;
            remainder_low = remainder_low.rotate_left(8);
        }
        self.buffer = hash([remainder_low, remainder_hi].convert(), self.buffer.convert()).convert();
    }
    #[inline]
    fn finish(&self) -> u64 {
        let result: [u64; 2] = hash(self.buffer.convert(), self.buffer.convert()).convert();
        result[0]//.wrapping_add(result[1])
    }
}

#[inline(always)]
fn hash(value: [u8; 16], xor: [u8; 16]) -> [u8; 16] {
    #[cfg(target_arch = "x86")]
    use core::arch::x86::*;
    #[cfg(target_arch = "x86_64")]
    use std::arch::x86_64::*;
    unsafe {
        let value = transmute(value);
        transmute(_mm_aesenc_si128(value, transmute(xor)))
    }
}

#[cfg(all(
    any(target_arch = "x86", target_arch = "x86_64"),
    target_feature = "aes"
))]
#[cfg(test)]
mod tests {
    use crate::convert::Convert;
    use crate::*;
    #[test]
    fn test_hash() {
        let mut result: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value: [u64; 2] = [1 << 32, 0xFEDCBA9876543210];
        result = hash(value.convert(), result.convert()).convert();
        result = hash(result.convert(), result.convert()).convert();
        let mut result2: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value2: [u64; 2] = [1, 0xFEDCBA9876543210];
        result2 = hash(value2.convert(), result2.convert()).convert();
        result2 = hash(result2.convert(), result.convert()).convert();
        let result: [u8; 16] = result.convert();
        let result2: [u8; 16] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }
    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }

}
<commit_msg>Add some documentation. \n Add better default instantiation<commit_after>mod convert;

///# aHash
///
/// This hashing algorithm is intended to be a DOS resistant, hardware specific, Hash.
/// This can be seen as a DOS resistant alternative to FxHash, or a fast equivalent to SipHash.
/// It provides a high speed hash algorithm, and is a Keyed hash. This allows it to be used
/// in a HashMap without allowing for the possibility that an malicious user can induce a collision.
///
/// # How aHash works
///
/// aHash uses the hardware AES instruction on x86 processors to provide a keyed hash function.
/// It uses two rounds of AES per hash. So it should not be considered cryptographically secure.

use crate::convert::Convert;
use std::collections::{HashMap};
use std::default::Default;
use std::hash::{BuildHasherDefault, Hasher, BuildHasher};
use std::mem::transmute;

/// A `HashMap` using a `LocationBasedState` BuildHasher to hash the items.
pub type AHashMap<K, V> = HashMap<K, V, LocationBasedState>;

const DEFAULT_KEYS: [u64; 2] = [0x6c62_272e_07bb_0142, 0x517c_c1b7_2722_0a95];

/// Provides a `BuildHasher` is typically used (e.g. by [`HashMap`]) to create
/// [`AHasher`]s for each key such that they are hashed independently of one
/// another, since [`AHasher`]s contain state.
///
/// LocationBasedState uses it's in-memory location to see the AHasher. This
/// is more predictable than true random values, but does not require generating
/// them.
///
/// For each instance of `LocationBasedState`, the [`AHasher`]s created by
/// [`build_hasher`] should be identical. That is, if the same stream of bytes
/// is fed into each hasher, the same output will also be generated.
///
/// # Examples
///
/// ```
/// use ahash::LocationBasedState;
/// use std::hash::{BuildHasher, Hasher};
///
/// let s = LocationBasedState::new();
/// let mut hasher_1 = s.build_hasher();
/// let mut hasher_2 = s.build_hasher();
///
/// hasher_1.write_u32(8128);
/// hasher_2.write_u32(8128);
///
/// assert_eq!(hasher_1.finish(), hasher_2.finish());
/// ```
///
/// [`build_hasher`]: #tymethod.build_hasher
/// [`Hasher`]: trait.Hasher.html
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
pub struct LocationBasedState { }

impl LocationBasedState {
    pub fn new() -> LocationBasedState {
        LocationBasedState{}
    }
}
impl BuildHasher for LocationBasedState {
    type Hasher = AHasher;

    fn build_hasher(&self) -> AHasher {
        let location = self as *const Self as u64;
        AHasher {buffer:[location, location.rotate_left(8)]}
    }
}
impl Default for LocationBasedState {
    fn default() -> LocationBasedState {
        LocationBasedState{}
    }
}

/// A trait for hashing an arbitrary stream of bytes.
///
/// Instances of `AHasher` represent state that is updated while hashing data.
///
/// Each method updates the internal state based on the new data provided. Once
/// all of the data has been provided, the resulting hash can be obtained by calling
/// `finish()`
///
/// #Example
///
/// ```
/// use std::hash::Hasher;
/// use ahash::AHasher;
///
/// let mut hasher = AHasher::new_with_keys(123, 456);
///
/// hasher.write_u32(1989);
/// hasher.write_u8(11);
/// hasher.write_u8(9);
/// hasher.write(b"Huh?");
///
/// println!("Hash is {:x}!", hasher.finish());
/// ```
#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: [u64; 2],
}
impl AHasher {
    pub fn new_with_keys(key0: u64, key1: u64) -> AHasher {
        AHasher { buffer:[key0, key1] }
    }
}
impl Default for AHasher {
    #[inline]
    fn default() -> AHasher {
        AHasher { buffer: [DEFAULT_KEYS[0], DEFAULT_KEYS[1]] }
    }
}

macro_rules! as_array {
    ($input:expr, $len:expr) => {{
        {
            #[inline]
            fn as_array<T>(slice: &[T]) -> &[T; $len] {
                assert_eq!(slice.len(), $len);
                unsafe {
                    &*(slice.as_ptr() as *const [_; $len])
                }
            }
            as_array($input)
        }
    }}
}

//Implementation note: each of the write_XX methods passes the arguments slightly differently to hash.
//This is done so that an u8 and a u64 that both contain the same value will produce different hashes.
impl Hasher for AHasher {
    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.buffer = hash([self.buffer[1], self.buffer[0] ^ i as u64].convert(), self.buffer.convert()).convert();

    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.buffer = hash([self.buffer[1] ^ i as u64, self.buffer[0]].convert(), self.buffer.convert()).convert();

    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.buffer = hash([self.buffer[0], self.buffer[1]  ^ i as u64].convert(), self.buffer.convert()).convert();
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        let buffer: u128 = self.buffer.convert();
        self.buffer = hash((buffer ^ i).convert(), self.buffer.convert()).convert();
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.buffer = hash([self.buffer[0] ^ i, self.buffer[1]].convert(), self.buffer.convert()).convert();
    }
    #[inline]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let mut remainder_low: u64 = self.buffer[0];
        let mut remainder_hi: u64 = self.buffer[1];
        if data.len() >= 16 {
            while data.len() >= 16 {
                let (block, rest) = data.split_at(16);
                let block: &[u8; 16] = as_array!(block, 16);
                self.buffer = hash(self.buffer.convert(), *block).convert();
                data = rest;
            }
            self.buffer = hash(self.buffer.convert(), self.buffer.convert()).convert();
        }
        if data.len() >= 8 {
            let (block, rest) = data.split_at(8);
            let val: u64 = as_array!(block, 8).convert();
            remainder_hi ^= val;
            remainder_hi = remainder_hi.rotate_left(32);
            data = rest;
        }
        if data.len() >= 4 {
            let (block, rest) = data.split_at(4);
            let val: u32 = as_array!(block, 4).convert();
            remainder_low ^= val as u64;
            remainder_low = remainder_low.rotate_left(32);
            data = rest;
        }
        if data.len() >= 2 {
            let (block, rest) = data.split_at(2);
            let val: u16 = as_array!(block, 2).convert();
            remainder_low ^= val as u64;
            remainder_low = remainder_low.rotate_left(16);
            data = rest;
        }
        if data.len() >= 1 {
            remainder_low ^= data[0] as u64;
            remainder_low = remainder_low.rotate_left(8);
        }
        self.buffer = hash([remainder_low, remainder_hi].convert(), self.buffer.convert()).convert();
    }
    #[inline]
    fn finish(&self) -> u64 {
        let result: [u64; 2] = hash(self.buffer.convert(), self.buffer.convert()).convert();
        result[0]//.wrapping_add(result[1])
    }
}

#[inline(always)]
fn hash(value: [u8; 16], xor: [u8; 16]) -> [u8; 16] {
    #[cfg(target_arch = "x86")]
    use core::arch::x86::*;
    #[cfg(target_arch = "x86_64")]
    use std::arch::x86_64::*;
    unsafe {
        let value = transmute(value);
        transmute(_mm_aesenc_si128(value, transmute(xor)))
    }
}

#[cfg(all(
    any(target_arch = "x86", target_arch = "x86_64"),
    target_feature = "aes"
))]
#[cfg(test)]
mod tests {
    use crate::convert::Convert;
    use crate::*;

    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, LocationBasedState>::default();
        map.insert(1, 3);
    }

    #[test]
    fn test_location_based_state() {
        let state = LocationBasedState::new();
        let hasher_a = state.build_hasher();
        assert_ne!(0, hasher_a.buffer[0]);
        assert_ne!(0, hasher_a.buffer[1]);
        assert_ne!(hasher_a.buffer[0], AHasher::default().buffer[0]);
        assert_ne!(hasher_a.buffer[1], AHasher::default().buffer[1]);
        let hasher_b = state.build_hasher();
        assert_eq!(hasher_a.buffer[0], hasher_b.buffer[0]);
        assert_eq!(hasher_a.buffer[1], hasher_b.buffer[1]);
    }

    #[test]
    fn test_hash() {
        let mut result: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value: [u64; 2] = [1 << 32, 0xFEDCBA9876543210];
        result = hash(value.convert(), result.convert()).convert();
        result = hash(result.convert(), result.convert()).convert();
        let mut result2: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value2: [u64; 2] = [1, 0xFEDCBA9876543210];
        result2 = hash(value2.convert(), result2.convert()).convert();
        result2 = hash(result2.convert(), result.convert()).convert();
        let result: [u8; 16] = result.convert();
        let result2: [u8; 16] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }
    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }

}
<|endoftext|>