<commit_before>use std::{fmt, thread};
use std::io::{self, ErrorKind};
use std::net::{Ipv4Addr, SocketAddrV4, TcpListener, TcpStream};

use amy::{self, Poller, Registrar};

use torrent::peer::reader::Reader;
use {handle, CONFIG};
use util::UHashMap;

pub struct Listener {
    listener: TcpListener,
    lid: usize,
    incoming: UHashMap<(TcpStream, Reader)>,
    poll: Poller,
    reg: Registrar,
    ch: handle::Handle<Request, Message>,
}

pub struct Message {
    pub conn: TcpStream,
    pub reader: Reader,
    pub id: [u8; 20],
    pub hash: [u8; 20],
    pub rsv: [u8; 8],
}

impl fmt::Debug for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "listener msg for torrent: ")?;
        for byte in &self.hash {
            write!(f, "{:X}", byte)?;
        }
        Ok(())
    }
}

#[derive(Debug)]
pub enum Request {
    Shutdown,
}

const POLL_INT_MS: usize = 1000;

impl Listener {
    pub fn start(
        creg: &mut amy::Registrar,
    ) -> io::Result<(handle::Handle<Message, Request>, thread::JoinHandle<()>)> {
        let poll = Poller::new()?;
        let mut reg = poll.get_registrar();
        let ip = Ipv4Addr::new(0, 0, 0, 0);
        let port = CONFIG.port;
        let listener = TcpListener::bind(SocketAddrV4::new(ip, port))?;
        listener.set_nonblocking(true)?;
        let lid = reg.register(&listener, amy::Event::Both)?;

        let (ch, dh) = handle::Handle::new(creg, &mut reg)?;
        let th = dh.run("listener", move |h| {
            Listener {
                listener,
                lid,
                incoming: UHashMap::default(),
                poll,
                reg,
                ch: h,
            }.run()
        })?;
        Ok((ch, th))
    }

    pub fn run(&mut self) {
        debug!("Accepting connections!");
        while let Ok(res) = self.poll.wait(POLL_INT_MS) {
            for not in res {
                match not.id {
                    id if id == self.lid => self.handle_conn(),
                    id if id == self.ch.rx.get_id() => {
                        if let Ok(Request::Shutdown) = self.ch.recv() {
                            return;
                        }
                    }
                    _ => self.handle_peer(not),
                }
            }
        }
    }

    fn handle_conn(&mut self) {
        loop {
            match self.listener.accept() {
                Ok((conn, ip)) => {
                    debug!("Accepted new connection from {:?}!", ip);
                    let pid = self.reg.register(&conn, amy::Event::Read).unwrap();
                    self.incoming.insert(pid, (conn, Reader::new()));
                }
                Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
                    break;
                }
                _ => {
                    unimplemented!();
                }
            }
        }
    }

    fn handle_peer(&mut self, not: amy::Notification) {
        let pid = not.id;

        let res = {
            let &mut (ref mut conn, ref mut reader) = self.incoming.get_mut(&pid).unwrap();
            reader.readable(conn)
        };

        match res {
            Ok(Some(hs)) => {
                debug!("Completed handshake({:?}) with peer, transferring!", hs);
                let (conn, reader) = self.incoming.remove(&pid).unwrap();
                self.reg.deregister(&conn).unwrap();
                let hsd = hs.get_handshake_data();
                if self.ch
                    .send(Message {
                        conn,
                        reader,
                        hash: hsd.0,
                        id: hsd.1,
                        rsv: hsd.2,
                    })
                    .is_err()
                {
                    error!("failed to send peer to ctrl");
                }
            }
            Ok(None) => {}
            Err(_) => {
                debug!("Peer connection failed!");
                self.incoming.remove(&pid);
            }
        }
    }
}
<commit_msg>Set sockets as nonblocking in listener<commit_after>use std::{fmt, thread};
use std::io::{self, ErrorKind};
use std::net::{Ipv4Addr, SocketAddrV4, TcpListener, TcpStream};

use amy::{self, Poller, Registrar};

use torrent::peer::reader::Reader;
use {handle, CONFIG};
use util::UHashMap;

pub struct Listener {
    listener: TcpListener,
    lid: usize,
    incoming: UHashMap<(TcpStream, Reader)>,
    poll: Poller,
    reg: Registrar,
    ch: handle::Handle<Request, Message>,
}

pub struct Message {
    pub conn: TcpStream,
    pub reader: Reader,
    pub id: [u8; 20],
    pub hash: [u8; 20],
    pub rsv: [u8; 8],
}

impl fmt::Debug for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "listener msg for torrent: ")?;
        for byte in &self.hash {
            write!(f, "{:X}", byte)?;
        }
        Ok(())
    }
}

#[derive(Debug)]
pub enum Request {
    Shutdown,
}

const POLL_INT_MS: usize = 1000;

impl Listener {
    pub fn start(
        creg: &mut amy::Registrar,
    ) -> io::Result<(handle::Handle<Message, Request>, thread::JoinHandle<()>)> {
        let poll = Poller::new()?;
        let mut reg = poll.get_registrar();
        let ip = Ipv4Addr::new(0, 0, 0, 0);
        let port = CONFIG.port;
        let listener = TcpListener::bind(SocketAddrV4::new(ip, port))?;
        listener.set_nonblocking(true)?;
        let lid = reg.register(&listener, amy::Event::Both)?;

        let (ch, dh) = handle::Handle::new(creg, &mut reg)?;
        let th = dh.run("listener", move |h| {
            Listener {
                listener,
                lid,
                incoming: UHashMap::default(),
                poll,
                reg,
                ch: h,
            }.run()
        })?;
        Ok((ch, th))
    }

    pub fn run(&mut self) {
        debug!("Accepting connections!");
        while let Ok(res) = self.poll.wait(POLL_INT_MS) {
            for not in res {
                match not.id {
                    id if id == self.lid => self.handle_conn(),
                    id if id == self.ch.rx.get_id() => {
                        if let Ok(Request::Shutdown) = self.ch.recv() {
                            return;
                        }
                    }
                    _ => self.handle_peer(not),
                }
            }
        }
    }

    fn handle_conn(&mut self) {
        loop {
            match self.listener.accept() {
                Ok((conn, ip)) => {
                    debug!("Accepted new connection from {:?}!", ip);
                    if conn.set_nonblocking(true).is_err() {
                        continue;
                    }
                    let pid = self.reg.register(&conn, amy::Event::Read).unwrap();
                    self.incoming.insert(pid, (conn, Reader::new()));
                }
                Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
                    break;
                }
                _ => {
                    unimplemented!();
                }
            }
        }
    }

    fn handle_peer(&mut self, not: amy::Notification) {
        let pid = not.id;

        let res = {
            let &mut (ref mut conn, ref mut reader) = self.incoming.get_mut(&pid).unwrap();
            reader.readable(conn)
        };

        match res {
            Ok(Some(hs)) => {
                debug!("Completed handshake({:?}) with peer, transferring!", hs);
                let (conn, reader) = self.incoming.remove(&pid).unwrap();
                self.reg.deregister(&conn).unwrap();
                let hsd = hs.get_handshake_data();
                if self.ch
                    .send(Message {
                        conn,
                        reader,
                        hash: hsd.0,
                        id: hsd.1,
                        rsv: hsd.2,
                    })
                    .is_err()
                {
                    error!("failed to send peer to ctrl");
                }
            }
            Ok(None) => {}
            Err(_) => {
                debug!("Peer connection failed!");
                self.incoming.remove(&pid);
            }
        }
    }
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright 2014 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

//! The `metadata` module deals with metadata at the beginning of a FLAC stream.

use std::iter;
use error::{Result, fmt_err};
use input::ReadBytes;

#[derive(Clone, Copy)]
struct MetadataBlockHeader {
    is_last: bool,
    block_type: u8,
    length: u32,
}

/// The streaminfo metadata block, with important information about the stream.
#[derive(Clone, Copy)]
pub struct StreamInfo {
    // TODO: "size" would better be called "duration" for clarity.

    /// The minimum block size (in samples) used in the stream.
    pub min_block_size: u16,
    /// The maximum block size (in samples) used in the stream.
    pub max_block_size: u16,
    /// The minimum frame size (in bytes) used in the stream.
    pub min_frame_size: Option<u32>,
    /// The maximum frame size (in bytes) used in the stream.
    pub max_frame_size: Option<u32>,
    /// The sample rate in Hz.
    pub sample_rate: u32,
    /// The number of channels.
    pub channels: u32,
    /// The number of bits per sample.
    pub bits_per_sample: u32,
    /// The total number of inter-channel samples in the stream.
    pub samples: Option<u64>,
    /// MD5 signature of the unencoded audio data.
    pub md5sum: [u8; 16],
}

/// A seek point in the seek table.
#[derive(Clone, Copy)]
pub struct SeekPoint {
    /// Sample number of the first sample in the target frame, or 2^64 - 1 for a placeholder.
    pub sample: u64,
    /// Offset in bytes from the first byte of the first frame header to the first byte of the
    /// target frame's header.
    pub offset: u64,
    /// Number of samples in the target frame.
    pub samples: u16,
}

/// A seek table to aid seeking in the stream.
pub struct SeekTable {
    /// The seek points, sorted in ascending order by sample number.
    #[allow(dead_code)] // TODO: Implement seeking.
    seekpoints: Vec<SeekPoint>,
}

/// A metadata about the flac stream.
pub enum MetadataBlock {
    /// A stream info block.
    StreamInfo(StreamInfo),
    /// A padding block (with no meaningful data).
    Padding {
        /// The number of padding bytes.
        length: u32,
    },
    /// An application block with application-specific data.
    Application {
        /// The registered application ID.
        id: u32,
        /// The contents of the application block.
        data: Vec<u8>,
    },
    /// A seek table block.
    SeekTable(SeekTable),
    /// A Vorbis comment block, also known as FLAC tags.
    VorbisComment, // TODO
    /// A CUE sheet block.
    CueSheet, // TODO
    /// A picture block.
    Picture, // TODO
    /// A block with a reserved block type, not supported by this library.
    Reserved,
}

fn read_metadata_block_header<R: ReadBytes>(input: &mut R) -> Result<MetadataBlockHeader> {
    let byte = try!(input.read_u8());

    // The first bit specifies whether this is the last block, the next 7 bits
    // specify the type of the metadata block to follow.
    let is_last = (byte >> 7) == 1;
    let block_type = byte & 0b0111_1111;

    // The length field is 24 bits, or 3 bytes.
    let length = try!(input.read_be_u24());

    let header = MetadataBlockHeader {
        is_last: is_last,
        block_type: block_type,
        length: length,
    };
    Ok(header)
}

fn read_metadata_block<R: ReadBytes>(input: &mut R,
                                     block_type: u8,
                                     length: u32)
                                     -> Result<MetadataBlock> {
    match block_type {
        0 => {
            // The streaminfo block has a fixed size of 34 bytes.
            if length == 34 {
                let streaminfo = try!(read_streaminfo_block(input));
                Ok(MetadataBlock::StreamInfo(streaminfo))
            } else {
                fmt_err("invalid streaminfo metadata block length")
            }
        }
        1 => {
            try!(read_padding_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        }
        2 => {
            let (id, data) = try!(read_application_block(input, length));
            Ok(MetadataBlock::Application {
                id: id,
                data: data,
            })
        }
        3 => {
            // TODO: implement seektable reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        4 => {
            // TODO: implement Vorbis comment reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        5 => {
            // TODO: implement CUE sheet reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        6 => {
            // TODO: implement picture reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        127 => {
            // This code is invalid to avoid confusion with a frame sync code.
            fmt_err("invalid metadata block type")
        }
        _ => {
            // Any other block type is 'reserved' at the moment of writing. The
            // reference implementation reads it as an 'unknown' block. That is
            // one way of handling it, but maybe there should be some kind of
            // 'strict' mode (configurable at compile time?) so that this can
            // be an error if desired.
            try!(input.skip(length));
            Ok(MetadataBlock::Reserved)
        }
    }
}

fn read_streaminfo_block<R: ReadBytes>(input: &mut R) -> Result<StreamInfo> {
    let min_block_size = try!(input.read_be_u16());
    let max_block_size = try!(input.read_be_u16());

    // The frame size fields are 24 bits, or 3 bytes.
    let min_frame_size = try!(input.read_be_u24());
    let max_frame_size = try!(input.read_be_u24());

    // Next up are 20 bits that determine the sample rate.
    let sample_rate_msb = try!(input.read_be_u16());
    let sample_rate_lsb = try!(input.read_u8());

    // Stitch together the value from the first 16 bits,
    // and then the 4 most significant bits of the next byte.
    let sample_rate = (sample_rate_msb as u32) << 4 | (sample_rate_lsb as u32) >> 4;

    // Next three bits are the number of channels - 1. Mask them out and add 1.
    let n_channels_bps = sample_rate_lsb;
    let n_channels = ((n_channels_bps >> 1) & 0b0000_0111) + 1;

    // The final bit is the most significant of bits per sample - 1. Bits per
    // sample - 1 is 5 bits in total.
    let bps_msb = n_channels_bps & 1;
    let bps_lsb_n_samples = try!(input.read_u8());

    // Stitch together these values, add 1 because # - 1 is stored.
    let bits_per_sample = (bps_msb << 4 | (bps_lsb_n_samples >> 4)) + 1;

    // Number of samples in 36 bits, we have 4 already, 32 to go.
    let n_samples_msb = bps_lsb_n_samples & 0b0000_1111;
    let n_samples_lsb = try!(input.read_be_u32());
    let n_samples = (n_samples_msb as u64) << 32 | n_samples_lsb as u64;

    // Next are 128 bits (16 bytes) of MD5 signature.
    let mut md5sum = [0u8; 16];
    try!(input.read_into(&mut md5sum));

    // Lower bounds can never be larger than upper bounds. Note that 0 indicates
    // unknown for the frame size. Also, the block size must be at least 16.
    if min_block_size > max_block_size {
        return fmt_err("inconsistent bounds, min block size > max block size");
    }
    if min_block_size < 16 {
        return fmt_err("invalid block size, must be at least 16");
    }
    if min_frame_size > max_frame_size && max_frame_size != 0 {
        return fmt_err("inconsistent bounds, min frame size > max frame size");
    }

    // A sample rate of 0 is invalid, and the maximum sample rate is limited by
    // the structure of the frame headers to 655350 Hz.
    if sample_rate == 0 || sample_rate > 655350 {
        return fmt_err("invalid sample rate");
    }

    let stream_info = StreamInfo {
        min_block_size: min_block_size,
        max_block_size: max_block_size,
        min_frame_size: if min_frame_size == 0 {
            None
        } else {
            Some(min_frame_size)
        },
        max_frame_size: if max_frame_size == 0 {
            None
        } else {
            Some(max_frame_size)
        },
        sample_rate: sample_rate,
        channels: n_channels as u32,
        bits_per_sample: bits_per_sample as u32,
        samples: if n_samples == 0 {
            None
        } else {
            Some(n_samples)
        },
        md5sum: md5sum,
    };
    Ok(stream_info)
}

fn read_padding_block<R: ReadBytes>(input: &mut R, length: u32) -> Result<()> {
    // The specification dictates that all bits of the padding block must be 0.
    // However, the reference implementation does not issue an error when this
    // is not the case, and frankly, when you are going to skip over these
    // bytes and do nothing with them whatsoever, why waste all those CPU
    // cycles checking that the padding is valid?
    Ok(try!(input.skip(length)))
}

fn read_application_block<R: ReadBytes>(input: &mut R, length: u32) -> Result<(u32, Vec<u8>)> {
    let id = try!(input.read_be_u32());

    // Four bytes of the block have been used for the ID, the rest is payload.
    let mut data: Vec<u8> = iter::repeat(0).take(length as usize - 4).collect();
    try!(input.read_into(&mut data));

    Ok((id, data))
}

/// Reads metadata blocks from a stream and exposes them as an iterator.
///
/// It is assumed that the next byte that the reader will read, is the first
/// byte of a metadata block header. This means that the iterator will yield at
/// least a single value. If the iterator ever yields an error, then no more
/// data will be read thereafter, and the next value will be `None`.
pub struct MetadataBlockReader<R: ReadBytes> {
    input: R,
    done: bool,
}

/// Either a `MetadataBlock` or an `Error`.
pub type MetadataBlockResult = Result<MetadataBlock>;

impl<R: ReadBytes> MetadataBlockReader<R> {
    /// Creates a metadata block reader that will yield at least one element.
    pub fn new(input: R) -> MetadataBlockReader<R> {
        MetadataBlockReader {
            input: input,
            done: false,
        }
    }

    fn read_next(&mut self) -> MetadataBlockResult {
        let header = try!(read_metadata_block_header(&mut self.input));
        let block = try!(read_metadata_block(&mut self.input, header.block_type, header.length));
        self.done = header.is_last;
        Ok(block)
    }
}

impl<R: ReadBytes> Iterator for MetadataBlockReader<R> {
    type Item = MetadataBlockResult;

    fn next(&mut self) -> Option<MetadataBlockResult> {
        if self.done {
            None
        } else {
            let block = self.read_next();

            // After a failure, no more attempts to read will be made,
            // because we don't know where we are in the stream.
            if !block.is_ok() {
                self.done = true;
            }

            Some(block)
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        // When done, there will be no more blocks,
        // when not done, there will be at least one more.
        if self.done { (0, Some(0)) } else { (1, None) }
    }
}
<commit_msg>Report format error for small application blocks<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2014 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

//! The `metadata` module deals with metadata at the beginning of a FLAC stream.

use std::iter;
use error::{Result, fmt_err};
use input::ReadBytes;

#[derive(Clone, Copy)]
struct MetadataBlockHeader {
    is_last: bool,
    block_type: u8,
    length: u32,
}

/// The streaminfo metadata block, with important information about the stream.
#[derive(Clone, Copy)]
pub struct StreamInfo {
    // TODO: "size" would better be called "duration" for clarity.

    /// The minimum block size (in samples) used in the stream.
    pub min_block_size: u16,
    /// The maximum block size (in samples) used in the stream.
    pub max_block_size: u16,
    /// The minimum frame size (in bytes) used in the stream.
    pub min_frame_size: Option<u32>,
    /// The maximum frame size (in bytes) used in the stream.
    pub max_frame_size: Option<u32>,
    /// The sample rate in Hz.
    pub sample_rate: u32,
    /// The number of channels.
    pub channels: u32,
    /// The number of bits per sample.
    pub bits_per_sample: u32,
    /// The total number of inter-channel samples in the stream.
    pub samples: Option<u64>,
    /// MD5 signature of the unencoded audio data.
    pub md5sum: [u8; 16],
}

/// A seek point in the seek table.
#[derive(Clone, Copy)]
pub struct SeekPoint {
    /// Sample number of the first sample in the target frame, or 2^64 - 1 for a placeholder.
    pub sample: u64,
    /// Offset in bytes from the first byte of the first frame header to the first byte of the
    /// target frame's header.
    pub offset: u64,
    /// Number of samples in the target frame.
    pub samples: u16,
}

/// A seek table to aid seeking in the stream.
pub struct SeekTable {
    /// The seek points, sorted in ascending order by sample number.
    #[allow(dead_code)] // TODO: Implement seeking.
    seekpoints: Vec<SeekPoint>,
}

/// A metadata about the flac stream.
pub enum MetadataBlock {
    /// A stream info block.
    StreamInfo(StreamInfo),
    /// A padding block (with no meaningful data).
    Padding {
        /// The number of padding bytes.
        length: u32,
    },
    /// An application block with application-specific data.
    Application {
        /// The registered application ID.
        id: u32,
        /// The contents of the application block.
        data: Vec<u8>,
    },
    /// A seek table block.
    SeekTable(SeekTable),
    /// A Vorbis comment block, also known as FLAC tags.
    VorbisComment, // TODO
    /// A CUE sheet block.
    CueSheet, // TODO
    /// A picture block.
    Picture, // TODO
    /// A block with a reserved block type, not supported by this library.
    Reserved,
}

fn read_metadata_block_header<R: ReadBytes>(input: &mut R) -> Result<MetadataBlockHeader> {
    let byte = try!(input.read_u8());

    // The first bit specifies whether this is the last block, the next 7 bits
    // specify the type of the metadata block to follow.
    let is_last = (byte >> 7) == 1;
    let block_type = byte & 0b0111_1111;

    // The length field is 24 bits, or 3 bytes.
    let length = try!(input.read_be_u24());

    let header = MetadataBlockHeader {
        is_last: is_last,
        block_type: block_type,
        length: length,
    };
    Ok(header)
}

fn read_metadata_block<R: ReadBytes>(input: &mut R,
                                     block_type: u8,
                                     length: u32)
                                     -> Result<MetadataBlock> {
    match block_type {
        0 => {
            // The streaminfo block has a fixed size of 34 bytes.
            if length == 34 {
                let streaminfo = try!(read_streaminfo_block(input));
                Ok(MetadataBlock::StreamInfo(streaminfo))
            } else {
                fmt_err("invalid streaminfo metadata block length")
            }
        }
        1 => {
            try!(read_padding_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        }
        2 => {
            let (id, data) = try!(read_application_block(input, length));
            Ok(MetadataBlock::Application {
                id: id,
                data: data,
            })
        }
        3 => {
            // TODO: implement seektable reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        4 => {
            // TODO: implement Vorbis comment reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        5 => {
            // TODO: implement CUE sheet reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        6 => {
            // TODO: implement picture reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        127 => {
            // This code is invalid to avoid confusion with a frame sync code.
            fmt_err("invalid metadata block type")
        }
        _ => {
            // Any other block type is 'reserved' at the moment of writing. The
            // reference implementation reads it as an 'unknown' block. That is
            // one way of handling it, but maybe there should be some kind of
            // 'strict' mode (configurable at compile time?) so that this can
            // be an error if desired.
            try!(input.skip(length));
            Ok(MetadataBlock::Reserved)
        }
    }
}

fn read_streaminfo_block<R: ReadBytes>(input: &mut R) -> Result<StreamInfo> {
    let min_block_size = try!(input.read_be_u16());
    let max_block_size = try!(input.read_be_u16());

    // The frame size fields are 24 bits, or 3 bytes.
    let min_frame_size = try!(input.read_be_u24());
    let max_frame_size = try!(input.read_be_u24());

    // Next up are 20 bits that determine the sample rate.
    let sample_rate_msb = try!(input.read_be_u16());
    let sample_rate_lsb = try!(input.read_u8());

    // Stitch together the value from the first 16 bits,
    // and then the 4 most significant bits of the next byte.
    let sample_rate = (sample_rate_msb as u32) << 4 | (sample_rate_lsb as u32) >> 4;

    // Next three bits are the number of channels - 1. Mask them out and add 1.
    let n_channels_bps = sample_rate_lsb;
    let n_channels = ((n_channels_bps >> 1) & 0b0000_0111) + 1;

    // The final bit is the most significant of bits per sample - 1. Bits per
    // sample - 1 is 5 bits in total.
    let bps_msb = n_channels_bps & 1;
    let bps_lsb_n_samples = try!(input.read_u8());

    // Stitch together these values, add 1 because # - 1 is stored.
    let bits_per_sample = (bps_msb << 4 | (bps_lsb_n_samples >> 4)) + 1;

    // Number of samples in 36 bits, we have 4 already, 32 to go.
    let n_samples_msb = bps_lsb_n_samples & 0b0000_1111;
    let n_samples_lsb = try!(input.read_be_u32());
    let n_samples = (n_samples_msb as u64) << 32 | n_samples_lsb as u64;

    // Next are 128 bits (16 bytes) of MD5 signature.
    let mut md5sum = [0u8; 16];
    try!(input.read_into(&mut md5sum));

    // Lower bounds can never be larger than upper bounds. Note that 0 indicates
    // unknown for the frame size. Also, the block size must be at least 16.
    if min_block_size > max_block_size {
        return fmt_err("inconsistent bounds, min block size > max block size");
    }
    if min_block_size < 16 {
        return fmt_err("invalid block size, must be at least 16");
    }
    if min_frame_size > max_frame_size && max_frame_size != 0 {
        return fmt_err("inconsistent bounds, min frame size > max frame size");
    }

    // A sample rate of 0 is invalid, and the maximum sample rate is limited by
    // the structure of the frame headers to 655350 Hz.
    if sample_rate == 0 || sample_rate > 655350 {
        return fmt_err("invalid sample rate");
    }

    let stream_info = StreamInfo {
        min_block_size: min_block_size,
        max_block_size: max_block_size,
        min_frame_size: if min_frame_size == 0 {
            None
        } else {
            Some(min_frame_size)
        },
        max_frame_size: if max_frame_size == 0 {
            None
        } else {
            Some(max_frame_size)
        },
        sample_rate: sample_rate,
        channels: n_channels as u32,
        bits_per_sample: bits_per_sample as u32,
        samples: if n_samples == 0 {
            None
        } else {
            Some(n_samples)
        },
        md5sum: md5sum,
    };
    Ok(stream_info)
}

fn read_padding_block<R: ReadBytes>(input: &mut R, length: u32) -> Result<()> {
    // The specification dictates that all bits of the padding block must be 0.
    // However, the reference implementation does not issue an error when this
    // is not the case, and frankly, when you are going to skip over these
    // bytes and do nothing with them whatsoever, why waste all those CPU
    // cycles checking that the padding is valid?
    Ok(try!(input.skip(length)))
}

fn read_application_block<R: ReadBytes>(input: &mut R, length: u32) -> Result<(u32, Vec<u8>)> {
    if length < 4 {
        return fmt_err("application block length must be at least 4 bytes.")
    }

    let id = try!(input.read_be_u32());

    // Four bytes of the block have been used for the ID, the rest is payload.
    let mut data: Vec<u8> = iter::repeat(0).take(length as usize - 4).collect();
    try!(input.read_into(&mut data));

    Ok((id, data))
}

/// Reads metadata blocks from a stream and exposes them as an iterator.
///
/// It is assumed that the next byte that the reader will read, is the first
/// byte of a metadata block header. This means that the iterator will yield at
/// least a single value. If the iterator ever yields an error, then no more
/// data will be read thereafter, and the next value will be `None`.
pub struct MetadataBlockReader<R: ReadBytes> {
    input: R,
    done: bool,
}

/// Either a `MetadataBlock` or an `Error`.
pub type MetadataBlockResult = Result<MetadataBlock>;

impl<R: ReadBytes> MetadataBlockReader<R> {
    /// Creates a metadata block reader that will yield at least one element.
    pub fn new(input: R) -> MetadataBlockReader<R> {
        MetadataBlockReader {
            input: input,
            done: false,
        }
    }

    fn read_next(&mut self) -> MetadataBlockResult {
        let header = try!(read_metadata_block_header(&mut self.input));
        let block = try!(read_metadata_block(&mut self.input, header.block_type, header.length));
        self.done = header.is_last;
        Ok(block)
    }
}

impl<R: ReadBytes> Iterator for MetadataBlockReader<R> {
    type Item = MetadataBlockResult;

    fn next(&mut self) -> Option<MetadataBlockResult> {
        if self.done {
            None
        } else {
            let block = self.read_next();

            // After a failure, no more attempts to read will be made,
            // because we don't know where we are in the stream.
            if !block.is_ok() {
                self.done = true;
            }

            Some(block)
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        // When done, there will be no more blocks,
        // when not done, there will be at least one more.
        if self.done { (0, Some(0)) } else { (1, None) }
    }
}
<|endoftext|>


<commit_before>/*!
This module is for platform-specific stuff.
*/

pub use self::inner::{current_time, file_last_modified, get_cache_dir_for};

#[cfg(windows)]
pub mod inner {
    #![allow(non_snake_case)]

    extern crate ole32;
    extern crate shell32;
    extern crate winapi;
    extern crate uuid;

    use std::ffi::OsString;
    use std::fmt;
    use std::fs;
    use std::path::{Path, PathBuf};
    use std::mem;
    use std::os::windows::ffi::OsStringExt;
    use self::uuid::FOLDERID_LocalAppData;
    use error::MainError;

    /**
    Gets the last-modified time of a file, in milliseconds since the UNIX epoch.
    */
    pub fn file_last_modified(file: &fs::File) -> u64 {
        use ::std::os::windows::fs::MetadataExt;

        const MS_BETWEEN_1601_1970: u64 = 11_644_473_600_000;

        let mtime_100ns_1601_utc = file.metadata()
            .map(|md| md.last_write_time())
            .unwrap_or(0);
        let mtime_ms_1601_utc = mtime_100ns_1601_utc / (1000*10);

        // This can obviously underflow... but since files created prior to 1970 are going to be *somewhat rare*, I'm just going to saturate to zero.
        let mtime_ms_1970_utc = mtime_ms_1601_utc.saturating_sub(MS_BETWEEN_1601_1970);
        mtime_ms_1970_utc
    }

    /**
    Gets the current system time, in milliseconds since the UNIX epoch.
    */
    pub fn current_time() -> u64 {
        extern crate time;

        /*
        This is kinda dicey, since *ideally* both this function and `file_last_modified` would be using the same underlying APIs.  They are not, insofar as I know.
        */
        let mut now_1970_utc = time::now_utc().to_timespec();
        if now_1970_utc.sec < 0 || now_1970_utc.nsec < 0 {
            // Fuck it.
            now_1970_utc = time::Timespec::new(0, 0);
        }
        let now_ms_1970_utc = (now_1970_utc.sec as u64 * 1000)
            + (now_1970_utc.nsec as u64 / 1_000_000);
        now_ms_1970_utc
    }

    /**
    Get a directory suitable for storing user- and machine-specific data which may or may not be persisted across sessions.

    On Windows, LocalAppData is where user- and machine- specific data should go, but it *might* be more appropriate to use whatever the official name for "Program Data" is, though.
    */
    pub fn get_cache_dir_for<P>(product: P) -> Result<PathBuf, MainError>
    where P: AsRef<Path> {
        let dir = try!(SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, ::std::ptr::null_mut())
            .map_err(|e| e.to_string()));
        Ok(Path::new(&dir).to_path_buf().join(product))
    }

    type WinResult<T> = Result<T, WinError>;

    struct WinError(winapi::HRESULT);

    impl fmt::Display for WinError {
        fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            write!(fmt, "HRESULT({})", self.0)
        }
    }

    fn SHGetKnownFolderPath(rfid: &winapi::KNOWNFOLDERID, dwFlags: winapi::DWORD, hToken: winapi::HANDLE) -> WinResult<OsString> {
        use self::winapi::PWSTR;
        let mut psz_path: PWSTR = unsafe { mem::uninitialized() };
        let hresult = unsafe {
            shell32::SHGetKnownFolderPath(
                rfid,
                dwFlags,
                hToken,
                mem::transmute(&mut psz_path as &mut PWSTR as *mut PWSTR)
            )
        };

        if hresult == winapi::S_OK {
            let r = unsafe { pwstr_to_os_string(psz_path) };
            unsafe { ole32::CoTaskMemFree(psz_path as *mut _) };
            Ok(r)
        } else {
            Err(WinError(hresult))
        }
    }

    unsafe fn pwstr_to_os_string(ptr: winapi::PWSTR) -> OsString {
        OsStringExt::from_wide(::std::slice::from_raw_parts(ptr, pwstr_len(ptr)))
    }

    unsafe fn pwstr_len(mut ptr: winapi::PWSTR) -> usize {
        let mut len = 0;
        while *ptr != 0 {
            len += 1;
            ptr = ptr.offset(1);
        }
        len
    }
}
<commit_msg>Impl get_cache_dir_for for unix platforms<commit_after>/*!
This module is for platform-specific stuff.
*/

pub use self::inner::{current_time, file_last_modified, get_cache_dir_for};

#[cfg(unix)]
mod inner {
    use std::path::{Path, PathBuf};
    use error::{MainError, Blame};
    use std::env;

    pub fn get_cache_dir_for<P>(product: P) -> Result<PathBuf, MainError>
    where P: AsRef<Path> {
        let home = match env::var_os("HOME") {
            Some(val) => val,
            None => return Err((Blame::Human, "$HOME is not defined").into())
        };

        match product.as_ref().to_str() {
            Some(s) => {
                let folder = format!(".{}", s.to_lowercase());
                Ok(Path::new(&home).join(folder))
            },
            None => Err("product for `get_cache_dir_for` was not utf8".into())
        }
    }
}

#[cfg(windows)]
pub mod inner {
    #![allow(non_snake_case)]

    extern crate ole32;
    extern crate shell32;
    extern crate winapi;
    extern crate uuid;

    use std::ffi::OsString;
    use std::fmt;
    use std::fs;
    use std::path::{Path, PathBuf};
    use std::mem;
    use std::os::windows::ffi::OsStringExt;
    use self::uuid::FOLDERID_LocalAppData;
    use error::MainError;

    /**
    Gets the last-modified time of a file, in milliseconds since the UNIX epoch.
    */
    pub fn file_last_modified(file: &fs::File) -> u64 {
        use ::std::os::windows::fs::MetadataExt;

        const MS_BETWEEN_1601_1970: u64 = 11_644_473_600_000;

        let mtime_100ns_1601_utc = file.metadata()
            .map(|md| md.last_write_time())
            .unwrap_or(0);
        let mtime_ms_1601_utc = mtime_100ns_1601_utc / (1000*10);

        // This can obviously underflow... but since files created prior to 1970 are going to be *somewhat rare*, I'm just going to saturate to zero.
        let mtime_ms_1970_utc = mtime_ms_1601_utc.saturating_sub(MS_BETWEEN_1601_1970);
        mtime_ms_1970_utc
    }

    /**
    Gets the current system time, in milliseconds since the UNIX epoch.
    */
    pub fn current_time() -> u64 {
        extern crate time;

        /*
        This is kinda dicey, since *ideally* both this function and `file_last_modified` would be using the same underlying APIs.  They are not, insofar as I know.
        */
        let mut now_1970_utc = time::now_utc().to_timespec();
        if now_1970_utc.sec < 0 || now_1970_utc.nsec < 0 {
            // Fuck it.
            now_1970_utc = time::Timespec::new(0, 0);
        }
        let now_ms_1970_utc = (now_1970_utc.sec as u64 * 1000)
            + (now_1970_utc.nsec as u64 / 1_000_000);
        now_ms_1970_utc
    }

    /**
    Get a directory suitable for storing user- and machine-specific data which may or may not be persisted across sessions.

    On Windows, LocalAppData is where user- and machine- specific data should go, but it *might* be more appropriate to use whatever the official name for "Program Data" is, though.
    */
    pub fn get_cache_dir_for<P>(product: P) -> Result<PathBuf, MainError>
    where P: AsRef<Path> {
        let dir = try!(SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, ::std::ptr::null_mut())
            .map_err(|e| e.to_string()));
        Ok(Path::new(&dir).to_path_buf().join(product))
    }

    type WinResult<T> = Result<T, WinError>;

    struct WinError(winapi::HRESULT);

    impl fmt::Display for WinError {
        fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            write!(fmt, "HRESULT({})", self.0)
        }
    }

    fn SHGetKnownFolderPath(rfid: &winapi::KNOWNFOLDERID, dwFlags: winapi::DWORD, hToken: winapi::HANDLE) -> WinResult<OsString> {
        use self::winapi::PWSTR;
        let mut psz_path: PWSTR = unsafe { mem::uninitialized() };
        let hresult = unsafe {
            shell32::SHGetKnownFolderPath(
                rfid,
                dwFlags,
                hToken,
                mem::transmute(&mut psz_path as &mut PWSTR as *mut PWSTR)
            )
        };

        if hresult == winapi::S_OK {
            let r = unsafe { pwstr_to_os_string(psz_path) };
            unsafe { ole32::CoTaskMemFree(psz_path as *mut _) };
            Ok(r)
        } else {
            Err(WinError(hresult))
        }
    }

    unsafe fn pwstr_to_os_string(ptr: winapi::PWSTR) -> OsString {
        OsStringExt::from_wide(::std::slice::from_raw_parts(ptr, pwstr_len(ptr)))
    }

    unsafe fn pwstr_len(mut ptr: winapi::PWSTR) -> usize {
        let mut len = 0;
        while *ptr != 0 {
            len += 1;
            ptr = ptr.offset(1);
        }
        len
    }
}
<|endoftext|>


<commit_before>use libc;
use ram::repr;
use ram::tombstone::TOMBSTONE_SIZE_U32;
use std::sync::atomic::{AtomicUsize, AtomicU32, AtomicI64, Ordering};
use std::collections::BTreeSet;
use bifrost::utils::async_locks::{RwLock, RwLockReadGuard};

use super::cell::CellHeader;

pub const SEGMENT_SIZE: usize = 8 * 1024 * 1024;

pub struct Segment {
    pub id: u64,
    pub addr: usize,
    pub bound: usize,
    pub append_header: AtomicUsize,
    pub dead_space: AtomicU32,
    pub tombstones: AtomicU32,
    pub dead_tombstones: AtomicU32,
    pub last_tombstones_scanned: AtomicI64,
    pub lock: RwLock<()>,
}

impl Segment {
    pub fn new(id: u64, size: usize) -> Segment {
        let buffer_ptr = libc::malloc(size) as usize;
        Segment {
            addr: buffer_ptr,
            id,
            bound: buffer_ptr + size,
            append_header: AtomicUsize::new(buffer_ptr),
            dead_space: AtomicU32::new(0),
            tombstones: AtomicU32::new(0),
            dead_tombstones: AtomicU32::new(0),
            last_tombstones_scanned: AtomicI64::new(0),
            lock: RwLock::new(()),
        }
    }

    // TODO: employ async lock
    pub fn try_acquire(&self, size: u32) -> Option<(usize, RwLockReadGuard<()>)> {
        let size = size as usize;
        let rl = self.lock.read();
        loop {
            let curr_last = self.append_header.load(Ordering::SeqCst);
            let exp_last = curr_last + size;
            if exp_last > self.bound {
                return None;
            } else {
                if self.append_header.compare_and_swap(curr_last, exp_last, Ordering::SeqCst) != curr_last {
                    continue;
                } else {
                    return Some((curr_last, rl));
                }
            }
        }
    }

    pub fn entry_iter(&self) -> SegmentEntryIter {
        SegmentEntryIter {
            bound: self.bound,
            cursor: self.addr,
            lock_guard: self.lock.read()
        }
    }

    fn total_dead_space(&self) -> u32 {
        let dead_tombstones_space = self.dead_tombstones.load(Ordering::Relaxed) * TOMBSTONE_SIZE_U32;
        let dead_cells_space = self.dead_space.load(Ordering::Relaxed);
        return dead_tombstones_space + dead_cells_space;
    }

    pub fn living_rate(&self) -> f32 {
        let used_spaces = (self.append_header.load(Ordering::Relaxed) - self.addr) as f32;
        let total_dead_space = self.total_dead_space() as f32;
        let living_space = used_spaces - total_dead_space;
        return living_space / used_spaces;
    }

    fn dispose (&self) {
        debug!("disposing chunk at {}", self.addr);
        unsafe {
            libc::free(self.addr as *mut libc::c_void)
        }
    }
}

pub struct SegmentEntryIter {
    bound: usize,
    cursor: usize,
    lock_guard: RwLockReadGuard<()>,
}

impl Iterator for SegmentEntryIter {
    type Item = (repr::Entry, usize);

    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        let cursor = self.cursor;
        if cursor >= self.bound {
            return None;
        }
        let (entry, entry_size) = repr::Entry::decode_from(
            cursor,
            |body_pos, entry| {
                let entry_header_size = body_pos - cursor;
                return entry_header_size + entry.content_length as usize;
            });
        self.cursor += entry_size;
        return Some((entry, cursor));
    }
}

impl Drop for Segment {
    fn drop(&mut self) {
        self.dispose()
    }
}<commit_msg>comment on segment lock<commit_after>use libc;
use ram::repr;
use ram::tombstone::TOMBSTONE_SIZE_U32;
use std::sync::atomic::{AtomicUsize, AtomicU32, AtomicI64, Ordering};
use std::collections::BTreeSet;
use bifrost::utils::async_locks::{RwLock, RwLockReadGuard};

use super::cell::CellHeader;

pub const SEGMENT_SIZE: usize = 8 * 1024 * 1024;

pub struct Segment {
    pub id: u64,
    pub addr: usize,
    pub bound: usize,
    pub append_header: AtomicUsize,
    pub dead_space: AtomicU32,
    pub tombstones: AtomicU32,
    pub dead_tombstones: AtomicU32,
    pub last_tombstones_scanned: AtomicI64,
    // this spin lock is used only for preventing early segment deletion on cleaning
    // all normal operations, including first stage of compaction should use read lock
    pub lock: RwLock<()>,
}

impl Segment {
    pub fn new(id: u64, size: usize) -> Segment {
        let buffer_ptr = libc::malloc(size) as usize;
        Segment {
            addr: buffer_ptr,
            id,
            bound: buffer_ptr + size,
            append_header: AtomicUsize::new(buffer_ptr),
            dead_space: AtomicU32::new(0),
            tombstones: AtomicU32::new(0),
            dead_tombstones: AtomicU32::new(0),
            last_tombstones_scanned: AtomicI64::new(0),
            lock: RwLock::new(()),
        }
    }

    pub fn try_acquire(&self, size: u32) -> Option<(usize, RwLockReadGuard<()>)> {
        let size = size as usize;
        let rl = self.lock.read();
        loop {
            let curr_last = self.append_header.load(Ordering::SeqCst);
            let exp_last = curr_last + size;
            if exp_last > self.bound {
                return None;
            } else {
                if self.append_header.compare_and_swap(curr_last, exp_last, Ordering::SeqCst) != curr_last {
                    continue;
                } else {
                    return Some((curr_last, rl));
                }
            }
        }
    }

    pub fn entry_iter(&self) -> SegmentEntryIter {
        SegmentEntryIter {
            bound: self.bound,
            cursor: self.addr,
            lock_guard: self.lock.read()
        }
    }

    fn total_dead_space(&self) -> u32 {
        let dead_tombstones_space = self.dead_tombstones.load(Ordering::Relaxed) * TOMBSTONE_SIZE_U32;
        let dead_cells_space = self.dead_space.load(Ordering::Relaxed);
        return dead_tombstones_space + dead_cells_space;
    }

    pub fn living_rate(&self) -> f32 {
        let used_spaces = (self.append_header.load(Ordering::Relaxed) - self.addr) as f32;
        let total_dead_space = self.total_dead_space() as f32;
        let living_space = used_spaces - total_dead_space;
        return living_space / used_spaces;
    }

    fn dispose (&self) {
        debug!("disposing chunk at {}", self.addr);
        unsafe {
            libc::free(self.addr as *mut libc::c_void)
        }
    }
}

pub struct SegmentEntryIter {
    bound: usize,
    cursor: usize,
    lock_guard: RwLockReadGuard<()>,
}

impl Iterator for SegmentEntryIter {
    type Item = (repr::Entry, usize);

    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        let cursor = self.cursor;
        if cursor >= self.bound {
            return None;
        }
        let (entry, entry_size) = repr::Entry::decode_from(
            cursor,
            |body_pos, entry| {
                let entry_header_size = body_pos - cursor;
                return entry_header_size + entry.content_length as usize;
            });
        self.cursor += entry_size;
        return Some((entry, cursor));
    }
}

impl Drop for Segment {
    fn drop(&mut self) {
        self.dispose()
    }
}<|endoftext|>


<commit_before>//! jsonrpc response
use serde::{Serialize, Serializer};
use super::{Id, Value, Error, Version};

#[derive(Debug, PartialEq, Serialize)]
pub struct Success {
	pub jsonrpc: Version,
	pub result: Value,
	pub id: Id
}

#[derive(Debug, PartialEq, Serialize)]
pub struct Failure {
	pub jsonrpc: Version,
	pub error: Error,
	pub id: Id
}

#[derive(Debug, PartialEq)]
pub enum Output {
	Success(Success),
	Failure(Failure)
}

impl Serialize for Output {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		match *self {
			Output::Success(ref s) => s.serialize(serializer),
			Output::Failure(ref f) => f.serialize(serializer)
		}
	}
}

#[derive(Debug, PartialEq)]
pub enum Response {
	Single(Output),
	Batch(Vec<Output>)
}

impl Serialize for Response {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		match *self {
			Response::Single(ref o) => o.serialize(serializer),
			Response::Batch(ref b) => b.serialize(serializer)
		}
	}
}

#[test]
fn success_output_serialize() {
	use serde_json;
	use serde_json::Value;

	let so = Output::Success(Success {
		jsonrpc: Version::V2,
		result: Value::U64(1),
		id: Id::Num(1)
	});

	let serialized = serde_json::to_string(&so).unwrap();
	assert_eq!(serialized, r#"{"jsonrpc":"2.0","result":1,"id":1}"#);
}

#[test]
fn failure_output_serialize() {
	use serde_json;
	use serde_json::Value;

	let fo = Output::Failure(Failure {
		jsonrpc: Version::V2,
		error: Error::parse_error(),
		id: Id::Num(1)
	});

	let serialized = serde_json::to_string(&fo).unwrap();
	assert_eq!(serialized, r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":1}"#);
}

<commit_msg>Add Unit Tests for Output and Response Deserialization<commit_after>//! jsonrpc response
use serde::{Serialize, Serializer};
use super::{Id, Value, Error, Version};

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Success {
	pub jsonrpc: Version,
	pub result: Value,
	pub id: Id
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Failure {
	pub jsonrpc: Version,
	pub error: Error,
	pub id: Id
}

#[derive(Debug, PartialEq, Deserialize)]
pub enum Output {
	Success(Success),
	Failure(Failure)
}

impl Serialize for Output {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		match *self {
			Output::Success(ref s) => s.serialize(serializer),
			Output::Failure(ref f) => f.serialize(serializer)
		}
	}
}

#[derive(Debug, PartialEq, Deserialize)]
pub enum Response {
	Single(Output),
	Batch(Vec<Output>)
}

impl Serialize for Response {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		match *self {
			Response::Single(ref o) => o.serialize(serializer),
			Response::Batch(ref b) => b.serialize(serializer)
		}
	}
}

#[test]
fn success_output_serialize() {
	use serde_json;
	use serde_json::Value;

	let so = Output::Success(Success {
		jsonrpc: Version::V2,
		result: Value::U64(1),
		id: Id::Num(1)
	});

	let serialized = serde_json::to_string(&so).unwrap();
	assert_eq!(serialized, r#"{"jsonrpc":"2.0","result":1,"id":1}"#);
}

#[test]
fn success_output_deserialize() {
	use serde_json;
	use serde_json::Value;

	let dso = r#"{"jsonrpc":"2.0","result":1,"id":1}"#;

	let deserialized: Output = serde_json::from_str(dso).unwrap();
	assert_eq!(deserialized, Output::Success(Success {
		jsonrpc: Version::V2,
		result: Value::U64(1),
		id: Id::Num(1)
	}));
}

#[test]
fn failure_output_serialize() {
	use serde_json;
	use serde_json::Value;

	let fo = Output::Failure(Failure {
		jsonrpc: Version::V2,
		error: Error::parse_error(),
		id: Id::Num(1)
	});

	let serialized = serde_json::to_string(&fo).unwrap();
	assert_eq!(serialized, r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error","data":null},"id":1}"#);
}

#[test]
fn failure_output_deserialize() {
	use serde_json;
	use serde_json::Value;

	let dfo = r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":1}"#;

	let deserialized: Output = serde_json::from_str(dfo).unwrap();
	assert_eq!(deserialized, Output::Failure(Failure {
		jsonrpc: Version::V2,
		error: Error::parse_error(),
		id: Id::Num(1)
	}));
}

#[test]
fn single_response_deserialize() {
	use serde_json;
	use serde_json::Value;

	let dsr = r#"{"jsonrpc":"2.0","result":1,"id":1}"#;

	let deserialized: Response = serde_json::from_str(dsr).unwrap();
	assert_eq!(deserialized, Response::Single(Output::Success(Success {
		jsonrpc: Version::V2,
		result: Value::U64(1),
		id: Id::Num(1)
	})));
}

#[test]
fn batch_response_deserialize() {
	use serde_json;
	use serde_json::Value;

	let dbr = r#"[{"jsonrpc":"2.0","result":1,"id":1},{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":1}]"#;

	let deserialized: Response = serde_json::from_str(dbr).unwrap();
	assert_eq!(deserialized, Response::Batch(vec![
		Output::Success(Success {
			jsonrpc: Version::V2,
			result: Value::U64(1),
			id: Id::Num(1)
		}),
		Output::Failure(Failure {
			jsonrpc: Version::V2,
			error: Error::parse_error(),
			id: Id::Num(1)
		})
	]));
}

<|endoftext|>


<commit_before>use color::Color;
use dimensions::Dimensions;
use graphics;
use graphics::{
    Graphics,
};
use graphics::character::CharacterCache;
use label;
use label::FontSize;
use mouse::Mouse;
use piston::input::keyboard::Key::{
    Backspace,
    Left,
    Right,
    Return,
};
use point::Point;
use rectangle;
use std::num::Float;
use clock_ticks::precise_time_s;
use ui_context::{
    Id,
    UIID,
    UiContext,
};
use vecmath::{
    vec2_add,
    vec2_sub,
};
use widget::{ DefaultWidgetState, Widget };
use std::cmp;
use Callback;
use FrameColor;
use FrameWidth;
use Position;
use Size;

pub type Idx = usize;
pub type CursorX = f64;

/// Represents the state of the text_box widget.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum State {
    Capturing(Captured),
    Uncaptured(rectangle::State),
}

/// Whether the textbox is currently captured or not.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Captured {
    Cursor(Idx),
    Selection(Idx, Idx)
}

/// Represents an element of the TextBox widget.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Element {
    Char(Idx),
    Nill,
    Rect,
}

impl Element {
    fn idx(&self) -> Idx {
        match *self {
            Element::Char(idx) => idx,
            Element::Nill | Element::Rect => 0,
        }
    }
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match *self {
            State::Capturing(_) => rectangle::State::Normal,
            State::Uncaptured(state) => state,
        }
    }
}

widget_fns!(TextBox, State, Widget::TextBox(State::Uncaptured(rectangle::State::Normal)));

static TEXT_PADDING: f64 = 5f64;

/// Find the position of a character in a text box.
fn cursor_position<C: CharacterCache>(uic: &mut UiContext<C>,
                 mut idx: usize,
                 mut text_x: f64,
                 font_size: FontSize,
                 text: &str) -> (Idx, CursorX) {
    if idx == 0 { return (0, text_x); }
    let text_len = text.len();
    if idx > text_len { idx = text_len; }
    for (i, ch) in text.chars().enumerate() {
        if i >= idx { break; }
        text_x += uic.get_character(font_size, ch).width();
    }
    (idx, text_x)
}

/// Check if cursor is over the pad and if so, which
fn over_elem<C: CharacterCache>(uic: &mut UiContext<C>,
             pos: Point,
             mouse_pos: Point,
             rect_dim: Dimensions,
             pad_pos: Point,
             pad_dim: Dimensions,
             text_pos: Point,
             text_w: f64,
             font_size: FontSize,
             text: &str) -> Element {
    match rectangle::is_over(pos, mouse_pos, rect_dim) {
        false => Element::Nill,
        true => match rectangle::is_over(pad_pos, mouse_pos, pad_dim) {
            false => Element::Rect,
            true => {
                let (idx, _) = closest_idx(uic, mouse_pos, text_pos[0], text_w, font_size, text);
                Element::Char(idx)
            },
        },
    }
}

/// Check which character is closest to the mouse cursor.
fn closest_idx<C: CharacterCache>(uic: &mut UiContext<C>,
               mouse_pos: Point,
               text_x: f64,
               text_w: f64,
               font_size: FontSize,
               text: &str) -> (Idx, f64) {
    if mouse_pos[0] <= text_x { return (0, text_x) }
    let mut x = text_x;
    let mut prev_x = x;
    let mut left_x = text_x;
    for (i, ch) in text.chars().enumerate() {
        let character = uic.get_character(font_size, ch);
        let char_w = character.width();
        x += char_w;
        let right_x = prev_x + char_w / 2.0;
        if mouse_pos[0] > left_x && mouse_pos[0] < right_x { return (i, prev_x) }
        prev_x = x;
        left_x = right_x;
    }
    (text.len(), text_x + text_w)
}

/// Check and return the current state of the TextBox.
fn get_new_state(over_elem: Element, prev_state: State, mouse: Mouse) -> State {
    use mouse::ButtonState::{ Down, Up };
    use rectangle::State::{ Normal, Highlighted, Clicked };
    use self::State::{ Capturing, Uncaptured };
    use self::Captured::{ Cursor, Selection };

    match prev_state {
        State::Capturing(prev) => match mouse.left {
            Down => match prev {
                Cursor(idx) => prev_state,// move the cursor to the new position
                Selection(start, end) => prev_state, // update the selection
            },
            Up => match prev {
                // Only way for there not to be a selection
                Cursor(_) => prev_state,
                Selection(start, end) => prev_state,
            },
        },
        State::Uncaptured(prev) => match (mouse.left) {
            Down => Capturing(Cursor(over_elem.idx())),
            Up => prev_state,
        },
    }
}

/// Draw the text cursor.
fn draw_cursor<B: Graphics>(
    win_w: f64,
    win_h: f64,
    graphics: &mut B,
    color: Color,
    cursor_x: f64,
    pad_pos_y: f64,
    pad_h: f64
) {
    let draw_state = graphics::default_draw_state();
    let transform = graphics::abs_transform(win_w, win_h);
    let Color(color) = color.plain_contrast();
    let (r, g, b, a) = (color[0], color[1], color[2], color[3]);
    graphics::Line::round([r, g, b, (a * (precise_time_s() * 2.5).sin() as f32).abs()], 0.5f64)
        .draw(
            [cursor_x, pad_pos_y, cursor_x, pad_pos_y + pad_h],
            draw_state,
            transform,
            graphics
        );
}

/// A context on which the builder pattern can be implemented.
pub struct TextBox<'a, F> {
    ui_id: UIID,
    text: &'a mut String,
    font_size: u32,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
}

impl<'a, F> TextBox<'a, F> {
    pub fn font_size(self, font_size: FontSize) -> TextBox<'a, F> {
        TextBox { font_size: font_size, ..self }
    }
}

impl<'a, F> TextBox<'a, F> {
    /// Initialise a TextBoxContext.
    pub fn new(ui_id: UIID, text: &'a mut String) -> TextBox<'a, F> {
        TextBox {
            ui_id: ui_id,
            text: text,
            font_size: 24, // Default font_size.
            pos: [0.0, 0.0],
            dim: [192.0, 48.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
        }
    }

    fn selection_rect<C: CharacterCache>
                     (&self, uic: &mut UiContext<C>, text_x: f64, mut start: Idx, end: Idx) ->
                     (Point, Dimensions) {
        if start != 0 { start -= 1; }
        let (_, pos) = cursor_position(uic, start, text_x, self.font_size, &self.text);
        let htext: String = self.text.chars().skip(start).take(end - start).collect();
        let htext_w = label::width(uic, self.font_size, &htext);
        ([pos, self.pos[1]], [htext_w, self.dim[1]])
    }
}

quack! {
    tb: TextBox['a, F]
    get:
        fn () -> Size [] { Size(tb.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(
                Widget::TextBox(State::Uncaptured(rectangle::State::Normal))
            )
        }
        fn () -> Id [] { Id(tb.ui_id) }
    set:
        fn (val: Color) [] { tb.maybe_color = Some(val) }
        fn (val: Callback<F>) [where F: FnMut(&mut String) + 'a] {
            tb.maybe_callback = Some(val.0)
        }
        fn (val: FrameColor) [] { tb.maybe_frame_color = Some(val.0) }
        fn (val: FrameWidth) [] { tb.maybe_frame = Some(val.0) }
        fn (val: Position) [] { tb.pos = val.0 }
        fn (val: Size) [] { tb.dim = val.0 }
    action:
}

impl<'a, F> ::draw::Drawable for TextBox<'a, F>
    where
        F: FnMut(&mut String) + 'a
{

    #[inline]
    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {
        let mouse = uic.get_mouse_state();
        let state = *get_state(uic, self.ui_id);

        // Rect.
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let frame_w2 = frame_w * 2.0;
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };
        let pad_pos = vec2_add(self.pos, [frame_w; 2]);
        let pad_dim = vec2_sub(self.dim, [frame_w2; 2]);
        let text_x = pad_pos[0] + TEXT_PADDING;
        let text_y = pad_pos[1] + (pad_dim[1] - self.font_size as f64) / 2.0;
        let text_pos = [text_x, text_y];
        let text_w = label::width(uic, self.font_size, &self.text);
        let over_elem = over_elem(uic, self.pos, mouse.pos, self.dim,
                                  pad_pos, pad_dim, text_pos, text_w,
                                  self.font_size, &self.text);
        let new_state = get_new_state(over_elem, state, mouse);

        rectangle::draw(uic.win_w, uic.win_h, graphics, new_state.as_rectangle_state(),
                        self.pos, self.dim, maybe_frame, color);

        if let State::Capturing(Captured::Selection(start, end)) = new_state {
            let (pos, dim) = self.selection_rect(uic, text_x, start, end);
            rectangle::draw(uic.win_w, uic.win_h, graphics, new_state.as_rectangle_state(),
                            pos, dim, maybe_frame, color);
        }

        uic.draw_text(graphics, text_pos, self.font_size,
                           color.plain_contrast(), &self.text);

        let new_state = match new_state {
            State::Uncaptured(_) => new_state,
            State::Capturing(Captured::Selection(..)) => new_state,
            State::Capturing(Captured::Cursor(idx)) => {
                let (idx, cursor_x) = cursor_position(uic, idx, text_x, self.font_size, &self.text);
                draw_cursor(uic.win_w, uic.win_h, graphics, color,
                            cursor_x, pad_pos[1], pad_dim[1]);
                let mut new_idx = idx;
                let mut new_cursor_x = cursor_x;

                // Check for entered text.
                let entered_text = uic.get_entered_text();
                for t in entered_text.iter() {
                    let mut entered_text_width = 0.0;
                    for ch in t[..].chars() {
                        let c = uic.get_character(self.font_size, ch);
                        entered_text_width += c.width();
                    }
                    if new_cursor_x + entered_text_width < pad_pos[0] + pad_dim[0] - TEXT_PADDING {
                        new_cursor_x += entered_text_width;
                    }
                    else {
                        break;
                    }
                    let new_text = format!("{}{}{}", &self.text[..idx], t, &self.text[idx..]);
                    *self.text = new_text;
                    new_idx += t.len();
                }

                // Check for control keys.
                let pressed_keys = uic.get_pressed_keys();
                for key in pressed_keys.iter() {
                    match *key {
                        Backspace => {
                            if self.text.len() > 0
                            && self.text.len() >= idx
                            && idx > 0 {
                                let rem_idx = idx - 1;
                                new_cursor_x -= uic.get_character_w(
                                    self.font_size, self.text[..].char_at(rem_idx)
                                );
                                let new_text = format!("{}{}", &self.text[..rem_idx], &self.text[idx..]);
                                *self.text = new_text;
                                new_idx = rem_idx;
                            }
                        },
                        Left => {
                            if idx > 0 {
                                new_cursor_x -= uic.get_character_w(
                                    self.font_size, self.text[..].char_at(idx - 1)
                                );
                                new_idx -= 1;
                            }
                        },
                        Right => {
                            if self.text.len() > idx {
                                new_cursor_x += uic.get_character_w(
                                    self.font_size, self.text[..].char_at(idx)
                                );
                                new_idx += 1;
                            }
                        },
                        Return => if self.text.len() > 0 {
                            let TextBox { // borrowck
                                ref mut maybe_callback,
                                ref font_size,
                                ref mut text,
                                ..
                            } = *self;
                            match *maybe_callback {
                                Some(ref mut callback) => {
                                    (*callback)(*text);

                                    new_idx = cmp::min(new_idx, text.len());
                                    let text = &*text;
                                    new_cursor_x = text.chars()
                                                       // Add text_pos.x for padding
                                                       .fold(text_pos[0], |acc, c| {
                                        acc + uic.get_character_w(*font_size, c)
                                    });
                                },
                                None => (),
                            }
                        },
                        _ => (),
                    }
                }

                State::Capturing(Captured::Cursor(new_idx))
            },
        };

        set_state(uic, self.ui_id, Widget::TextBox(new_state), self.pos, self.dim);

    }
}
<commit_msg>add support for text selection with mouse<commit_after>use color::Color;
use dimensions::Dimensions;
use graphics;
use graphics::{
    Graphics,
};
use graphics::character::CharacterCache;
use label;
use label::FontSize;
use mouse::Mouse;
use piston::input::keyboard::Key::{
    Backspace,
    Left,
    Right,
    Return,
};
use point::Point;
use rectangle;
use std::num::Float;
use clock_ticks::precise_time_s;
use ui_context::{
    Id,
    UIID,
    UiContext,
};
use vecmath::{
    vec2_add,
    vec2_sub,
};
use widget::{ DefaultWidgetState, Widget };
use std::cmp;
use Callback;
use FrameColor;
use FrameWidth;
use Position;
use Size;

pub type Idx = usize;
pub type CursorX = f64;

/// Represents the state of the text_box widget.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum State {
    Capturing(Selection),
    Uncaptured(Uncaptured),
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Selection {
    anchor: Anchor,
    start: Idx,
    end: Idx,
}

impl Selection {
    fn from_index(idx: Idx) -> Selection {
        Selection {anchor: Anchor::Start, start: idx, end: idx }
    }

    fn from_range(start: Idx, end: Idx) -> Selection {
        if start < end {
            Selection { anchor: Anchor::Start, start: start, end: end }
        } else {
            Selection { anchor: Anchor::End, start: end, end: start }
        }
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Anchor {
    None,
    Start,
    End,
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Uncaptured {
    Highlighted,
    Normal,
}

/// Represents an element of the TextBox widget.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Element {
    Char(Idx),
    Nill,
    Rect,
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match *self {
            State::Capturing(_) => rectangle::State::Normal,
            State::Uncaptured(state) => match state {
                Uncaptured::Highlighted => rectangle::State::Highlighted,
                Uncaptured::Normal => rectangle::State::Normal,
            }
        }
    }
}

widget_fns!(TextBox, State, Widget::TextBox(State::Uncaptured(Uncaptured::Normal)));

static TEXT_PADDING: f64 = 5f64;

/// Find the position of a character in a text box.
fn cursor_position<C: CharacterCache>(uic: &mut UiContext<C>,
                 mut idx: usize,
                 mut text_x: f64,
                 font_size: FontSize,
                 text: &str) -> (Idx, CursorX) {
    if idx == 0 { return (0, text_x); }
    let text_len = text.len();
    if idx > text_len { idx = text_len; }
    for (i, ch) in text.chars().enumerate() {
        if i >= idx { break; }
        text_x += uic.get_character(font_size, ch).width();
    }
    (idx, text_x)
}

/// Check if cursor is over the pad and if so, which
fn over_elem<C: CharacterCache>(uic: &mut UiContext<C>,
             pos: Point,
             mouse_pos: Point,
             rect_dim: Dimensions,
             pad_pos: Point,
             pad_dim: Dimensions,
             text_pos: Point,
             text_w: f64,
             font_size: FontSize,
             text: &str) -> Element {
    match rectangle::is_over(pos, mouse_pos, rect_dim) {
        false => Element::Nill,
        true => match rectangle::is_over(pad_pos, mouse_pos, pad_dim) {
            false => Element::Rect,
            true => {
                let (idx, _) = closest_idx(uic, mouse_pos, text_pos[0], text_w, font_size, text);
                Element::Char(idx)
            },
        },
    }
}

/// Check which character is closest to the mouse cursor.
fn closest_idx<C: CharacterCache>(uic: &mut UiContext<C>,
               mouse_pos: Point,
               text_x: f64,
               text_w: f64,
               font_size: FontSize,
               text: &str) -> (Idx, f64) {
    if mouse_pos[0] <= text_x { return (0, text_x) }
    let mut x = text_x;
    let mut prev_x = x;
    let mut left_x = text_x;
    for (i, ch) in text.chars().enumerate() {
        let character = uic.get_character(font_size, ch);
        let char_w = character.width();
        x += char_w;
        let right_x = prev_x + char_w / 2.0;
        if mouse_pos[0] > left_x && mouse_pos[0] <= right_x { return (i, prev_x) }
        prev_x = x;
        left_x = right_x;
    }
    (text.len(), text_x + text_w)
}

/// Check and return the current state of the TextBox.
fn get_new_state(over_elem: Element, prev_state: State, mouse: Mouse) -> State {
    use mouse::ButtonState::{ Down, Up };
    use self::State::{ Capturing, Uncaptured };
    use self::Uncaptured::{ Normal, Highlighted };

    match prev_state {
        State::Capturing(prev) => match mouse.left {
            Down => match over_elem {
                Element::Nill => if prev.anchor == Anchor::None {
                    Uncaptured(Normal)
                } else {
                    prev_state
                },
                Element::Rect =>  if prev.anchor == Anchor::None {
                    Capturing(Selection::from_index(0))
                } else {
                    prev_state
                },
                Element::Char(idx) => match prev.anchor {
                    Anchor::None => Capturing(Selection::from_index(idx)),
                    Anchor::Start => Capturing(Selection::from_range(prev.start, idx)),
                    Anchor::End => Capturing(Selection::from_range(prev.end, idx)),
                },
            },
            Up => Capturing(Selection { anchor: Anchor::None, .. prev })
        },

        State::Uncaptured(prev) => match mouse.left {
            Down => match over_elem {
                Element::Nill => Uncaptured(Normal),
                Element::Rect => match prev {
                    Normal => prev_state,
                    Highlighted => Capturing(Selection::from_index(0)),
                },
                Element::Char(idx) =>  match prev {
                    Normal => prev_state,
                    Highlighted => Capturing(Selection::from_index(idx)),
                },
            },
            Up => match over_elem {
                Element::Nill => Uncaptured(Normal),
                Element::Char(_) | Element::Rect => match prev {
                    Normal => Uncaptured(Highlighted),
                    Highlighted => prev_state,
                },
            },
        },
    }
}

/// Draw the text cursor.
fn draw_cursor<B: Graphics>(
    win_w: f64,
    win_h: f64,
    graphics: &mut B,
    color: Color,
    cursor_x: f64,
    pad_pos_y: f64,
    pad_h: f64
) {
    let draw_state = graphics::default_draw_state();
    let transform = graphics::abs_transform(win_w, win_h);
    let Color(color) = color.plain_contrast();
    let (r, g, b, a) = (color[0], color[1], color[2], color[3]);
    graphics::Line::round([r, g, b, (a * (precise_time_s() * 2.5).sin() as f32).abs()], 0.5f64)
        .draw(
            [cursor_x, pad_pos_y, cursor_x, pad_pos_y + pad_h],
            draw_state,
            transform,
            graphics
        );
}

/// A context on which the builder pattern can be implemented.
pub struct TextBox<'a, F> {
    ui_id: UIID,
    text: &'a mut String,
    font_size: u32,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
}

impl<'a, F> TextBox<'a, F> {
    pub fn font_size(self, font_size: FontSize) -> TextBox<'a, F> {
        TextBox { font_size: font_size, ..self }
    }
}

impl<'a, F> TextBox<'a, F> {
    /// Initialise a TextBoxContext.
    pub fn new(ui_id: UIID, text: &'a mut String) -> TextBox<'a, F> {
        TextBox {
            ui_id: ui_id,
            text: text,
            font_size: 24, // Default font_size.
            pos: [0.0, 0.0],
            dim: [192.0, 48.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
        }
    }

    fn selection_rect<C: CharacterCache>
                     (&self, uic: &mut UiContext<C>, text_x: f64, start: Idx, end: Idx) ->
                     (Point, Dimensions) {
        let (_, pos) = cursor_position(uic, start, text_x, self.font_size, &self.text);
        let htext: String = self.text.chars().skip(start).take(end - start).collect();
        let htext_w = label::width(uic, self.font_size, &htext);
        ([pos, self.pos[1]], [htext_w, self.dim[1]])
    }
}

quack! {
    tb: TextBox['a, F]
    get:
        fn () -> Size [] { Size(tb.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(
                Widget::TextBox(State::Uncaptured(Uncaptured::Normal))
            )
        }
        fn () -> Id [] { Id(tb.ui_id) }
    set:
        fn (val: Color) [] { tb.maybe_color = Some(val) }
        fn (val: Callback<F>) [where F: FnMut(&mut String) + 'a] {
            tb.maybe_callback = Some(val.0)
        }
        fn (val: FrameColor) [] { tb.maybe_frame_color = Some(val.0) }
        fn (val: FrameWidth) [] { tb.maybe_frame = Some(val.0) }
        fn (val: Position) [] { tb.pos = val.0 }
        fn (val: Size) [] { tb.dim = val.0 }
    action:
}

impl<'a, F> ::draw::Drawable for TextBox<'a, F>
    where
        F: FnMut(&mut String) + 'a
{

    #[inline]
    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {
        let mouse = uic.get_mouse_state();
        let state = *get_state(uic, self.ui_id);

        // Rect.
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let frame_w2 = frame_w * 2.0;
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };
        let pad_pos = vec2_add(self.pos, [frame_w; 2]);
        let pad_dim = vec2_sub(self.dim, [frame_w2; 2]);
        let text_x = pad_pos[0] + TEXT_PADDING;
        let text_y = pad_pos[1] + (pad_dim[1] - self.font_size as f64) / 2.0;
        let text_pos = [text_x, text_y];
        let text_w = label::width(uic, self.font_size, &self.text);
        let over_elem = over_elem(uic, self.pos, mouse.pos, self.dim,
                                  pad_pos, pad_dim, text_pos, text_w,
                                  self.font_size, &self.text);
        let mut new_state = get_new_state(over_elem, state, mouse);

        rectangle::draw(uic.win_w, uic.win_h, graphics, new_state.as_rectangle_state(),
                        self.pos, self.dim, maybe_frame, color);

        if let State::Capturing(selection) = new_state {
            if selection.start != selection.end {
                let (pos, dim) = self.selection_rect(uic, text_x, selection.start, selection.end);
                rectangle::draw(uic.win_w, uic.win_h, graphics, new_state.as_rectangle_state(),
                                [pos[0], pos[1] + frame_w], [dim[0], dim[1] - frame_w2],
                                None, color.highlighted());
            }
        }

        uic.draw_text(graphics, text_pos, self.font_size, color.plain_contrast(), &self.text);

        if let State::Capturing(selection) = new_state {
            if selection.start == selection.end {
            let (idx, cursor_x) = cursor_position(uic, selection.start, text_x, self.font_size, &self.text);
            draw_cursor(uic.win_w, uic.win_h, graphics, color, cursor_x, pad_pos[1], pad_dim[1]);
            let mut new_idx = idx;
            let mut new_cursor_x = cursor_x;

            // Check for entered text.
            let entered_text = uic.get_entered_text();
            for t in entered_text.iter() {
                let mut entered_text_width = 0.0;
                for ch in t[..].chars() {
                    let c = uic.get_character(self.font_size, ch);
                    entered_text_width += c.width();
                }
                if new_cursor_x + entered_text_width < pad_pos[0] + pad_dim[0] - TEXT_PADDING {
                    new_cursor_x += entered_text_width;
                }
                else {
                    break;
                }
                let new_text = format!("{}{}{}", &self.text[..idx], t, &self.text[idx..]);
                *self.text = new_text;
                new_idx += t.len();
            }

            // Check for control keys.
            let pressed_keys = uic.get_pressed_keys();
            for key in pressed_keys.iter() {
                match *key {
                    Backspace => {
                        if self.text.len() > 0
                        && self.text.len() >= idx
                        && idx > 0 {
                            let rem_idx = idx - 1;
                            new_cursor_x -= uic.get_character_w(
                                self.font_size, self.text[..].char_at(rem_idx)
                            );
                            let new_text = format!("{}{}", &self.text[..rem_idx], &self.text[idx..]);
                            *self.text = new_text;
                            new_idx = rem_idx;
                        }
                    },
                    Left => {
                        if idx > 0 {
                            new_cursor_x -= uic.get_character_w(
                                self.font_size, self.text[..].char_at(idx - 1)
                            );
                            new_idx -= 1;
                        }
                    },
                    Right => {
                        if self.text.len() > idx {
                            new_cursor_x += uic.get_character_w(
                                self.font_size, self.text[..].char_at(idx)
                            );
                            new_idx += 1;
                        }
                    },
                    Return => if self.text.len() > 0 {
                        let TextBox { // borrowck
                            ref mut maybe_callback,
                            ref font_size,
                            ref mut text,
                            ..
                        } = *self;
                        match *maybe_callback {
                            Some(ref mut callback) => {
                                (*callback)(*text);
                                new_idx = cmp::min(new_idx, text.len());
                                let text = &*text;
                                new_cursor_x = text.chars()
                                                   // Add text_pos.x for padding
                                                   .fold(text_pos[0], |acc, c| {
                                    acc + uic.get_character_w(*font_size, c)
                                });
                            },
                            None => (),
                        }
                    },
                    _ => (),
                }
            }
            new_state = State::Capturing(Selection { start: new_idx, end: new_idx, .. selection });
        }}
        set_state(uic, self.ui_id, Widget::TextBox(new_state), self.pos, self.dim);
    }
}
<|endoftext|>


<commit_before>use num::{BigUint, Integer, Zero, One};
use rand::{Rng, Rand};
use std::io;
use std::ops::{Mul, Rem, Shr};
use std::fs;
use std::path::Path;
use time;

mod int128;
mod spotify_id;
mod arcvec;
mod subfile;

pub use util::int128::u128;
pub use util::spotify_id::{SpotifyId, FileId};
pub use util::arcvec::ArcVec;
pub use util::subfile::Subfile;

#[macro_export]
macro_rules! eprintln(
    ($($arg:tt)*) => (
        {
            use std::io::Write;
            writeln!(&mut ::std::io::stderr(), $($arg)* ).unwrap()
        }
    )
);
#[macro_export]
macro_rules! eprint(
    ($($arg:tt)*) => (
        {
            use std::io::Write;
            write!(&mut ::std::io::stderr(), $($arg)* ).unwrap()
        }
    )
);

pub fn rand_vec<G: Rng, R: Rand>(rng: &mut G, size: usize) -> Vec<R> {
    rng.gen_iter().take(size).collect()
}

pub fn hexdump(data: &[u8]) {
    for b in data.iter() {
        eprint!("{:02X} ", b);
    }
    eprintln!("");
}

pub trait IgnoreExt {
    fn ignore(self);
}

impl<T, E> IgnoreExt for Result<T, E> {
    fn ignore(self) {
        match self {
            Ok(_) => (),
            Err(_) => (),
        }
    }
}

pub fn now_ms() -> i64 {
    let ts = time::now_utc().to_timespec();
    ts.sec * 1000 + ts.nsec as i64 / 1000000
}

pub fn mkdir_existing(path: &Path) -> io::Result<()> {
    fs::create_dir(path).or_else(|err| {
        if err.kind() == io::ErrorKind::AlreadyExists {
            Ok(())
        } else {
            Err(err)
        }
    })
}

pub fn powm(base: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
    let mut base = base.clone();
    let mut exp = exp.clone();
    let mut result: BigUint = One::one();

    while !exp.is_zero() {
        if exp.is_odd() {
            result = result.mul(&base).rem(modulus);
        }
        exp = exp.shr(1);
        base = (&base).mul(&base).rem(modulus);
    }

    result
}

pub struct StrChunks<'s>(&'s str, usize);

pub trait StrChunksExt {
    fn chunks(&self, size: usize) -> StrChunks;
}

impl StrChunksExt for str {
    fn chunks(&self, size: usize) -> StrChunks {
        StrChunks(self, size)
    }
}

impl<'s> Iterator for StrChunks<'s> {
    type Item = &'s str;
    fn next(&mut self) -> Option<&'s str> {
        let &mut StrChunks(data, size) = self;
        if data.is_empty() {
            None
        } else {
            let ret = Some(&data[..size]);
            self.0 = &data[size..];
            ret
        }
    }
}

pub trait ReadSeek : ::std::io::Read + ::std::io::Seek { }
impl <T: ::std::io::Read + ::std::io::Seek> ReadSeek for T { }

<commit_msg>Remove unused eprintln macro and hex dump function.<commit_after>use num::{BigUint, Integer, Zero, One};
use rand::{Rng, Rand};
use std::io;
use std::ops::{Mul, Rem, Shr};
use std::fs;
use std::path::Path;
use time;

mod int128;
mod spotify_id;
mod arcvec;
mod subfile;

pub use util::int128::u128;
pub use util::spotify_id::{SpotifyId, FileId};
pub use util::arcvec::ArcVec;
pub use util::subfile::Subfile;

pub fn rand_vec<G: Rng, R: Rand>(rng: &mut G, size: usize) -> Vec<R> {
    rng.gen_iter().take(size).collect()
}

pub trait IgnoreExt {
    fn ignore(self);
}

impl<T, E> IgnoreExt for Result<T, E> {
    fn ignore(self) {
        match self {
            Ok(_) => (),
            Err(_) => (),
        }
    }
}

pub fn now_ms() -> i64 {
    let ts = time::now_utc().to_timespec();
    ts.sec * 1000 + ts.nsec as i64 / 1000000
}

pub fn mkdir_existing(path: &Path) -> io::Result<()> {
    fs::create_dir(path).or_else(|err| {
        if err.kind() == io::ErrorKind::AlreadyExists {
            Ok(())
        } else {
            Err(err)
        }
    })
}

pub fn powm(base: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
    let mut base = base.clone();
    let mut exp = exp.clone();
    let mut result: BigUint = One::one();

    while !exp.is_zero() {
        if exp.is_odd() {
            result = result.mul(&base).rem(modulus);
        }
        exp = exp.shr(1);
        base = (&base).mul(&base).rem(modulus);
    }

    result
}

pub struct StrChunks<'s>(&'s str, usize);

pub trait StrChunksExt {
    fn chunks(&self, size: usize) -> StrChunks;
}

impl StrChunksExt for str {
    fn chunks(&self, size: usize) -> StrChunks {
        StrChunks(self, size)
    }
}

impl<'s> Iterator for StrChunks<'s> {
    type Item = &'s str;
    fn next(&mut self) -> Option<&'s str> {
        let &mut StrChunks(data, size) = self;
        if data.is_empty() {
            None
        } else {
            let ret = Some(&data[..size]);
            self.0 = &data[size..];
            ret
        }
    }
}

pub trait ReadSeek : ::std::io::Read + ::std::io::Seek { }
impl <T: ::std::io::Read + ::std::io::Seek> ReadSeek for T { }

<|endoftext|>