<commit_before>use ffi;
use types::{Result, PortMidiDeviceId, Error};
use io::{InputPort, OutputPort};
use device::DeviceInfo;

/// The elements are static after initializing
pub struct PortMidi {
    device_cnt: i32,
    buffer_size: i32,
}
impl PortMidi {
    /// Initializes the underlying PortMidi C library.
    /// It does not support *hot plugging*, this means
    /// that devices that are connect after calling `new`
    /// are not picked up by PortMidi.
    pub fn new() -> Result<Self> {
        try!(Result::from(unsafe { ffi::Pm_Initialize() }));

        Ok(PortMidi {
            device_cnt: unsafe { ffi::Pm_CountDevices() },
            buffer_size: 1024, // TODO: argument
        })
    }

    /// Return the number of devices. This number will not change during the lifetime
    /// of the program.
    pub fn device_cnt(&self) -> PortMidiDeviceId {
        self.device_cnt
    }

    /// Gets the `PortMidiDeviceId` for the default input, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_input_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultInputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    /// Gets the `PortMidiDeviceId` for the default output, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_output_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultOutputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    pub fn device(&self, id: PortMidiDeviceId) -> Result<DeviceInfo> {
        DeviceInfo::new(id)
    }

    pub fn default_input_port(&self) -> Result<InputPort> {
        let info = try!(self.default_input_device_id().and_then(|id| self.device(id)));
        InputPort::new(info, self.buffer_size)
    }

    pub fn input_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_input() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }

    pub fn default_output_port(&self) -> Result<OutputPort> {
        let info = try!(self.default_output_device_id().and_then(|id| self.device(id)));
        OutputPort::new(info, self.buffer_size)
    }

    pub fn output_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_output() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }
}
impl Drop for PortMidi {
    fn drop(&mut self) {
        Result::from(unsafe { ffi::Pm_Terminate() })
            .map_err(|err| println!("Could not terminate library: {}", err));
    }
}
<commit_msg>Add `devices` which returns the `DeviceInfo`s for all avail. devices<commit_after>use ffi;
use types::{Result, PortMidiDeviceId, Error};
use io::{InputPort, OutputPort};
use device::DeviceInfo;

/// The elements are static after initializing
pub struct PortMidi {
    device_cnt: i32,
    buffer_size: i32,
}
impl PortMidi {
    /// Initializes the underlying PortMidi C library.
    /// It does not support *hot plugging*, this means
    /// that devices that are connect after calling `new`
    /// are not picked up by PortMidi.
    pub fn new() -> Result<Self> {
        try!(Result::from(unsafe { ffi::Pm_Initialize() }));

        Ok(PortMidi {
            device_cnt: unsafe { ffi::Pm_CountDevices() },
            buffer_size: 1024, // TODO: argument
        })
    }

    /// Return the number of devices. This number will not change during the lifetime
    /// of the program.
    pub fn device_cnt(&self) -> PortMidiDeviceId {
        self.device_cnt
    }

    /// Gets the `PortMidiDeviceId` for the default input, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_input_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultInputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    /// Gets the `PortMidiDeviceId` for the default output, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_output_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultOutputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    pub fn device(&self, id: PortMidiDeviceId) -> Result<DeviceInfo> {
        DeviceInfo::new(id)
    }

    pub fn devices(&self) -> Result<Vec<DeviceInfo>> {
        let mut devices = Vec::with_capacity(self.device_cnt() as usize);
        for res in (0..self.device_cnt()).map(|id| self.device(id)) {
            match res {
                Ok(device) => devices.push(device),
                Err(err) => return Err(err),
            }
        }
        Ok(devices)
    }

    pub fn default_input_port(&self) -> Result<InputPort> {
        let info = try!(self.default_input_device_id().and_then(|id| self.device(id)));
        InputPort::new(info, self.buffer_size)
    }

    pub fn input_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_input() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }

    pub fn default_output_port(&self) -> Result<OutputPort> {
        let info = try!(self.default_output_device_id().and_then(|id| self.device(id)));
        OutputPort::new(info, self.buffer_size)
    }

    pub fn output_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_output() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }
}
impl Drop for PortMidi {
    fn drop(&mut self) {
        Result::from(unsafe { ffi::Pm_Terminate() })
            .map_err(|err| println!("Could not terminate library: {}", err));
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::io;
use std::io::Read;
use std::sync::mpsc;
use std::sync::mpsc::{SyncSender, Receiver};
use std::default::Default;
use std::marker::Send;
use self::mad_decoder_mode::* ;
use std::option::Option::{None, Some};
use libc::types::common::c95::c_void;
use libc::types::common::c99::*;
use libc::types::os::arch::c95::*;

#[allow(unused)]
#[repr(C)]
static mut input_buffer: [u8; 16384] = [0; 16384];

#[allow(unused, improper_ctypes)]
#[link(name = "mad")]
extern {
    fn mad_decoder_init(decoder: *mut mad_decoder,
                        message: *mut c_void,
                        input_callback: extern fn(message: *mut MadMessage,
                                                  stream: &mad_stream) -> mad_flow,
                        header_callback: extern fn(),
                        filter_callback: extern fn(),
                        output_callback: extern fn(message: *mut MadMessage,
                                                   header: c_int,
                                                   pcm: &mad_pcm) -> mad_flow,
                        error_callback: extern fn(message: *mut MadMessage,
                                                  stream: &mad_stream,
                                                  frame: c_int) -> mad_flow,
                        message_callback: extern fn());
    #[allow(dead_code)]
    fn mad_decoder_run(input: &mut mad_decoder, mode: mad_decoder_mode) -> c_int;
    fn mad_stream_buffer(stream: &mad_stream, buf_start: *const u8, buf_length: size_t);
}

#[allow(unused)]
#[repr(C)]
enum mad_flow {
    mf_continue = 0x0000,    /* continue normally */
    mf_stop     = 0x0010,    /* stop decoding normally */
    mf_break    = 0x0011,    /* stop decoding and signal an error */
    mf_ignore   = 0x0020    /* ignore the current frame */
}

#[allow(unused)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum Error {
  mad_error_none           = 0x0000,    /* no error */

  mad_error_buflen         = 0x0001,    /* input buffer too small (or eof) */
  mad_error_bufptr         = 0x0002,    /* invalid (null) buffer pointer */

  mad_error_nomem          = 0x0031,    /* not enough memory */

  mad_error_lostsync       = 0x0101,    /* lost synchronization */
  mad_error_badlayer       = 0x0102,    /* reserved header layer value */
  mad_error_badbitrate     = 0x0103,    /* forbidden bitrate value */
  mad_error_badsamplerate  = 0x0104,    /* reserved sample frequency value */
  mad_error_bademphasis    = 0x0105,    /* reserved emphasis value */

  mad_error_badcrc         = 0x0201,    /* crc check failed */
  mad_error_badbitalloc    = 0x0211,    /* forbidden bit allocation value */
  mad_error_badscalefactor = 0x0221,    /* bad scalefactor index */
  mad_error_badmode        = 0x0222,    /* bad bitrate/mode combination */
  mad_error_badframelen    = 0x0231,    /* bad frame length */
  mad_error_badbigvalues   = 0x0232,    /* bad big_values count */
  mad_error_badblocktype   = 0x0233,    /* reserved block_type */
  mad_error_badscfsi       = 0x0234,    /* bad scalefactor selection info */
  mad_error_baddataptr     = 0x0235,    /* bad main_data_begin pointer */
  mad_error_badpart3len    = 0x0236,    /* bad audio data length */
  mad_error_badhufftable   = 0x0237,    /* bad huffman table select */
  mad_error_badhuffdata    = 0x0238,    /* huffman data overrun */
  mad_error_badstereo      = 0x0239,    /* incompatible block_type for js */
}

#[allow(unused)]
#[repr(C)]
struct mad_bitptr {
    byte: size_t,
    cache: uint16_t,
    left: uint16_t,
}

#[allow(unused)]
#[repr(C)]
struct mad_stream {
    buffer: size_t,
    buff_end: size_t,
    skip_len: c_ulong,
    sync: c_int,
    free_rate: c_ulong,
    this_frame: size_t,
    next_frame: size_t,
    ptr: mad_bitptr,
    anc_ptr: mad_bitptr,
    anc_bitlen: c_uint,
    buffer_mdlen: size_t,
    md_len: c_uint,
    options: c_int,
    error: Error,
}

#[allow(unused)]
#[repr(C)]
struct mad_pcm {
    sample_rate: c_uint,
    channels: uint16_t,
    length: uint16_t,
    samples: [[int32_t; 1152]; 2],
}

#[allow(unused)]
struct MadMessage<'a> {
    buffer: &'static mut [u8; 16384],
    reader: &'a mut (io::Read + 'a),
    sender: &'a SyncSender<Result<Frame, Error>>,
}

#[allow(unused)]
#[repr(C)]
enum mad_decoder_mode {
    MAD_DECODER_MODE_SYNC = 0,
    MAD_DECODER_MODE_ASYNC
}

impl Default for mad_decoder_mode {
    fn default() -> mad_decoder_mode {MAD_DECODER_MODE_SYNC}
}

#[derive(Default)]
#[repr(C)]
struct mad_async_parameters {
    pid: c_long,
    ain: c_int,
    aout: c_int,
}

#[derive(Default)]
#[repr(C)]
struct mad_decoder {
    mode: mad_decoder_mode,
    options: c_int,
    async: mad_async_parameters,
    sync: size_t,
    cb_data: size_t,
    input_func: size_t,
    header_func: size_t,
    filter_func: size_t,
    output_func: size_t,
    error_func: size_t,
    message_func: size_t,
}

#[allow(unused)]
pub struct Frame {
    pub sample_rate: u32,
    pub channels: uint16_t,
    pub length: uint16_t,
    pub samples: [[i32; 1152]; 2],
}

#[allow(unused)]
extern fn empty_callback() {

}

#[allow(unused)]
extern fn input_callback (msg: *mut MadMessage, stream: &mad_stream) -> mad_flow {
    unsafe {
        let buffer_size = (*msg).buffer.len();
        let next_frame_position = (stream.next_frame - stream.buffer) as usize;
        let unused_byte_count = buffer_size - next_frame_position;

        if unused_byte_count > 0 {
            for idx in 0 .. unused_byte_count {
                (*msg).buffer[idx] = (*msg).buffer[idx + next_frame_position];
            }
        }

        let mut bytes_read = None;

        if next_frame_position == 0 {
            bytes_read = Some((*msg).reader.read((*msg).buffer).unwrap());
        } else {
            let slice = &mut (*msg).buffer[unused_byte_count .. buffer_size];
            bytes_read = Some((*msg).reader.read(slice).unwrap());
        }

        match bytes_read {
            None    => return mad_flow::mf_stop,
            Some(0) => return mad_flow::mf_stop,
            Some(n) => mad_stream_buffer(stream, (*msg).buffer.as_ptr(), n as u64),
        }
    }

    mad_flow::mf_continue
}

#[allow(unused)]
extern fn error_callback(msg: *mut MadMessage,
                         stream: &mad_stream,
                         frame: c_int) -> mad_flow
{
    unsafe {
        let error_type = stream.error.clone();
        (*msg).sender.send(Err(error_type));
    }
    mad_flow::mf_continue
}

#[allow(unused)]
extern fn output_callback(msg: *mut MadMessage,
                          header: c_int,
                          pcm: &mad_pcm) -> mad_flow
{
    unsafe {
        let frame = Ok(Frame {sample_rate: pcm.sample_rate,
                              channels: pcm.channels,
                              length: pcm.length,
                              samples: pcm.samples});
        (*msg).sender.send(frame);
    }
    mad_flow::mf_continue
}

#[allow(unused)]
pub fn decode<T>(mut reader: T) -> Receiver<Result<Frame, Error>>
    where T: io::Read + Send + 'static {
    let (tx, rx): (SyncSender<Result<Frame, Error>>, Receiver<Result<Frame, Error>>) = mpsc::sync_channel::<Result<Frame, Error>>(2);
    thread::spawn(move || {
        unsafe {
            let mut message = MadMessage {
                buffer: &mut input_buffer,
                reader: &mut reader,
                sender: &tx,
            };
            let message_ptr = &mut message as *mut _ as *mut c_void;
            let mut decoder: mad_decoder = Default::default();
            mad_decoder_init(&mut decoder,
                             message_ptr,
                             input_callback,
                             empty_callback,
                             empty_callback,
                             output_callback,
                             error_callback,
                             empty_callback);
            mad_decoder_run(&mut decoder, mad_decoder_mode::MAD_DECODER_MODE_SYNC);
        }
    });
    rx
}

#[test]
fn data_sizes() {
    use std::mem::size_of;
    assert_eq!(size_of::<mad_bitptr>(), 16);
    assert_eq!(size_of::<Error>(), 4);
    assert_eq!(size_of::<mad_decoder>(), 88);
    assert_eq!(size_of::<mad_pcm>(), 9224);
    assert_eq!(size_of::<mad_stream>(), 120);
}

#[test]
fn test_short_file() {
    use std::path::Path;
    use std::fs::File;
    let path = Path::new("test_samples/tailtoddle_lo.mp3");
    let f = File::open(&path).unwrap();
    let decoder = decode(f);
    let mut frame_count = 0;
    let mut error_count = 0;
    for frame in decoder.iter() {
        match frame {
            Ok(_) => frame_count += 1,
            Err(_) => error_count += 1,
        }
    }
    assert_eq!(frame_count, 1656);
    assert_eq!(error_count, 1);
}

<commit_msg>Style improvements<commit_after>use std::thread;
use std::io;
use std::io::Read;
use std::sync::mpsc;
use std::sync::mpsc::{SyncSender, Receiver};
use std::default::Default;
use std::marker::Send;
use std::option::Option::{None, Some};
use libc::types::common::c95::c_void;
use libc::types::common::c99::*;
use libc::types::os::arch::c95::*;

#[allow(unused)]
#[repr(C)]
static mut input_buffer: [u8; 16384] = [0; 16384];

#[allow(unused, improper_ctypes)]
#[link(name = "mad")]
extern {
    fn mad_decoder_init(decoder: *mut MadDecoder,
                        message: *mut c_void,
                        input_callback: extern fn(message: *mut MadMessage,
                                                  stream: &MadStream) -> MadFlow,
                        header_callback: extern fn(),
                        filter_callback: extern fn(),
                        output_callback: extern fn(message: *mut MadMessage,
                                                   header: c_int,
                                                   pcm: &MadPcm) -> MadFlow,
                        error_callback: extern fn(message: *mut MadMessage,
                                                  stream: &MadStream,
                                                  frame: c_int) -> MadFlow,
                        message_callback: extern fn());
    #[allow(dead_code)]
    fn mad_decoder_run(input: &mut MadDecoder, mode: MadDecoderMode) -> c_int;
    fn mad_stream_buffer(stream: &MadStream, buf_start: *const u8, buf_length: size_t);
}

#[allow(unused)]
#[repr(C)]
enum MadFlow {
    Continue = 0x0000,    /* continue normally */
    Stop     = 0x0010,    /* stop decoding normally */
    Break    = 0x0011,    /* stop decoding and signal an error */
    Ignore   = 0x0020    /* ignore the current frame */
}

#[allow(unused)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum Error {
  mad_error_none           = 0x0000,    /* no error */

  mad_error_buflen         = 0x0001,    /* input buffer too small (or eof) */
  mad_error_bufptr         = 0x0002,    /* invalid (null) buffer pointer */

  mad_error_nomem          = 0x0031,    /* not enough memory */

  mad_error_lostsync       = 0x0101,    /* lost synchronization */
  mad_error_badlayer       = 0x0102,    /* reserved header layer value */
  mad_error_badbitrate     = 0x0103,    /* forbidden bitrate value */
  mad_error_badsamplerate  = 0x0104,    /* reserved sample frequency value */
  mad_error_bademphasis    = 0x0105,    /* reserved emphasis value */

  mad_error_badcrc         = 0x0201,    /* crc check failed */
  mad_error_badbitalloc    = 0x0211,    /* forbidden bit allocation value */
  mad_error_badscalefactor = 0x0221,    /* bad scalefactor index */
  mad_error_badmode        = 0x0222,    /* bad bitrate/mode combination */
  mad_error_badframelen    = 0x0231,    /* bad frame length */
  mad_error_badbigvalues   = 0x0232,    /* bad big_values count */
  mad_error_badblocktype   = 0x0233,    /* reserved block_type */
  mad_error_badscfsi       = 0x0234,    /* bad scalefactor selection info */
  mad_error_baddataptr     = 0x0235,    /* bad main_data_begin pointer */
  mad_error_badpart3len    = 0x0236,    /* bad audio data length */
  mad_error_badhufftable   = 0x0237,    /* bad huffman table select */
  mad_error_badhuffdata    = 0x0238,    /* huffman data overrun */
  mad_error_badstereo      = 0x0239,    /* incompatible block_type for js */
}

#[allow(unused)]
#[repr(C)]
struct MadBitPtr {
    byte: size_t,
    cache: uint16_t,
    left: uint16_t,
}

#[allow(unused)]
#[repr(C)]
struct MadStream {
    buffer: size_t,
    buff_end: size_t,
    skip_len: c_ulong,
    sync: c_int,
    free_rate: c_ulong,
    this_frame: size_t,
    next_frame: size_t,
    ptr: MadBitPtr,
    anc_ptr: MadBitPtr,
    anc_bitlen: c_uint,
    buffer_mdlen: size_t,
    md_len: c_uint,
    options: c_int,
    error: Error,
}

#[allow(unused)]
#[repr(C)]
struct MadPcm {
    sample_rate: c_uint,
    channels: uint16_t,
    length: uint16_t,
    samples: [[int32_t; 1152]; 2],
}

#[allow(unused)]
struct MadMessage<'a> {
    buffer: &'static mut [u8; 16384],
    reader: &'a mut (io::Read + 'a),
    sender: &'a SyncSender<Result<Frame, Error>>,
}

#[allow(unused)]
#[repr(C)]
enum MadDecoderMode {
    Sync = 0,
    Async
}

impl Default for MadDecoderMode {
    fn default() -> MadDecoderMode {MadDecoderMode::Sync}
}

#[derive(Default)]
#[repr(C)]
struct MadAsyncParameters {
    pid: c_long,
    ain: c_int,
    aout: c_int,
}

#[derive(Default)]
#[repr(C)]
struct MadDecoder {
    mode: MadDecoderMode,
    options: c_int,
    async: MadAsyncParameters,
    sync: size_t,
    cb_data: size_t,
    input_func: size_t,
    header_func: size_t,
    filter_func: size_t,
    output_func: size_t,
    error_func: size_t,
    message_func: size_t,
}

#[allow(unused)]
pub struct Frame {
    pub sample_rate: u32,
    pub channels: uint16_t,
    pub length: uint16_t,
    pub samples: [[i32; 1152]; 2],
}

#[allow(unused)]
extern fn empty_callback() {

}

#[allow(unused)]
extern fn input_callback (msg: *mut MadMessage, stream: &MadStream) -> MadFlow {
    unsafe {
        let buffer_size = (*msg).buffer.len();
        let next_frame_position = (stream.next_frame - stream.buffer) as usize;
        let unused_byte_count = buffer_size - next_frame_position;

        if unused_byte_count > 0 {
            for idx in 0 .. unused_byte_count {
                (*msg).buffer[idx] = (*msg).buffer[idx + next_frame_position];
            }
        }

        let mut bytes_read = None;

        if next_frame_position == 0 {
            bytes_read = Some((*msg).reader.read((*msg).buffer).unwrap());
        } else {
            let slice = &mut (*msg).buffer[unused_byte_count .. buffer_size];
            bytes_read = Some((*msg).reader.read(slice).unwrap());
        }

        match bytes_read {
            None    => return MadFlow::Stop,
            Some(0) => return MadFlow::Stop,
            Some(n) => mad_stream_buffer(stream, (*msg).buffer.as_ptr(), n as u64),
        }
    }

    MadFlow::Continue
}

#[allow(unused)]
extern fn error_callback(msg: *mut MadMessage,
                         stream: &MadStream,
                         frame: c_int) -> MadFlow
{
    unsafe {
        let error_type = stream.error.clone();
        (*msg).sender.send(Err(error_type));
    }
    MadFlow::Continue
}

#[allow(unused)]
extern fn output_callback(msg: *mut MadMessage,
                          header: c_int,
                          pcm: &MadPcm) -> MadFlow
{
    unsafe {
        let frame = Ok(Frame {sample_rate: pcm.sample_rate,
                              channels: pcm.channels,
                              length: pcm.length,
                              samples: pcm.samples});
        (*msg).sender.send(frame);
    }
    MadFlow::Continue
}

#[allow(unused)]
pub fn decode<T>(mut reader: T) -> Receiver<Result<Frame, Error>>
    where T: io::Read + Send + 'static {
    let (tx, rx): (SyncSender<Result<Frame, Error>>, Receiver<Result<Frame, Error>>) = mpsc::sync_channel::<Result<Frame, Error>>(2);
    thread::spawn(move || {
        unsafe {
            let mut message = MadMessage {
                buffer: &mut input_buffer,
                reader: &mut reader,
                sender: &tx,
            };
            let message_ptr = &mut message as *mut _ as *mut c_void;
            let mut decoder: MadDecoder = Default::default();
            mad_decoder_init(&mut decoder,
                             message_ptr,
                             input_callback,
                             empty_callback,
                             empty_callback,
                             output_callback,
                             error_callback,
                             empty_callback);
            mad_decoder_run(&mut decoder, MadDecoderMode::Sync);
        }
    });
    rx
}

#[test]
fn data_sizes() {
    use std::mem::size_of;
    assert_eq!(size_of::<MadBitPtr>(), 16);
    assert_eq!(size_of::<Error>(), 4);
    assert_eq!(size_of::<MadDecoder>(), 88);
    assert_eq!(size_of::<MadPcm>(), 9224);
    assert_eq!(size_of::<MadStream>(), 120);
}

#[test]
fn test_short_file() {
    use std::path::Path;
    use std::fs::File;
    let path = Path::new("test_samples/tailtoddle_lo.mp3");
    let f = File::open(&path).unwrap();
    let decoder = decode(f);
    let mut frame_count = 0;
    let mut error_count = 0;
    for frame in decoder.iter() {
        match frame {
            Ok(_) => frame_count += 1,
            Err(_) => error_count += 1,
        }
    }
    assert_eq!(frame_count, 1656);
    assert_eq!(error_count, 1);
}

<|endoftext|>


<commit_before>use std::io::{Read, Seek, SeekFrom};
use byteorder::{BigEndian, ByteOrder};
use {HEADER_LEN, Error, Result};

/// A farbfeld decoder
#[derive(Debug)]
pub struct Decoder<R> {
    r: R,

    width: u32,
    height: u32,
}

impl<R: Read + Seek> Decoder<R> {
    /// Create a new decoder from `r` and parse the header.
    /// # Failures
    /// Returns Error::FormatError if the magic number does not match `farbfeld`
    pub fn new(mut r: R) -> Result<Decoder<R>> {
        let head = &mut [0; HEADER_LEN as usize];
        r.seek(SeekFrom::Start(0))?;
        r.read_exact(head)?;
        if &head[..8] != b"farbfeld" {
                return Err(Error::FormatError("unexpected magic number".to_string()))
        }

        Ok(Decoder {
            r: r,
            width: BigEndian::read_u32(&head[8..]),
            height: BigEndian::read_u32(&head[12..]),
        })
    }

    /// Returns the `(width, height)` of the image.
    pub fn dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Returns the length in bytes for a row.
    pub fn row_len(&self) -> usize {
        self.width as usize * 8
    }

    /// Read a single row from the image and return the bytes read.
    /// # Failures
    /// Returns a `Error::ImageEnd` if the `row` is greater as the `height`
    pub fn read_row(&mut self, row: u32,  buf: &mut [u8]) -> Result<usize> {
        if row > self.height { return Err(Error::ImageEnd) }

        let row_len = self.row_len();
        let offset = HEADER_LEN + row as u64 * row_len as u64;
        self.r.seek(SeekFrom::Start(offset))?;
        self.r.read_exact(&mut buf[..row_len])?;
        Ok(row_len)
    }

    /// Read whole image into a `Vec<u8>`.
    pub fn read_image(&mut self) -> Result<Vec<u8>> {
        self.r.seek(SeekFrom::Start(HEADER_LEN))?;
        let num_raw_bytes = self.height as usize * self.row_len();
        let mut buf = vec![0; num_raw_bytes];
        self.r.read_exact(&mut buf)?;
        Ok(buf)
    }
}

#[cfg(test)]
mod tests {
    use std::io::{Cursor, ErrorKind, Write};
    use Decoder;
    use tests::IMAGE_DATA;
    use Error;

    #[test]
    fn invalid_magic() {
        let mut img_data = Vec::new();
        img_data.write(b"test fail").unwrap();
        img_data.write(&IMAGE_DATA[8..]).unwrap();
        let buf = Cursor::new(img_data);

        match Decoder::new(buf) {
            Err(e) => match e {
                Error::FormatError(_) => return,
                e => panic!("{:?}", e),
            },
            Ok(_) => panic!("Got Ok expected Error::FormatError"),
        }
    }

    #[test]
    fn truncate_header() {
        let buf = Cursor::new(&IMAGE_DATA[0..8]);

        match Decoder::new(buf) {
            Err(Error::IoError(e)) => {
                if e.kind() == ErrorKind::UnexpectedEof {
                    return
                } else { panic!("{:?}", e) }
            },
            Err(e) => panic!("{:?}", e),
            Ok(_) => panic!("Got Ok expected Error::FormatError"),
        }

    }

    #[test]
    fn truncate_data() {
        let mut img_data = Vec::with_capacity(IMAGE_DATA.len()-1);
        img_data.write_all(&IMAGE_DATA[..IMAGE_DATA.len()-1]).unwrap();
        let buf = Cursor::new(img_data);
        let mut img = Decoder::new(buf).unwrap();
        match img.read_image() {
            Err(Error::IoError(e)) => {
                if e.kind() == ErrorKind::UnexpectedEof {
                    return
                } else { panic!("{:?}", e) }
            },
            Err(e) => panic!("{:?}", e),
            Ok(_) => panic!("Got Ok expected Error::FormatError"),
        }
    }
}
<commit_msg>kick out the vec and use the slice direct to create the Cursor<commit_after>use std::io::{Read, Seek, SeekFrom};
use byteorder::{BigEndian, ByteOrder};
use {HEADER_LEN, Error, Result};

/// A farbfeld decoder
#[derive(Debug)]
pub struct Decoder<R> {
    r: R,

    width: u32,
    height: u32,
}

impl<R: Read + Seek> Decoder<R> {
    /// Create a new decoder from `r` and parse the header.
    /// # Failures
    /// Returns Error::FormatError if the magic number does not match `farbfeld`
    pub fn new(mut r: R) -> Result<Decoder<R>> {
        let head = &mut [0; HEADER_LEN as usize];
        r.seek(SeekFrom::Start(0))?;
        r.read_exact(head)?;
        if &head[..8] != b"farbfeld" {
                return Err(Error::FormatError("unexpected magic number".to_string()))
        }

        Ok(Decoder {
            r: r,
            width: BigEndian::read_u32(&head[8..]),
            height: BigEndian::read_u32(&head[12..]),
        })
    }

    /// Returns the `(width, height)` of the image.
    pub fn dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Returns the length in bytes for a row.
    pub fn row_len(&self) -> usize {
        self.width as usize * 8
    }

    /// Read a single row from the image and return the bytes read.
    /// # Failures
    /// Returns a `Error::ImageEnd` if the `row` is greater as the `height`
    pub fn read_row(&mut self, row: u32,  buf: &mut [u8]) -> Result<usize> {
        if row > self.height { return Err(Error::ImageEnd) }

        let row_len = self.row_len();
        let offset = HEADER_LEN + row as u64 * row_len as u64;
        self.r.seek(SeekFrom::Start(offset))?;
        self.r.read_exact(&mut buf[..row_len])?;
        Ok(row_len)
    }

    /// Read whole image into a `Vec<u8>`.
    pub fn read_image(&mut self) -> Result<Vec<u8>> {
        self.r.seek(SeekFrom::Start(HEADER_LEN))?;
        let num_raw_bytes = self.height as usize * self.row_len();
        let mut buf = vec![0; num_raw_bytes];
        self.r.read_exact(&mut buf)?;
        Ok(buf)
    }
}

#[cfg(test)]
mod tests {
    use std::io::{Cursor, ErrorKind, Write};
    use Decoder;
    use tests::IMAGE_DATA;
    use Error;

    #[test]
    fn invalid_magic() {
        let mut img_data = Vec::new();
        img_data.write(b"test fail").unwrap();
        img_data.write(&IMAGE_DATA[8..]).unwrap();
        let buf = Cursor::new(img_data);

        match Decoder::new(buf) {
            Err(e) => match e {
                Error::FormatError(_) => return,
                e => panic!("{:?}", e),
            },
            Ok(_) => panic!("Got Ok expected Error::FormatError"),
        }
    }

    #[test]
    fn truncate_header() {
        let buf = Cursor::new(&IMAGE_DATA[0..8]);

        match Decoder::new(buf) {
            Err(Error::IoError(e)) => {
                if e.kind() == ErrorKind::UnexpectedEof {
                    return
                } else { panic!("{:?}", e) }
            },
            Err(e) => panic!("{:?}", e),
            Ok(_) => panic!("Got Ok expected Error::FormatError"),
        }

    }

    #[test]
    fn truncate_data() {
        let buf = Cursor::new(&IMAGE_DATA[..IMAGE_DATA.len()-1]);
        let mut img = Decoder::new(buf).unwrap();
        match img.read_image() {
            Err(Error::IoError(e)) => {
                if e.kind() == ErrorKind::UnexpectedEof {
                    return
                } else { panic!("{:?}", e) }
            },
            Err(e) => panic!("{:?}", e),
            Ok(_) => panic!("Got Ok expected Error::FormatError"),
        }
    }
}
<|endoftext|>


<commit_before>use std::str;
use serde::ser::{Serializer, Serialize, Error};
use error::BencodeError;

type Token = Vec<u8>;
type Context = Vec<Token>;

#[derive(Debug)]
pub struct Encoder {
    stack: Vec<Context>
}

impl Encoder {
    pub fn new() -> Encoder {
        let mut stack = Vec::new();
        stack.push(Context::new());
        Encoder {
            stack: stack
        }
    }

    pub fn encoded(&self) -> Vec<u8> {
        let mut result: Vec<u8> = Vec::new();
        for c in self.stack.iter() {
            for t in c.iter() {
                result.extend_from_slice(&t)
            }
        }
        result
    }

    fn push(&mut self, token: &[u8]) {
        if let Some(last) = self.stack.last_mut() {
            (*last).push(token.into());
        }
    }

    fn new_context(&mut self) {
        self.stack.push(Context::new());
    }

    fn merge_context(&mut self) {
        if let Some(current) = self.stack.pop() {
            if let Some(last) = self.stack.last_mut() {
                (*last).extend(current);
            }
        }
    }

    fn tokenify_context(&mut self) {
        if let Some(c) = self.stack.pop() {
            let token: Token = c.into_iter().flat_map(|t| t).collect();
            self.push(&token);
        }
    }

    fn sort_current_context(&mut self) {
        if let Some(last) = self.stack.pop() {
            let mut m: Vec<_> = last.chunks(2).collect();
            m.sort();
            self.new_context();
            for c in m.iter() {
                self.push(&c[0]);
                self.push(&c[1]);
            }
        }
    }

    fn start_dict(&mut self) {
        self.new_context();
        self.push(&"d".as_bytes());
        self.new_context();
    }

    fn end_dict(&mut self) {
        self.sort_current_context();
        self.merge_context();
        self.push("e".as_bytes());
        self.tokenify_context();
    }
}

impl<'a> From<&'a Encoder> for Vec<u8> {
    fn from(encoder: &Encoder) -> Vec<u8> {
        encoder.encoded()
    }
}

impl From<Encoder> for Vec<u8> {
    fn from(encoder: Encoder) -> Vec<u8> {
        encoder.encoded()
    }
}

impl Serializer for Encoder {

    type Error = BencodeError;
    type SeqState = ();
    type TupleState = ();
    type TupleStructState = ();
    type TupleVariantState = ();
    type MapState = ();
    type StructState = ();
    type StructVariantState = ();

    fn serialize_bool(&mut self, value: bool) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_isize(&mut self, value: isize) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_i8(&mut self, value: i8) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_i16(&mut self, value: i16) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_i32(&mut self, value: i32) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_i64(&mut self, value: i64) -> Result<(), Self::Error> {
        let mut token = Vec::new();
        token.extend_from_slice(&"i".as_bytes());
        token.extend_from_slice(&value.to_string().as_bytes());
        token.extend_from_slice(&"e".as_bytes());
        self.push(&token);
        Ok(())
    }
    fn serialize_usize(&mut self, value: usize) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_u8(&mut self, value: u8) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_u16(&mut self, value: u16) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_u32(&mut self, value: u32) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_u64(&mut self, value: u64) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_f32(&mut self, _value: f32) -> Result<(), Self::Error> {
        Err(BencodeError::invalid_value("Cannot serialize f32"))
    }
    fn serialize_f64(&mut self, _value: f64) -> Result<(), Self::Error> {
        Err(BencodeError::invalid_value("Cannot serialize f64"))
    }
    fn serialize_char(&mut self, value: char) -> Result<(), Self::Error> {
        self.serialize_bytes(&[value as u8])
    }
    fn serialize_str(&mut self, value: &str) -> Result<(), Self::Error> {
        self.serialize_bytes(value.as_bytes())
    }
    fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
        let mut token = Vec::new();
        token.extend_from_slice(&value.len().to_string().as_bytes());
        token.extend_from_slice(&":".as_bytes());
        token.extend_from_slice(value);
        self.push(&token);
        Ok(())
    }
    fn serialize_unit(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }
    fn serialize_unit_struct(&mut self, _name: &'static str) -> Result<(), Self::Error> {
        self.serialize_unit()
    }
    fn serialize_unit_variant(&mut self, _name: &'static str, _variant_index: usize, _variant: &'static str) -> Result<(), Self::Error> {
        self.serialize_unit()
    }
    fn serialize_newtype_struct<T: Serialize>(&mut self, _name: &'static str, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_newtype_variant<T: Serialize>(&mut self, _name: &'static str, _variant_index: usize, _variant: &'static str, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_none(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }
    fn serialize_some<T: Serialize>(&mut self, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_seq(&mut self, _len: Option<usize>) -> Result<Self::SeqState, Self::Error> {
        self.new_context();
        self.push("l".as_bytes());
        Ok(())
    }
    fn serialize_seq_elt<T: Serialize>(&mut self, _state: &mut Self::SeqState, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_seq_end(&mut self, _state: Self::SeqState) -> Result<(), Self::Error> {
        self.push("e".as_bytes());
        self.tokenify_context();
        Ok(())
    }
    fn serialize_seq_fixed_size(&mut self, size: usize) -> Result<Self::SeqState, Self::Error> {
        self.serialize_seq(Some(size))
    }
    fn serialize_tuple(&mut self, size: usize) -> Result<Self::TupleState, Self::Error> {
        self.serialize_seq(Some(size))
    }
    fn serialize_tuple_elt<T: Serialize>(&mut self, _state: &mut Self::TupleState, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_tuple_end(&mut self, _state: Self::TupleState) -> Result<(), Self::Error> {
        self.serialize_seq_end(())
    }
    fn serialize_tuple_struct(&mut self, _name: &'static str, len: usize) -> Result<Self::TupleStructState, Self::Error> {
        self.serialize_tuple(len)
    }
    fn serialize_tuple_struct_elt<T: Serialize>(&mut self, _state: &mut Self::TupleStructState, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_tuple_struct_end(&mut self, _state: Self::TupleStructState) -> Result<(), Self::Error> {
        self.serialize_tuple_end(())
    }
    fn serialize_tuple_variant(&mut self, name: &'static str, _variant_index: usize, _variant: &'static str, len: usize) -> Result<Self::TupleVariantState, Self::Error> {
        self.serialize_tuple_struct(name, len)
    }
    fn serialize_tuple_variant_elt<T: Serialize>(&mut self, _state: &mut Self::TupleVariantState, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_tuple_variant_end(&mut self, _state: Self::TupleVariantState) -> Result<(), Self::Error> {
        self.serialize_tuple_struct_end(())
    }
    fn serialize_map(&mut self, _len: Option<usize>) -> Result<Self::MapState, Self::Error> {
        self.start_dict();
        Ok(())
    }
    fn serialize_map_key<T: Serialize>(&mut self, _state: &mut Self::MapState, key: T) -> Result<(), Self::Error> {
        key.serialize(self)
    }
    fn serialize_map_value<T: Serialize>(&mut self, _state: &mut Self::MapState, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_map_end(&mut self, _state: Self::MapState) -> Result<(), Self::Error> {
        self.end_dict();
        Ok(())
    }
    fn serialize_struct(&mut self, _name: &'static str, _len: usize) -> Result<Self::StructState, Self::Error> {
        self.start_dict();
        Ok(())
    }
    fn serialize_struct_elt<V: Serialize>(&mut self, _state: &mut Self::StructState, key: &'static str, value: V) -> Result<(), Self::Error> {
        key.serialize(self).unwrap();
        value.serialize(self).unwrap();
        Ok(())
    }
    fn serialize_struct_end(&mut self, _state: Self::StructState) -> Result<(), Self::Error> {
        self.end_dict();
        Ok(())
    }
    fn serialize_struct_variant(&mut self, name: &'static str, _variant_index: usize, _variant: &'static str, len: usize) -> Result<Self::StructVariantState, Self::Error> {
        self.serialize_struct(name, len)
    }
    fn serialize_struct_variant_elt<V: Serialize>(&mut self, _state: &mut Self::StructVariantState, key: &'static str, value: V) -> Result<(), Self::Error> {
        key.serialize(self).unwrap();
        value.serialize(self).unwrap();
        Ok(())
    }
    fn serialize_struct_variant_end(&mut self, _state: Self::StructVariantState) -> Result<(), Self::Error> {
        self.serialize_struct_end(())
    }
}
<commit_msg>consolidate struct elt serialization<commit_after>use std::str;
use serde::ser::{Serializer, Serialize, Error};
use error::BencodeError;

type Token = Vec<u8>;
type Context = Vec<Token>;

#[derive(Debug)]
pub struct Encoder {
    stack: Vec<Context>
}

impl Encoder {
    pub fn new() -> Encoder {
        let mut stack = Vec::new();
        stack.push(Context::new());
        Encoder {
            stack: stack
        }
    }

    pub fn encoded(&self) -> Vec<u8> {
        let mut result: Vec<u8> = Vec::new();
        for c in self.stack.iter() {
            for t in c.iter() {
                result.extend_from_slice(&t)
            }
        }
        result
    }

    fn push(&mut self, token: &[u8]) {
        if let Some(last) = self.stack.last_mut() {
            (*last).push(token.into());
        }
    }

    fn new_context(&mut self) {
        self.stack.push(Context::new());
    }

    fn merge_context(&mut self) {
        if let Some(current) = self.stack.pop() {
            if let Some(last) = self.stack.last_mut() {
                (*last).extend(current);
            }
        }
    }

    fn tokenify_context(&mut self) {
        if let Some(c) = self.stack.pop() {
            let token: Token = c.into_iter().flat_map(|t| t).collect();
            self.push(&token);
        }
    }

    fn sort_current_context(&mut self) {
        if let Some(last) = self.stack.pop() {
            let mut m: Vec<_> = last.chunks(2).collect();
            m.sort();
            self.new_context();
            for c in m.iter() {
                self.push(&c[0]);
                self.push(&c[1]);
            }
        }
    }

    fn start_dict(&mut self) {
        self.new_context();
        self.push(&"d".as_bytes());
        self.new_context();
    }

    fn end_dict(&mut self) {
        self.sort_current_context();
        self.merge_context();
        self.push("e".as_bytes());
        self.tokenify_context();
    }
}

impl<'a> From<&'a Encoder> for Vec<u8> {
    fn from(encoder: &Encoder) -> Vec<u8> {
        encoder.encoded()
    }
}

impl From<Encoder> for Vec<u8> {
    fn from(encoder: Encoder) -> Vec<u8> {
        encoder.encoded()
    }
}

impl Serializer for Encoder {

    type Error = BencodeError;
    type SeqState = ();
    type TupleState = ();
    type TupleStructState = ();
    type TupleVariantState = ();
    type MapState = ();
    type StructState = ();
    type StructVariantState = ();

    fn serialize_bool(&mut self, value: bool) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_isize(&mut self, value: isize) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_i8(&mut self, value: i8) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_i16(&mut self, value: i16) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_i32(&mut self, value: i32) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_i64(&mut self, value: i64) -> Result<(), Self::Error> {
        let mut token = Vec::new();
        token.extend_from_slice(&"i".as_bytes());
        token.extend_from_slice(&value.to_string().as_bytes());
        token.extend_from_slice(&"e".as_bytes());
        self.push(&token);
        Ok(())
    }
    fn serialize_usize(&mut self, value: usize) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_u8(&mut self, value: u8) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_u16(&mut self, value: u16) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_u32(&mut self, value: u32) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_u64(&mut self, value: u64) -> Result<(), Self::Error> {
        self.serialize_i64(value as i64)
    }
    fn serialize_f32(&mut self, _value: f32) -> Result<(), Self::Error> {
        Err(BencodeError::invalid_value("Cannot serialize f32"))
    }
    fn serialize_f64(&mut self, _value: f64) -> Result<(), Self::Error> {
        Err(BencodeError::invalid_value("Cannot serialize f64"))
    }
    fn serialize_char(&mut self, value: char) -> Result<(), Self::Error> {
        self.serialize_bytes(&[value as u8])
    }
    fn serialize_str(&mut self, value: &str) -> Result<(), Self::Error> {
        self.serialize_bytes(value.as_bytes())
    }
    fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
        let mut token = Vec::new();
        token.extend_from_slice(&value.len().to_string().as_bytes());
        token.extend_from_slice(&":".as_bytes());
        token.extend_from_slice(value);
        self.push(&token);
        Ok(())
    }
    fn serialize_unit(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }
    fn serialize_unit_struct(&mut self, _name: &'static str) -> Result<(), Self::Error> {
        self.serialize_unit()
    }
    fn serialize_unit_variant(&mut self, _name: &'static str, _variant_index: usize, _variant: &'static str) -> Result<(), Self::Error> {
        self.serialize_unit()
    }
    fn serialize_newtype_struct<T: Serialize>(&mut self, _name: &'static str, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_newtype_variant<T: Serialize>(&mut self, _name: &'static str, _variant_index: usize, _variant: &'static str, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_none(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }
    fn serialize_some<T: Serialize>(&mut self, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_seq(&mut self, _len: Option<usize>) -> Result<Self::SeqState, Self::Error> {
        self.new_context();
        self.push("l".as_bytes());
        Ok(())
    }
    fn serialize_seq_elt<T: Serialize>(&mut self, _state: &mut Self::SeqState, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_seq_end(&mut self, _state: Self::SeqState) -> Result<(), Self::Error> {
        self.push("e".as_bytes());
        self.tokenify_context();
        Ok(())
    }
    fn serialize_seq_fixed_size(&mut self, size: usize) -> Result<Self::SeqState, Self::Error> {
        self.serialize_seq(Some(size))
    }
    fn serialize_tuple(&mut self, size: usize) -> Result<Self::TupleState, Self::Error> {
        self.serialize_seq(Some(size))
    }
    fn serialize_tuple_elt<T: Serialize>(&mut self, _state: &mut Self::TupleState, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_tuple_end(&mut self, _state: Self::TupleState) -> Result<(), Self::Error> {
        self.serialize_seq_end(())
    }
    fn serialize_tuple_struct(&mut self, _name: &'static str, len: usize) -> Result<Self::TupleStructState, Self::Error> {
        self.serialize_tuple(len)
    }
    fn serialize_tuple_struct_elt<T: Serialize>(&mut self, _state: &mut Self::TupleStructState, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_tuple_struct_end(&mut self, _state: Self::TupleStructState) -> Result<(), Self::Error> {
        self.serialize_tuple_end(())
    }
    fn serialize_tuple_variant(&mut self, name: &'static str, _variant_index: usize, _variant: &'static str, len: usize) -> Result<Self::TupleVariantState, Self::Error> {
        self.serialize_tuple_struct(name, len)
    }
    fn serialize_tuple_variant_elt<T: Serialize>(&mut self, _state: &mut Self::TupleVariantState, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_tuple_variant_end(&mut self, _state: Self::TupleVariantState) -> Result<(), Self::Error> {
        self.serialize_tuple_struct_end(())
    }
    fn serialize_map(&mut self, _len: Option<usize>) -> Result<Self::MapState, Self::Error> {
        self.start_dict();
        Ok(())
    }
    fn serialize_map_key<T: Serialize>(&mut self, _state: &mut Self::MapState, key: T) -> Result<(), Self::Error> {
        key.serialize(self)
    }
    fn serialize_map_value<T: Serialize>(&mut self, _state: &mut Self::MapState, value: T) -> Result<(), Self::Error> {
        value.serialize(self)
    }
    fn serialize_map_end(&mut self, _state: Self::MapState) -> Result<(), Self::Error> {
        self.end_dict();
        Ok(())
    }
    fn serialize_struct(&mut self, _name: &'static str, _len: usize) -> Result<Self::StructState, Self::Error> {
        self.start_dict();
        Ok(())
    }
    fn serialize_struct_elt<V: Serialize>(&mut self, _state: &mut Self::StructState, key: &'static str, value: V) -> Result<(), Self::Error> {
        key.serialize(self).unwrap();
        value.serialize(self).unwrap();
        Ok(())
    }
    fn serialize_struct_end(&mut self, _state: Self::StructState) -> Result<(), Self::Error> {
        self.end_dict();
        Ok(())
    }
    fn serialize_struct_variant(&mut self, name: &'static str, _variant_index: usize, _variant: &'static str, len: usize) -> Result<Self::StructVariantState, Self::Error> {
        self.serialize_struct(name, len)
    }
    fn serialize_struct_variant_elt<V: Serialize>(&mut self, _state: &mut Self::StructVariantState, key: &'static str, value: V) -> Result<(), Self::Error> {
        self.serialize_struct_elt(&mut (), key, value)
    }
    fn serialize_struct_variant_end(&mut self, _state: Self::StructVariantState) -> Result<(), Self::Error> {
        self.serialize_struct_end(())
    }
}
<|endoftext|>


<commit_before>/// Run as an application, this is the starting point for our app
extern crate iron;
extern crate redis;
extern crate hyper;
extern crate url;
extern crate time;

extern crate router;
extern crate mime;
extern crate tempdir;
extern crate zip;

use std::fs::File;
use std::io::{Read, Cursor, Write};
use std::fs;
use std::vec::Vec;
use std::env;
use tempdir::TempDir;
use time::now_utc;
use zip::ZipArchive;

use std::slice::SliceConcatExt;
use redis::{Commands, PipelineCommands};

use iron::modifiers::Redirect;
use iron::headers::Location;
use iron::prelude::*;
use iron::status;
use iron::Url as iUrl;

use url::Url;

use hyper::client::Client;
use hyper::header::qitem;
use hyper::header;

pub fn download_and_unzip(source_url: &str, tmp_dir: &TempDir) -> Result<Vec<String>, String> {

    let client = Client::new();
    let res = client.get(&source_url.to_owned())
                    .header(header::UserAgent("Clippy/0.1".to_owned()))
                    .header(header::Accept(vec![qitem(mime!(_/_))]))
                    .header(header::Connection::close());

    match res.send() {
        Ok(mut res) => {
            let mut zip_body: Vec<u8> = Vec::new();
            match res.read_to_end(&mut zip_body) {
                Ok(_) => {
                    match ZipArchive::new(Cursor::new(zip_body)) {
                        Ok(mut archive) => {
                            let mut paths: Vec<String> = Vec::new();
                            for i in 0..archive.len() {
                                let mut zip_file = archive.by_index(i).unwrap();
                                let extracted_path = tmp_dir.path().join(zip_file.name());
                                let full_path = extracted_path.as_path();

                                if zip_file.size() == 0 {
                                    fs::create_dir_all(full_path).unwrap();
                                } else {
                                    let mut writer = File::create(full_path).unwrap();
                                    let mut buffer: Vec<u8> = vec![];
                                    zip_file.read_to_end(&mut buffer).unwrap();
                                    writer.write(&buffer).unwrap();
                                    paths.push(String::from(full_path.to_string_lossy()
                                                                     .into_owned()));
                                }
                            }
                            Ok(paths)
                        }
                        Err(zip::result::ZipError::InvalidArchive(error)) |
                        Err(zip::result::ZipError::UnsupportedArchive(error)) => {
                            Err(format!("Extracting archive failed: {}", error).to_owned())
                        }
                        Err(zip::result::ZipError::FileNotFound) => {
                            Err(String::from("Zip  Archive Corrupt"))
                        }
                        Err(_) => Err(String::from("General IO Error")),
                    }
                }
                Err(error) => Err(format!("Couldn't read github response: {}", error)),
            }
        }
        Err(error) => Err(format!("Couldn't connect to github: {}", error)),
    }
}

pub fn log_redis(redis: &redis::Connection, key: &str, value: &str) {
    redis::pipe()
        .cmd("RPUSH")
        .arg(key.clone())
        .arg(format!("{0} {1}", now_utc().rfc3339(), value))
        .ignore()
        .execute(redis);
}

pub fn set_redis_cache(redis: &redis::Connection, key: &str, value: &str) {
    redis::pipe()
        .cmd("SET").arg(key.clone()).arg(value).ignore()
        .cmd("EXPIRE").arg(key.clone()).arg(5 * 60).ignore() // we expire in 5min
        .execute(redis);
}

pub fn local_redir(url: &str, source_url: &iUrl) -> IronResult<Response> {
    let mut resp = Response::with(status::TemporaryRedirect);
    match source_url.query {
        Some(ref query) => resp.headers.set(Location(format!("{}?{}", &url, query))),
        _ => resp.headers.set(Location(url.to_owned())),
    }
    Ok(resp)
}

pub fn redir(url: &Url, source_url: &iUrl) -> IronResult<Response> {
    match iUrl::from_generic_url(url.clone()) {
        Ok(mut redir_url) => {
            if let Some(ref query) = source_url.query {
                redir_url.query = Some(query.clone());
            }
            Ok(Response::with((status::TemporaryRedirect, Redirect(redir_url))))
        }
        Err(err) => Ok(Response::with((status::InternalServerError, err))),
    }
}

pub fn fetch(client: &Client, url: &str) -> Option<String> {
    let res = client.get(url)
                    .header(header::UserAgent("Clippy/0.1".to_owned()))
                    .header(header::Accept(vec![qitem(mime!(_/_))]))
                    .header(header::Connection::close());
    if let Ok(mut res) = res.send() {
        let mut body = String::new();
        if res.read_to_string(&mut body).is_ok() {
            return Some(body);
        }
    }
    None
}

pub fn setup_redis() -> redis::Connection {
    let url = redis::parse_redis_url(&env::var("REDIS_URL").unwrap_or("redis://redis/".to_owned()))
                  .unwrap();
    redis::Client::open(url)
        .unwrap()
        .get_connection()
        .unwrap()
}
<commit_msg>Default redis url should be 'localhst'<commit_after>/// Run as an application, this is the starting point for our app
extern crate iron;
extern crate redis;
extern crate hyper;
extern crate url;
extern crate time;

extern crate router;
extern crate mime;
extern crate tempdir;
extern crate zip;

use std::fs::File;
use std::io::{Read, Cursor, Write};
use std::fs;
use std::vec::Vec;
use std::env;
use tempdir::TempDir;
use time::now_utc;
use zip::ZipArchive;

use std::slice::SliceConcatExt;
use redis::{Commands, PipelineCommands};

use iron::modifiers::Redirect;
use iron::headers::Location;
use iron::prelude::*;
use iron::status;
use iron::Url as iUrl;

use url::Url;

use hyper::client::Client;
use hyper::header::qitem;
use hyper::header;

pub fn download_and_unzip(source_url: &str, tmp_dir: &TempDir) -> Result<Vec<String>, String> {

    let client = Client::new();
    let res = client.get(&source_url.to_owned())
                    .header(header::UserAgent("Clippy/0.1".to_owned()))
                    .header(header::Accept(vec![qitem(mime!(_/_))]))
                    .header(header::Connection::close());

    match res.send() {
        Ok(mut res) => {
            let mut zip_body: Vec<u8> = Vec::new();
            match res.read_to_end(&mut zip_body) {
                Ok(_) => {
                    match ZipArchive::new(Cursor::new(zip_body)) {
                        Ok(mut archive) => {
                            let mut paths: Vec<String> = Vec::new();
                            for i in 0..archive.len() {
                                let mut zip_file = archive.by_index(i).unwrap();
                                let extracted_path = tmp_dir.path().join(zip_file.name());
                                let full_path = extracted_path.as_path();

                                if zip_file.size() == 0 {
                                    fs::create_dir_all(full_path).unwrap();
                                } else {
                                    let mut writer = File::create(full_path).unwrap();
                                    let mut buffer: Vec<u8> = vec![];
                                    zip_file.read_to_end(&mut buffer).unwrap();
                                    writer.write(&buffer).unwrap();
                                    paths.push(String::from(full_path.to_string_lossy()
                                                                     .into_owned()));
                                }
                            }
                            Ok(paths)
                        }
                        Err(zip::result::ZipError::InvalidArchive(error)) |
                        Err(zip::result::ZipError::UnsupportedArchive(error)) => {
                            Err(format!("Extracting archive failed: {}", error).to_owned())
                        }
                        Err(zip::result::ZipError::FileNotFound) => {
                            Err(String::from("Zip  Archive Corrupt"))
                        }
                        Err(_) => Err(String::from("General IO Error")),
                    }
                }
                Err(error) => Err(format!("Couldn't read github response: {}", error)),
            }
        }
        Err(error) => Err(format!("Couldn't connect to github: {}", error)),
    }
}

pub fn log_redis(redis: &redis::Connection, key: &str, value: &str) {
    redis::pipe()
        .cmd("RPUSH")
        .arg(key.clone())
        .arg(format!("{0} {1}", now_utc().rfc3339(), value))
        .ignore()
        .execute(redis);
}

pub fn set_redis_cache(redis: &redis::Connection, key: &str, value: &str) {
    redis::pipe()
        .cmd("SET").arg(key.clone()).arg(value).ignore()
        .cmd("EXPIRE").arg(key.clone()).arg(5 * 60).ignore() // we expire in 5min
        .execute(redis);
}

pub fn local_redir(url: &str, source_url: &iUrl) -> IronResult<Response> {
    let mut resp = Response::with(status::TemporaryRedirect);
    match source_url.query {
        Some(ref query) => resp.headers.set(Location(format!("{}?{}", &url, query))),
        _ => resp.headers.set(Location(url.to_owned())),
    }
    Ok(resp)
}

pub fn redir(url: &Url, source_url: &iUrl) -> IronResult<Response> {
    match iUrl::from_generic_url(url.clone()) {
        Ok(mut redir_url) => {
            if let Some(ref query) = source_url.query {
                redir_url.query = Some(query.clone());
            }
            Ok(Response::with((status::TemporaryRedirect, Redirect(redir_url))))
        }
        Err(err) => Ok(Response::with((status::InternalServerError, err))),
    }
}

pub fn fetch(client: &Client, url: &str) -> Option<String> {
    let res = client.get(url)
                    .header(header::UserAgent("Clippy/0.1".to_owned()))
                    .header(header::Accept(vec![qitem(mime!(_/_))]))
                    .header(header::Connection::close());
    if let Ok(mut res) = res.send() {
        let mut body = String::new();
        if res.read_to_string(&mut body).is_ok() {
            return Some(body);
        }
    }
    None
}

pub fn setup_redis() -> redis::Connection {
    let url = redis::parse_redis_url(&env::var("REDIS_URL").unwrap_or("redis://localhost/".to_owned()))
                  .unwrap();
    redis::Client::open(url)
        .unwrap()
        .get_connection()
        .unwrap()
}
<|endoftext|>


<commit_before>use rustc::ty::layout::{Size, HasDataLayout};

use super::{Scalar, ScalarMaybeUndef, EvalResult};
use rustc_mir::interpret::sign_extend;

pub trait ScalarExt {
    fn null(size: Size) -> Self;
    fn from_i32(i: i32) -> Self;
    fn from_uint(i: impl Into<u128>, ptr_size: Size) -> Self;
    fn from_int(i: impl Into<i128>, ptr_size: Size) -> Self;
    fn from_f32(f: f32) -> Self;
    fn from_f64(f: f64) -> Self;
    fn is_null(self) -> bool;
}

pub trait FalibleScalarExt {
    fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64>;
    fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64>;
    fn to_i32(self) -> EvalResult<'static, i32>;
    fn to_u8(self) -> EvalResult<'static, u8>;

    /// HACK: this function just extracts all bits if `defined != 0`
    /// Mainly used for args of C-functions and we should totally correctly fetch the size
    /// of their arguments
    fn to_bytes(self) -> EvalResult<'static, u128>;
}

impl ScalarExt for Scalar {
    fn null(size: Size) -> Self {
        Scalar::Bits { bits: 0, size: size.bytes() as u8 }
    }

    fn from_i32(i: i32) -> Self {
        Scalar::Bits { bits: i as u32 as u128, size: 4 }
    }

    fn from_uint(i: impl Into<u128>, size: Size) -> Self {
        Scalar::Bits { bits: i.into(), size: size.bytes() as u8 }
    }

    fn from_int(i: impl Into<i128>, size: Size) -> Self {
        Scalar::Bits { bits: i.into() as u128, size: size.bytes() as u8 }
    }

    fn from_f32(f: f32) -> Self {
        Scalar::Bits { bits: f.to_bits() as u128, size: 4 }
    }

    fn from_f64(f: f64) -> Self {
        Scalar::Bits { bits: f.to_bits() as u128, size: 8 }
    }

    fn is_null(self) -> bool {
        match self {
            Scalar::Bits { bits, .. } => bits == 0,
            Scalar::Ptr(_) => false
        }
    }
}

impl FalibleScalarExt for Scalar {
    fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> {
        let b = self.to_bits(cx.data_layout().pointer_size)?;
        assert_eq!(b as u64 as u128, b);
        Ok(b as u64)
    }

    fn to_u8(self) -> EvalResult<'static, u8> {
        let sz = Size::from_bits(8);
        let b = self.to_bits(sz)?;
        assert_eq!(b as u8 as u128, b);
        Ok(b as u8)
    }

    fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> {
        let b = self.to_bits(cx.data_layout().pointer_size)?;
        let b = sign_extend(b, cx.data_layout().pointer_size) as i128;
        assert_eq!(b as i64 as i128, b);
        Ok(b as i64)
    }

    fn to_i32(self) -> EvalResult<'static, i32> {
        let sz = Size::from_bits(32);
        let b = self.to_bits(sz)?;
        let b = sign_extend(b, sz) as i128;
        assert_eq!(b as i32 as i128, b);
        Ok(b as i32)
    }

    fn to_bytes(self) -> EvalResult<'static, u128> {
        match self {
            Scalar::Bits { bits, size } => {
                assert_ne!(size, 0);
                Ok(bits)
            },
            Scalar::Ptr(_) => err!(ReadPointerAsBytes),
        }
    }
}

impl FalibleScalarExt for ScalarMaybeUndef {
    fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> {
        self.not_undef()?.to_usize(cx)
    }

    fn to_u8(self) -> EvalResult<'static, u8> {
        self.not_undef()?.to_u8()
    }

    fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> {
        self.not_undef()?.to_isize(cx)
    }

    fn to_i32(self) -> EvalResult<'static, i32> {
        self.not_undef()?.to_i32()
    }

    fn to_bytes(self) -> EvalResult<'static, u128> {
        self.not_undef()?.to_bytes()
    }
}
<commit_msg>fix compilation after rustc change<commit_after>use rustc::ty::layout::{Size, HasDataLayout};
use rustc::mir::interpret::sign_extend;

use super::{Scalar, ScalarMaybeUndef, EvalResult};

pub trait ScalarExt {
    fn null(size: Size) -> Self;
    fn from_i32(i: i32) -> Self;
    fn from_uint(i: impl Into<u128>, ptr_size: Size) -> Self;
    fn from_int(i: impl Into<i128>, ptr_size: Size) -> Self;
    fn from_f32(f: f32) -> Self;
    fn from_f64(f: f64) -> Self;
    fn is_null(self) -> bool;
}

pub trait FalibleScalarExt {
    fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64>;
    fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64>;
    fn to_i32(self) -> EvalResult<'static, i32>;
    fn to_u8(self) -> EvalResult<'static, u8>;

    /// HACK: this function just extracts all bits if `defined != 0`
    /// Mainly used for args of C-functions and we should totally correctly fetch the size
    /// of their arguments
    fn to_bytes(self) -> EvalResult<'static, u128>;
}

impl ScalarExt for Scalar {
    fn null(size: Size) -> Self {
        Scalar::Bits { bits: 0, size: size.bytes() as u8 }
    }

    fn from_i32(i: i32) -> Self {
        Scalar::Bits { bits: i as u32 as u128, size: 4 }
    }

    fn from_uint(i: impl Into<u128>, size: Size) -> Self {
        Scalar::Bits { bits: i.into(), size: size.bytes() as u8 }
    }

    fn from_int(i: impl Into<i128>, size: Size) -> Self {
        Scalar::Bits { bits: i.into() as u128, size: size.bytes() as u8 }
    }

    fn from_f32(f: f32) -> Self {
        Scalar::Bits { bits: f.to_bits() as u128, size: 4 }
    }

    fn from_f64(f: f64) -> Self {
        Scalar::Bits { bits: f.to_bits() as u128, size: 8 }
    }

    fn is_null(self) -> bool {
        match self {
            Scalar::Bits { bits, .. } => bits == 0,
            Scalar::Ptr(_) => false
        }
    }
}

impl FalibleScalarExt for Scalar {
    fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> {
        let b = self.to_bits(cx.data_layout().pointer_size)?;
        assert_eq!(b as u64 as u128, b);
        Ok(b as u64)
    }

    fn to_u8(self) -> EvalResult<'static, u8> {
        let sz = Size::from_bits(8);
        let b = self.to_bits(sz)?;
        assert_eq!(b as u8 as u128, b);
        Ok(b as u8)
    }

    fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> {
        let b = self.to_bits(cx.data_layout().pointer_size)?;
        let b = sign_extend(b, cx.data_layout().pointer_size) as i128;
        assert_eq!(b as i64 as i128, b);
        Ok(b as i64)
    }

    fn to_i32(self) -> EvalResult<'static, i32> {
        let sz = Size::from_bits(32);
        let b = self.to_bits(sz)?;
        let b = sign_extend(b, sz) as i128;
        assert_eq!(b as i32 as i128, b);
        Ok(b as i32)
    }

    fn to_bytes(self) -> EvalResult<'static, u128> {
        match self {
            Scalar::Bits { bits, size } => {
                assert_ne!(size, 0);
                Ok(bits)
            },
            Scalar::Ptr(_) => err!(ReadPointerAsBytes),
        }
    }
}

impl FalibleScalarExt for ScalarMaybeUndef {
    fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> {
        self.not_undef()?.to_usize(cx)
    }

    fn to_u8(self) -> EvalResult<'static, u8> {
        self.not_undef()?.to_u8()
    }

    fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> {
        self.not_undef()?.to_isize(cx)
    }

    fn to_i32(self) -> EvalResult<'static, i32> {
        self.not_undef()?.to_i32()
    }

    fn to_bytes(self) -> EvalResult<'static, u128> {
        self.not_undef()?.to_bytes()
    }
}
<|endoftext|>


<commit_before>use super::*;

use std::collections::VecDeque;
use std::io::{BufReader, BufRead, Error, ErrorKind};
use std::fs::{File, OpenOptions};
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::ops::Index;
use std::ops::IndexMut;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::mpsc::{channel, Sender};
use std::thread::{sleep, spawn, JoinHandle};
use std::time::Duration;

use bytecount::count;

const DEFAULT_MAX_SIZE: usize = 1000;

/// Structure encapsulating command history
pub struct History {
    // TODO: this should eventually be private
    /// Vector of buffers to store history in
    pub buffers: VecDeque<Buffer>,
    /// Store a filename to save history into; if None don't save history
    file_name: Option<String>,
    /// Maximal number of buffers stored in the memory
    /// TODO: just make this public?
    max_size: usize,
    /// Maximal number of lines stored in the file
    // TODO: just make this public?
    max_file_size: Arc<AtomicUsize>,
    /// Handle to the background thread managing writes to the history file
    bg_handle: Option<JoinHandle<()>>,
    /// Signals the background thread to stop when dropping the struct
    bg_stop: Arc<AtomicBool>,
    /// Sends commands to write to the history file
    sender: Sender<(Buffer, String)>,

    // TODO set from environment variable?
    pub append_duplicate_entries: bool,
}

impl History {
    /// It's important to execute this function before exiting your program, as it will
    /// ensure that all history data has been written to the disk.
    pub fn commit_history(&mut self) {
        // Signal the background thread to stop
        self.bg_stop.store(true, Ordering::Relaxed);
        // Wait for the background thread to stop
        if let Some(handle) = self.bg_handle.take() {
            let _ = handle.join();
        }
    }

    /// Create new History structure.
    pub fn new() -> History {
        let max_file_size = Arc::new(AtomicUsize::new(DEFAULT_MAX_SIZE));
        let bg_stop = Arc::new(AtomicBool::new(false));
        let (sender, receiver) = channel();

        let stop_signal = bg_stop.clone();
        let max_size = max_file_size.clone();
        History {
            buffers: VecDeque::with_capacity(DEFAULT_MAX_SIZE),
            file_name: None,
            sender: sender,
            bg_handle: Some(spawn(move || {
                while !stop_signal.load(Ordering::Relaxed) {
                    if let Ok((command, filepath)) = receiver.try_recv() {
                        let max_file_size = max_size.load(Ordering::Relaxed);
                        let _ = write_to_disk(max_file_size, &command, &filepath);
                    }
                    sleep(Duration::from_millis(100));
                }

                // Deplete the receiver of commands to write, before exiting the thread.
                while let Ok((command, filepath)) = receiver.try_recv() {
                    let max_file_size = max_size.load(Ordering::Relaxed);
                    let _ = write_to_disk(max_file_size, &command, &filepath);
                }
            })),
            bg_stop: bg_stop,
            max_size: DEFAULT_MAX_SIZE,
            max_file_size: max_file_size,
            append_duplicate_entries: false,
        }
    }

    /// Number of items in history.
    pub fn len(&self) -> usize {
        self.buffers.len()
    }

    /// Add a command to the history buffer and remove the oldest commands when the max history
    /// size has been met. If writing to the disk is enabled, this function will be used for
    /// logging history to the designated history file.
    pub fn push(&mut self, new_item: Buffer) -> io::Result<()> {
        self.file_name
            .as_ref()
            .map(|name| {
                let _ = self.sender.send((new_item.clone(), name.to_owned()));
            });

        // buffers[0] is the oldest entry
        // the new entry goes to the end
        if !self.append_duplicate_entries &&
            self.buffers.back().map(|b| b.to_string()) == Some(new_item.to_string())
        {
            return Ok(());
        }

        self.buffers.push_back(new_item);
        while self.buffers.len() > self.max_size {
            self.buffers.pop_front();
        }
        Ok(())
    }

    /// Go through the history and try to find a buffer which starts the same as the new buffer
    /// given to this function as argument.
    pub fn get_newest_match<'a, 'b>(
        &'a self,
        curr_position: Option<usize>,
        new_buff: &'b Buffer,
    ) -> Option<&'a Buffer> {
        let pos = curr_position.unwrap_or(self.buffers.len());
        for iter in (0..pos).rev() {
            if let Some(tested) = self.buffers.get(iter) {
                if tested.starts_with(new_buff) {
                    return self.buffers.get(iter);
                }
            }
        }
        None
    }

    /// Get the history file name.
    pub fn file_name(&self) -> Option<&str> {
        match self.file_name {
            Some(ref s) => Some(&s[..]),
            None => None,
        }
    }

    /// Set history file name. At the same time enable history.
    pub fn set_file_name(&mut self, name: Option<String>) {
        self.file_name = name;
    }

    /// Set maximal number of buffers stored in memory
    pub fn set_max_size(&mut self, size: usize) {
        self.max_size = size;
    }

    /// Set maximal number of entries in history file
    pub fn set_max_file_size(&mut self, size: usize) {
        self.max_file_size.store(size, Ordering::Relaxed);
    }

    /// Load history from given file name
    pub fn load_history(&mut self) -> io::Result<()> {
        let file_name = match self.file_name.clone() {
            Some(name) => name,
            None => {
                return Err(Error::new(
                    ErrorKind::Other,
                    "Liner: file name not specified",
                ))
            }
        };
        let file = try!(OpenOptions::new().read(true).open(file_name));
        let reader = BufReader::new(file);
        for line in reader.lines() {
            match line {
                Ok(line) => self.buffers.push_back(Buffer::from(line)),
                Err(_) => break,
            }
        }
        Ok(())
    }
}

impl Index<usize> for History {
    type Output = Buffer;

    fn index(&self, index: usize) -> &Buffer {
        &self.buffers[index]
    }
}

impl IndexMut<usize> for History {
    fn index_mut(&mut self, index: usize) -> &mut Buffer {
        &mut self.buffers[index]
    }
}

/// Perform write operation. If the history file does not exist, it will be created.
/// This function is not part of the public interface.
/// XXX: include more information in the file (like fish does)
fn write_to_disk(max_file_size: usize, new_item: &Buffer, file_name: &str) -> io::Result<()> {
    let ret = match OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(file_name) {
        Ok(mut file) => {
            // The metadata contains the length of the file
            let file_length = file.metadata().ok().map_or(0u64, |m| m.len());
            // 4K byte buffer for reading chunks of the file at once.
            let mut buffer = [0; 4096];

            // Determine the number of commands stored.
            {
                let mut seek_point = 0u64;
                let mut stored = 0;
                let mut total_read = 0u64;
                let mut rfile = File::open(file_name).unwrap();
                loop {
                    // Read 4K of bytes all at once into the buffer.
                    let read = rfile.read(&mut buffer)?;
                    // If EOF is found, don't seek at all.
                    if read == 0 { break }
                    // Count the number of commands that were found in the current buffer.
                    let cmds_read = count(&buffer[0..read], b'\n');
                    // If stored + read >= max file size, a seek point is in the current buffer.
                    if stored + cmds_read >= max_file_size {
                        for &byte in buffer[0..read].iter() {
                            total_read += 1;
                            if byte == b'\n' {
                                stored += 1;
                                if stored == max_file_size {
                                    seek_point = total_read;
                                    break
                                }
                            }
                        }

                        try!(file.seek(SeekFrom::Start(seek_point as u64)));
                        let mut buffer: Vec<u8> = Vec::with_capacity((file_length - seek_point) as usize);
                        try!(file.read_to_end(&mut buffer));
                        try!(file.set_len(0));
                        try!(io::copy(&mut buffer.as_slice(), &mut file));
                        break
                    } else {
                        total_read += read as u64;
                        stored += cmds_read;
                    }
                }
            };

            // Seek to end for appending
            try!(file.seek(SeekFrom::End(0)));
            // Write the command to the history file.
            try!(file.write_all(String::from(new_item.clone()).as_bytes()));
            try!(file.write_all(b"\n"));
            file.flush()?;

            Ok(())
        }
        Err(message) => Err(message),
    };
    ret
}
<commit_msg>implement IntoIterator trait for the History type<commit_after>use super::*;

use std::collections::{vec_deque, VecDeque};
use std::io::{BufReader, BufRead, Error, ErrorKind};
use std::fs::{File, OpenOptions};
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::iter::IntoIterator;
use std::ops::Index;
use std::ops::IndexMut;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::mpsc::{channel, Sender};
use std::thread::{sleep, spawn, JoinHandle};
use std::time::Duration;

use bytecount::count;

const DEFAULT_MAX_SIZE: usize = 1000;

/// Structure encapsulating command history
pub struct History {
    // TODO: this should eventually be private
    /// Vector of buffers to store history in
    pub buffers: VecDeque<Buffer>,
    /// Store a filename to save history into; if None don't save history
    file_name: Option<String>,
    /// Maximal number of buffers stored in the memory
    /// TODO: just make this public?
    max_size: usize,
    /// Maximal number of lines stored in the file
    // TODO: just make this public?
    max_file_size: Arc<AtomicUsize>,
    /// Handle to the background thread managing writes to the history file
    bg_handle: Option<JoinHandle<()>>,
    /// Signals the background thread to stop when dropping the struct
    bg_stop: Arc<AtomicBool>,
    /// Sends commands to write to the history file
    sender: Sender<(Buffer, String)>,

    // TODO set from environment variable?
    pub append_duplicate_entries: bool,
}

impl History {
    /// It's important to execute this function before exiting your program, as it will
    /// ensure that all history data has been written to the disk.
    pub fn commit_history(&mut self) {
        // Signal the background thread to stop
        self.bg_stop.store(true, Ordering::Relaxed);
        // Wait for the background thread to stop
        if let Some(handle) = self.bg_handle.take() {
            let _ = handle.join();
        }
    }

    /// Create new History structure.
    pub fn new() -> History {
        let max_file_size = Arc::new(AtomicUsize::new(DEFAULT_MAX_SIZE));
        let bg_stop = Arc::new(AtomicBool::new(false));
        let (sender, receiver) = channel();

        let stop_signal = bg_stop.clone();
        let max_size = max_file_size.clone();
        History {
            buffers: VecDeque::with_capacity(DEFAULT_MAX_SIZE),
            file_name: None,
            sender: sender,
            bg_handle: Some(spawn(move || {
                while !stop_signal.load(Ordering::Relaxed) {
                    if let Ok((command, filepath)) = receiver.try_recv() {
                        let max_file_size = max_size.load(Ordering::Relaxed);
                        let _ = write_to_disk(max_file_size, &command, &filepath);
                    }
                    sleep(Duration::from_millis(100));
                }

                // Deplete the receiver of commands to write, before exiting the thread.
                while let Ok((command, filepath)) = receiver.try_recv() {
                    let max_file_size = max_size.load(Ordering::Relaxed);
                    let _ = write_to_disk(max_file_size, &command, &filepath);
                }
            })),
            bg_stop: bg_stop,
            max_size: DEFAULT_MAX_SIZE,
            max_file_size: max_file_size,
            append_duplicate_entries: false,
        }
    }

    /// Number of items in history.
    pub fn len(&self) -> usize {
        self.buffers.len()
    }

    /// Add a command to the history buffer and remove the oldest commands when the max history
    /// size has been met. If writing to the disk is enabled, this function will be used for
    /// logging history to the designated history file.
    pub fn push(&mut self, new_item: Buffer) -> io::Result<()> {
        self.file_name
            .as_ref()
            .map(|name| {
                let _ = self.sender.send((new_item.clone(), name.to_owned()));
            });

        // buffers[0] is the oldest entry
        // the new entry goes to the end
        if !self.append_duplicate_entries &&
            self.buffers.back().map(|b| b.to_string()) == Some(new_item.to_string())
        {
            return Ok(());
        }

        self.buffers.push_back(new_item);
        while self.buffers.len() > self.max_size {
            self.buffers.pop_front();
        }
        Ok(())
    }

    /// Go through the history and try to find a buffer which starts the same as the new buffer
    /// given to this function as argument.
    pub fn get_newest_match<'a, 'b>(
        &'a self,
        curr_position: Option<usize>,
        new_buff: &'b Buffer,
    ) -> Option<&'a Buffer> {
        let pos = curr_position.unwrap_or(self.buffers.len());
        for iter in (0..pos).rev() {
            if let Some(tested) = self.buffers.get(iter) {
                if tested.starts_with(new_buff) {
                    return self.buffers.get(iter);
                }
            }
        }
        None
    }

    /// Get the history file name.
    pub fn file_name(&self) -> Option<&str> {
        match self.file_name {
            Some(ref s) => Some(&s[..]),
            None => None,
        }
    }

    /// Set history file name. At the same time enable history.
    pub fn set_file_name(&mut self, name: Option<String>) {
        self.file_name = name;
    }

    /// Set maximal number of buffers stored in memory
    pub fn set_max_size(&mut self, size: usize) {
        self.max_size = size;
    }

    /// Set maximal number of entries in history file
    pub fn set_max_file_size(&mut self, size: usize) {
        self.max_file_size.store(size, Ordering::Relaxed);
    }

    /// Load history from given file name
    pub fn load_history(&mut self) -> io::Result<()> {
        let file_name = match self.file_name.clone() {
            Some(name) => name,
            None => {
                return Err(Error::new(
                    ErrorKind::Other,
                    "Liner: file name not specified",
                ))
            }
        };
        let file = try!(OpenOptions::new().read(true).open(file_name));
        let reader = BufReader::new(file);
        for line in reader.lines() {
            match line {
                Ok(line) => self.buffers.push_back(Buffer::from(line)),
                Err(_) => break,
            }
        }
        Ok(())
    }

    fn buffers_ref(&self) -> &VecDeque<Buffer> {
        &self.buffers
    }
}

impl<'a> IntoIterator for &'a History {
    type Item = &'a Buffer;
    type IntoIter = vec_deque::Iter<'a, Buffer>;

    fn into_iter(self) -> Self::IntoIter {
        self.buffers_ref().into_iter()
    }
}

impl Index<usize> for History {
    type Output = Buffer;

    fn index(&self, index: usize) -> &Buffer {
        &self.buffers[index]
    }
}

impl IndexMut<usize> for History {
    fn index_mut(&mut self, index: usize) -> &mut Buffer {
        &mut self.buffers[index]
    }
}

/// Perform write operation. If the history file does not exist, it will be created.
/// This function is not part of the public interface.
/// XXX: include more information in the file (like fish does)
fn write_to_disk(max_file_size: usize, new_item: &Buffer, file_name: &str) -> io::Result<()> {
    let ret = match OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(file_name) {
        Ok(mut file) => {
            // The metadata contains the length of the file
            let file_length = file.metadata().ok().map_or(0u64, |m| m.len());
            // 4K byte buffer for reading chunks of the file at once.
            let mut buffer = [0; 4096];

            // Determine the number of commands stored.
            {
                let mut seek_point = 0u64;
                let mut stored = 0;
                let mut total_read = 0u64;
                let mut rfile = File::open(file_name).unwrap();
                loop {
                    // Read 4K of bytes all at once into the buffer.
                    let read = rfile.read(&mut buffer)?;
                    // If EOF is found, don't seek at all.
                    if read == 0 { break }
                    // Count the number of commands that were found in the current buffer.
                    let cmds_read = count(&buffer[0..read], b'\n');
                    // If stored + read >= max file size, a seek point is in the current buffer.
                    if stored + cmds_read >= max_file_size {
                        for &byte in buffer[0..read].iter() {
                            total_read += 1;
                            if byte == b'\n' {
                                stored += 1;
                                if stored == max_file_size {
                                    seek_point = total_read;
                                    break
                                }
                            }
                        }

                        try!(file.seek(SeekFrom::Start(seek_point as u64)));
                        let mut buffer: Vec<u8> = Vec::with_capacity((file_length - seek_point) as usize);
                        try!(file.read_to_end(&mut buffer));
                        try!(file.set_len(0));
                        try!(io::copy(&mut buffer.as_slice(), &mut file));
                        break
                    } else {
                        total_read += read as u64;
                        stored += cmds_read;
                    }
                }
            };

            // Seek to end for appending
            try!(file.seek(SeekFrom::End(0)));
            // Write the command to the history file.
            try!(file.write_all(String::from(new_item.clone()).as_bytes()));
            try!(file.write_all(b"\n"));
            file.flush()?;

            Ok(())
        }
        Err(message) => Err(message),
    };
    ret
}
<|endoftext|>