<commit_before>use std::io;

use super::{Numeric, SignedNumeric, BitQueueBE, BitQueueLE, BitQueue};

/// For reading bit values from an underlying stream
/// in a given endianness.
pub trait BitRead {
    /// Reads an unsigned value from the stream with
    /// the given number of bits.  This method assumes
    /// that the programmer is using an output type
    /// sufficiently large to hold those bits.
    fn read<U>(&mut self, bits: u32) -> Result<U, io::Error>
        where U: Numeric;

    /// Reads a twos-complement signed value from the stream with
    /// the given number of bits.  This method assumes
    /// that the programmer is using an output type
    /// sufficiently large to hold those bits.
    fn read_signed<S>(&mut self, bits: u32) -> Result<S, io::Error>
        where S: SignedNumeric;

    /// Skips the given number of bits in the stream.
    /// Since this method does not need an accumulator,
    /// it may be slightly faster than reading to an empty variable.
    /// In addition, since there is no accumulator,
    /// there is no upper limit on the number of bytes
    /// which may be skipped.
    /// These bytes are still read from the stream, however,
    /// and are never skipped via a `seek` method.
    fn skip(&mut self, bits: u32) -> Result<(), io::Error>;

    /// Completely fills the given buffer with whole bytes.
    /// If the stream is already byte-aligned, it will map
    /// to a faster `read_exact` call.  Otherwise it will read
    /// bytes individually in 8-bit increments.
    fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), io::Error>;

    /// Reads an unsigned unary value with a stop bit of 0.
    fn read_unary0(&mut self) -> Result<u32, io::Error> {
        /*FIXME - optimize this*/
        let mut acc = 0;
        while self.read::<u32>(1)? != 0 {
            acc += 1;
        }
        Ok(acc)
    }

    /// Reads an unsigned unary value with a stop bit of 1.
    fn read_unary1(&mut self) -> Result<u32, io::Error> {
        /*FIXME - optimize this*/
        let mut acc = 0;
        while self.read::<u32>(1)? != 1 {
            acc += 1;
        }
        Ok(acc)
    }

    /// Returns true if the stream is aligned at a whole byte.
    fn byte_aligned(&self) -> bool;

    /// Throws away all unread bit values until the next whole byte.
    fn byte_align(&mut self);

    /*FIXME - add support for reading Huffman codes*/
}

/// A wrapper for reading values from a big-endian stream.
pub struct BitReaderBE<'a> {
    reader: &'a mut io::BufRead,
    bitqueue: BitQueueBE<u8>
}

impl<'a> BitReaderBE<'a> {
    /// Wraps a big-endian reader around a `BufRead` reference.
    ///
    /// A `BufRead` is required because this reader is liable
    /// to make many small reads to the stream in normal operation,
    /// so reading from the buffer directly is preferable
    /// to making many calls to `read_exact`.
    pub fn new(reader: &mut io::BufRead) -> BitReaderBE {
        BitReaderBE{reader: reader, bitqueue: BitQueueBE::new()}
    }
}

impl<'a> BitRead for BitReaderBE<'a> {
    fn read<U>(&mut self, mut bits: u32) -> Result<U, io::Error>
        where U: Numeric {
        use std::cmp::min;
        let mut acc: BitQueueBE<U> = BitQueueBE::new();

        /*transfer un-processed bits from queue to accumulator*/
        let queue_len = self.bitqueue.len();
        if queue_len > 0 {
            let to_transfer = min(queue_len, bits);
            acc.push(to_transfer, U::from_u8(self.bitqueue.pop(to_transfer)));
            bits -= to_transfer;
        }

        read_aligned(&mut self.reader, bits / 8, &mut acc)
        .and_then(|()| read_unaligned(&mut self.reader,
                                      bits % 8,
                                      &mut acc,
                                      &mut self.bitqueue))
        .map(|()| acc.value())
    }

    fn skip(&mut self, mut bits: u32) -> Result<(), io::Error> {
        use std::cmp::min;

        let queue_len = self.bitqueue.len();
        if queue_len > 0 {
            let to_drop = min(queue_len, bits);
            self.bitqueue.pop(to_drop);
            bits -= to_drop;
        }

        skip_aligned(&mut self.reader, bits / 8)
        .and_then(|()| skip_unaligned(&mut self.reader,
                                      bits % 8,
                                      &mut self.bitqueue))
    }

    fn read_signed<S>(&mut self, bits: u32) -> Result<S, io::Error>
        where S: SignedNumeric {
        debug_assert!(bits >= 1);
        let sign = self.read::<S>(1)?;
        let unsigned = self.read::<S>(bits - 1)?;
        Ok(if sign.is_zero() {unsigned} else{unsigned.as_negative(bits)})
    }

    fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), io::Error> {
        if self.byte_aligned() {
            self.reader.read_exact(buf)
        } else {
            for b in buf.iter_mut() {
                *b = self.read::<u8>(8)?;
            }
            Ok(())
        }
    }

    #[inline]
    fn byte_aligned(&self) -> bool {
        self.bitqueue.is_empty()
    }

    #[inline]
    fn byte_align(&mut self) {
        self.bitqueue.clear()
    }
}

/// A wrapper for reading values from a little-endian stream.
pub struct BitReaderLE<'a> {
    reader: &'a mut io::BufRead,
    bitqueue: BitQueueLE<u8>
}

impl<'a> BitReaderLE<'a> {
    /// Wraps a little-endian reader around a `BufRead` reference.
    ///
    /// A `BufRead` is required because this reader is liable
    /// to make many small reads to the stream in normal operation,
    /// so reading from the buffer directly is preferable
    /// to making many calls to `read_exact`.
    pub fn new(reader: &mut io::BufRead) -> BitReaderLE {
        BitReaderLE{reader: reader, bitqueue: BitQueueLE::new()}
    }
}

impl<'a> BitRead for BitReaderLE<'a> {
    fn read<U>(&mut self, mut bits: u32) -> Result<U, io::Error>
        where U: Numeric {
        use std::cmp::min;

        let mut acc: BitQueueLE<U> = BitQueueLE::new();

        /*transfer un-processed bits from queue to accumulator*/
        let queue_len = self.bitqueue.len();
        if queue_len > 0 {
            let to_transfer = min(queue_len, bits);
            acc.push(to_transfer, U::from_u8(self.bitqueue.pop(to_transfer)));
            bits -= to_transfer;
        }

        read_aligned(&mut self.reader, bits / 8, &mut acc)
        .and_then(|()| read_unaligned(&mut self.reader,
                                      bits % 8,
                                      &mut acc,
                                      &mut self.bitqueue))
        .map(|()| acc.value())
    }

    fn skip(&mut self, mut bits: u32) -> Result<(), io::Error> {
        use std::cmp::min;

        let queue_len = self.bitqueue.len();
        if queue_len > 0 {
            let to_drop = min(queue_len, bits);
            self.bitqueue.pop(to_drop);
            bits -= to_drop;
        }

        skip_aligned(&mut self.reader, bits / 8)
        .and_then(|()| skip_unaligned(&mut self.reader,
                                      bits % 8,
                                      &mut self.bitqueue))
    }

    fn read_signed<S>(&mut self, bits: u32) -> Result<S, io::Error>
        where S: SignedNumeric {
        debug_assert!(bits >= 1);
        let unsigned = self.read::<S>(bits - 1)?;
        let sign = self.read::<S>(1)?;
        Ok(if sign.is_zero() {unsigned} else {unsigned.as_negative(bits)})
    }

    fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), io::Error> {
        if self.byte_aligned() {
            self.reader.read_exact(buf)
        } else {
            for b in buf.iter_mut() {
                *b = self.read::<u8>(8)?;
            }
            Ok(())
        }
    }

    #[inline]
    fn byte_aligned(&self) -> bool {
        self.bitqueue.is_empty()
    }

    #[inline]
    fn byte_align(&mut self) {
        self.bitqueue.clear()
    }
}

fn read_aligned<N>(reader: &mut io::BufRead,
                   mut bytes: u32,
                   acc: &mut BitQueue<N>) -> Result<(), io::Error>
    where N: Numeric {
    use std::cmp::min;

    while bytes > 0 {
        let processed = {
            let buf = reader.fill_buf()?;
            let to_process = min(bytes as usize, buf.len());
            for b in &buf[0..to_process] {
                acc.push(8, N::from_u8(*b));
            }
            to_process
        };
        if processed > 0 {
            reader.consume(processed);
            bytes -= processed as u32;
        } else {
            return Err(io::Error::new(
                io::ErrorKind::UnexpectedEof, "EOF in stream"));
        }
    }
    Ok(())
}

fn read_unaligned<N>(reader: &mut io::BufRead,
                     bits: u32,
                     acc: &mut BitQueue<N>,
                     rem: &mut BitQueue<u8>) -> Result<(), io::Error>
    where N: Numeric {

    debug_assert!(bits <= 8);

    if bits > 0 {
        let length = {
            let buf = reader.fill_buf()?;
            if buf.len() > 0 {
                rem.set(buf[0], 8);
                acc.push(bits, N::from_u8(rem.pop(bits)));
                1
            } else {0}
        };
        if length > 0 {
            Ok(reader.consume(length))
        } else {
            Err(io::Error::new(
                io::ErrorKind::UnexpectedEof, "EOF in stream"))
        }
    } else {
        Ok(())
    }
}

fn skip_aligned(reader: &mut io::BufRead,
                mut bytes: u32) -> Result<(), io::Error> {
    use std::cmp::min;

    while bytes > 0 {
        let processed = {
            let buf = reader.fill_buf()?;
            let to_process = min(bytes as usize, buf.len());
            to_process
        };
        if processed > 0 {
            reader.consume(processed);
            bytes -= processed as u32;
        } else {
            return Err(io::Error::new(
                io::ErrorKind::UnexpectedEof, "EOF in stream"));
        }
    }
    Ok(())
}

fn skip_unaligned(reader: &mut io::BufRead,
                  bits: u32,
                  rem: &mut BitQueue<u8>) -> Result<(), io::Error> {
    debug_assert!(bits <= 8);

    if bits > 0 {
        let length = {
            let buf = reader.fill_buf()?;
            if buf.len() > 0 {
                rem.set(buf[0], 8);
                rem.pop(bits);
                1
            } else {0}
        };
        if length > 0 {
            Ok(reader.consume(length))
        } else {
            Err(io::Error::new(
                io::ErrorKind::UnexpectedEof, "EOF in stream"))
        }
    } else {
        Ok(())
    }
}
<commit_msg>Add lengthy read test<commit_after>use std::io;

use super::{Numeric, SignedNumeric, BitQueueBE, BitQueueLE, BitQueue};

/// For reading bit values from an underlying stream
/// in a given endianness.
///
/// ## Example
/// ```
/// use std::io::Cursor;
/// use bitstream_io::{BitRead, BitReaderBE};
///
/// let flac: Vec<u8> = vec![0x66,0x4C,0x61,0x43,0x00,0x00,0x00,0x22,
///                          0x10,0x00,0x10,0x00,0x00,0x06,0x06,0x00,
///                          0x21,0x62,0x0A,0xC4,0x42,0xF0,0x00,0x04,
///                          0xA6,0xCC,0xFA,0xF2,0x69,0x2F,0xFD,0xEC,
///                          0x2D,0x5B,0x30,0x01,0x76,0xB4,0x62,0x88,
///                          0x7D,0x92];
///
/// let mut cursor = Cursor::new(&flac);
/// let mut reader = BitReaderBE::new(&mut cursor);
/// let mut file_header: [u8; 4] = [0, 0, 0, 0];
/// reader.read_bytes(&mut file_header).unwrap();
/// assert_eq!(&file_header, b"fLaC");
///
/// let last_block: u8 = reader.read(1).unwrap();
/// let block_type: u8 = reader.read(7).unwrap();
/// let block_size: u32 = reader.read(24).unwrap();
/// assert_eq!(last_block, 0);
/// assert_eq!(block_type, 0);
/// assert_eq!(block_size, 34);
///
/// let minimum_block_size: u16 = reader.read(16).unwrap();
/// let maximum_block_size: u16 = reader.read(16).unwrap();
/// let minimum_frame_size: u32 = reader.read(24).unwrap();
/// let maximum_frame_size: u32 = reader.read(24).unwrap();
/// let sample_rate: u32 = reader.read(20).unwrap();
/// let channels = reader.read::<u8>(3).unwrap() + 1;
/// let bits_per_sample = reader.read::<u8>(5).unwrap() + 1;
/// let total_samples: u64 = reader.read(36).unwrap();
/// assert_eq!(minimum_block_size, 4096);
/// assert_eq!(maximum_block_size, 4096);
/// assert_eq!(minimum_frame_size, 1542);
/// assert_eq!(maximum_frame_size, 8546);
/// assert_eq!(sample_rate, 44100);
/// assert_eq!(channels, 2);
/// assert_eq!(bits_per_sample, 16);
/// assert_eq!(total_samples, 304844);
///
/// let mut md5: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
/// reader.read_bytes(&mut md5).unwrap();
/// assert_eq!(&md5,
///     b"\xFA\xF2\x69\x2F\xFD\xEC\x2D\x5B\x30\x01\x76\xB4\x62\x88\x7D\x92");
/// ```
pub trait BitRead {
    /// Reads an unsigned value from the stream with
    /// the given number of bits.  This method assumes
    /// that the programmer is using an output type
    /// sufficiently large to hold those bits.
    fn read<U>(&mut self, bits: u32) -> Result<U, io::Error>
        where U: Numeric;

    /// Reads a twos-complement signed value from the stream with
    /// the given number of bits.  This method assumes
    /// that the programmer is using an output type
    /// sufficiently large to hold those bits.
    fn read_signed<S>(&mut self, bits: u32) -> Result<S, io::Error>
        where S: SignedNumeric;

    /// Skips the given number of bits in the stream.
    /// Since this method does not need an accumulator,
    /// it may be slightly faster than reading to an empty variable.
    /// In addition, since there is no accumulator,
    /// there is no upper limit on the number of bytes
    /// which may be skipped.
    /// These bytes are still read from the stream, however,
    /// and are never skipped via a `seek` method.
    fn skip(&mut self, bits: u32) -> Result<(), io::Error>;

    /// Completely fills the given buffer with whole bytes.
    /// If the stream is already byte-aligned, it will map
    /// to a faster `read_exact` call.  Otherwise it will read
    /// bytes individually in 8-bit increments.
    fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), io::Error>;

    /// Reads an unsigned unary value with a stop bit of 0.
    fn read_unary0(&mut self) -> Result<u32, io::Error> {
        /*FIXME - optimize this*/
        let mut acc = 0;
        while self.read::<u32>(1)? != 0 {
            acc += 1;
        }
        Ok(acc)
    }

    /// Reads an unsigned unary value with a stop bit of 1.
    fn read_unary1(&mut self) -> Result<u32, io::Error> {
        /*FIXME - optimize this*/
        let mut acc = 0;
        while self.read::<u32>(1)? != 1 {
            acc += 1;
        }
        Ok(acc)
    }

    /// Returns true if the stream is aligned at a whole byte.
    fn byte_aligned(&self) -> bool;

    /// Throws away all unread bit values until the next whole byte.
    fn byte_align(&mut self);

    /*FIXME - add support for reading Huffman codes*/
}

/// A wrapper for reading values from a big-endian stream.
pub struct BitReaderBE<'a> {
    reader: &'a mut io::BufRead,
    bitqueue: BitQueueBE<u8>
}

impl<'a> BitReaderBE<'a> {
    /// Wraps a big-endian reader around a `BufRead` reference.
    ///
    /// A `BufRead` is required because this reader is liable
    /// to make many small reads to the stream in normal operation,
    /// so reading from the buffer directly is preferable
    /// to making many calls to `read_exact`.
    pub fn new(reader: &mut io::BufRead) -> BitReaderBE {
        BitReaderBE{reader: reader, bitqueue: BitQueueBE::new()}
    }
}

impl<'a> BitRead for BitReaderBE<'a> {
    fn read<U>(&mut self, mut bits: u32) -> Result<U, io::Error>
        where U: Numeric {
        use std::cmp::min;
        let mut acc: BitQueueBE<U> = BitQueueBE::new();

        /*transfer un-processed bits from queue to accumulator*/
        let queue_len = self.bitqueue.len();
        if queue_len > 0 {
            let to_transfer = min(queue_len, bits);
            acc.push(to_transfer, U::from_u8(self.bitqueue.pop(to_transfer)));
            bits -= to_transfer;
        }

        read_aligned(&mut self.reader, bits / 8, &mut acc)
        .and_then(|()| read_unaligned(&mut self.reader,
                                      bits % 8,
                                      &mut acc,
                                      &mut self.bitqueue))
        .map(|()| acc.value())
    }

    fn skip(&mut self, mut bits: u32) -> Result<(), io::Error> {
        use std::cmp::min;

        let queue_len = self.bitqueue.len();
        if queue_len > 0 {
            let to_drop = min(queue_len, bits);
            self.bitqueue.pop(to_drop);
            bits -= to_drop;
        }

        skip_aligned(&mut self.reader, bits / 8)
        .and_then(|()| skip_unaligned(&mut self.reader,
                                      bits % 8,
                                      &mut self.bitqueue))
    }

    fn read_signed<S>(&mut self, bits: u32) -> Result<S, io::Error>
        where S: SignedNumeric {
        debug_assert!(bits >= 1);
        let sign = self.read::<S>(1)?;
        let unsigned = self.read::<S>(bits - 1)?;
        Ok(if sign.is_zero() {unsigned} else{unsigned.as_negative(bits)})
    }

    fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), io::Error> {
        if self.byte_aligned() {
            self.reader.read_exact(buf)
        } else {
            for b in buf.iter_mut() {
                *b = self.read::<u8>(8)?;
            }
            Ok(())
        }
    }

    #[inline]
    fn byte_aligned(&self) -> bool {
        self.bitqueue.is_empty()
    }

    #[inline]
    fn byte_align(&mut self) {
        self.bitqueue.clear()
    }
}

/// A wrapper for reading values from a little-endian stream.
pub struct BitReaderLE<'a> {
    reader: &'a mut io::BufRead,
    bitqueue: BitQueueLE<u8>
}

impl<'a> BitReaderLE<'a> {
    /// Wraps a little-endian reader around a `BufRead` reference.
    ///
    /// A `BufRead` is required because this reader is liable
    /// to make many small reads to the stream in normal operation,
    /// so reading from the buffer directly is preferable
    /// to making many calls to `read_exact`.
    pub fn new(reader: &mut io::BufRead) -> BitReaderLE {
        BitReaderLE{reader: reader, bitqueue: BitQueueLE::new()}
    }
}

impl<'a> BitRead for BitReaderLE<'a> {
    fn read<U>(&mut self, mut bits: u32) -> Result<U, io::Error>
        where U: Numeric {
        use std::cmp::min;

        let mut acc: BitQueueLE<U> = BitQueueLE::new();

        /*transfer un-processed bits from queue to accumulator*/
        let queue_len = self.bitqueue.len();
        if queue_len > 0 {
            let to_transfer = min(queue_len, bits);
            acc.push(to_transfer, U::from_u8(self.bitqueue.pop(to_transfer)));
            bits -= to_transfer;
        }

        read_aligned(&mut self.reader, bits / 8, &mut acc)
        .and_then(|()| read_unaligned(&mut self.reader,
                                      bits % 8,
                                      &mut acc,
                                      &mut self.bitqueue))
        .map(|()| acc.value())
    }

    fn skip(&mut self, mut bits: u32) -> Result<(), io::Error> {
        use std::cmp::min;

        let queue_len = self.bitqueue.len();
        if queue_len > 0 {
            let to_drop = min(queue_len, bits);
            self.bitqueue.pop(to_drop);
            bits -= to_drop;
        }

        skip_aligned(&mut self.reader, bits / 8)
        .and_then(|()| skip_unaligned(&mut self.reader,
                                      bits % 8,
                                      &mut self.bitqueue))
    }

    fn read_signed<S>(&mut self, bits: u32) -> Result<S, io::Error>
        where S: SignedNumeric {
        debug_assert!(bits >= 1);
        let unsigned = self.read::<S>(bits - 1)?;
        let sign = self.read::<S>(1)?;
        Ok(if sign.is_zero() {unsigned} else {unsigned.as_negative(bits)})
    }

    fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), io::Error> {
        if self.byte_aligned() {
            self.reader.read_exact(buf)
        } else {
            for b in buf.iter_mut() {
                *b = self.read::<u8>(8)?;
            }
            Ok(())
        }
    }

    #[inline]
    fn byte_aligned(&self) -> bool {
        self.bitqueue.is_empty()
    }

    #[inline]
    fn byte_align(&mut self) {
        self.bitqueue.clear()
    }
}

fn read_aligned<N>(reader: &mut io::BufRead,
                   mut bytes: u32,
                   acc: &mut BitQueue<N>) -> Result<(), io::Error>
    where N: Numeric {
    use std::cmp::min;

    while bytes > 0 {
        let processed = {
            let buf = reader.fill_buf()?;
            let to_process = min(bytes as usize, buf.len());
            for b in &buf[0..to_process] {
                acc.push(8, N::from_u8(*b));
            }
            to_process
        };
        if processed > 0 {
            reader.consume(processed);
            bytes -= processed as u32;
        } else {
            return Err(io::Error::new(
                io::ErrorKind::UnexpectedEof, "EOF in stream"));
        }
    }
    Ok(())
}

fn read_unaligned<N>(reader: &mut io::BufRead,
                     bits: u32,
                     acc: &mut BitQueue<N>,
                     rem: &mut BitQueue<u8>) -> Result<(), io::Error>
    where N: Numeric {

    debug_assert!(bits <= 8);

    if bits > 0 {
        let length = {
            let buf = reader.fill_buf()?;
            if buf.len() > 0 {
                rem.set(buf[0], 8);
                acc.push(bits, N::from_u8(rem.pop(bits)));
                1
            } else {0}
        };
        if length > 0 {
            Ok(reader.consume(length))
        } else {
            Err(io::Error::new(
                io::ErrorKind::UnexpectedEof, "EOF in stream"))
        }
    } else {
        Ok(())
    }
}

fn skip_aligned(reader: &mut io::BufRead,
                mut bytes: u32) -> Result<(), io::Error> {
    use std::cmp::min;

    while bytes > 0 {
        let processed = {
            let buf = reader.fill_buf()?;
            let to_process = min(bytes as usize, buf.len());
            to_process
        };
        if processed > 0 {
            reader.consume(processed);
            bytes -= processed as u32;
        } else {
            return Err(io::Error::new(
                io::ErrorKind::UnexpectedEof, "EOF in stream"));
        }
    }
    Ok(())
}

fn skip_unaligned(reader: &mut io::BufRead,
                  bits: u32,
                  rem: &mut BitQueue<u8>) -> Result<(), io::Error> {
    debug_assert!(bits <= 8);

    if bits > 0 {
        let length = {
            let buf = reader.fill_buf()?;
            if buf.len() > 0 {
                rem.set(buf[0], 8);
                rem.pop(bits);
                1
            } else {0}
        };
        if length > 0 {
            Ok(reader.consume(length))
        } else {
            Err(io::Error::new(
                io::ErrorKind::UnexpectedEof, "EOF in stream"))
        }
    } else {
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::path::{PathBuf,Path};
use std::str;
use std::str::FromStr;
use std::fs;
use std::fmt;
use git2;
use super::config::{Config,RepoLocation};
use super::result::*;
use super::db;

#[derive(Debug,Copy,Clone)]
pub enum SyncState {
    NotCloned,
    Cloned,
    Corrupted,
}

impl FromStr for SyncState {
    type Err = RepoError;
    fn from_str(s: &str) -> Result<SyncState, Self::Err> {
        match s {
            "NotCloned" => Ok(SyncState::NotCloned),
            "Cloned" => Ok(SyncState::Cloned),
            "Corrupted" => Ok(SyncState::Corrupted),
            _ => Err(RepoError::EnumParseError(s.to_string()))
        }
    }
}

impl ToString for SyncState {
    fn to_string(&self) -> String {
        match *self {
            SyncState::NotCloned => "NotCloned".to_string(),
            SyncState::Cloned => "Cloned".to_string(),
            SyncState::Corrupted => "Corrupted".to_string(),
        }
    }
}

#[derive(Clone)]
pub struct Repo {
    pub path: PathBuf,
    pub uri: String,
    pub branch: String,
    pub sync_state: SyncState,
    pub git_repo: Option<Rc<git2::Repository>>,
    pub commit: Option<String>,
}

impl fmt::Debug for Repo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Repo ({:?}, {}, {}, {:?})", self.path, self.uri, self.branch, self.sync_state)
    }
}

impl Repo {
    pub fn new_for_config(config: &Config) -> RepoResult<Repo> {
        let repo_loc = try!(config.repo_location.as_ref().ok_or(RepoError::NoRemote));

        let uri = try!(repo_loc.remote.as_ref().ok_or(RepoError::NoRemote));
        let branch = repo_loc.branch.clone();

        Ok(Repo::new(Repo::get_repo_path(config, repo_loc), uri.clone(), branch, SyncState::NotCloned))
    }

    pub fn new(path: PathBuf, uri: String, branch: Option<String>, sync_state: SyncState) -> Repo {
        Repo {
            path: path,
            uri: uri,
            branch: branch.unwrap_or("master".to_string()),
            sync_state: sync_state,
            git_repo: None,
            commit: None,
        }
    }

    fn new_git_callbacks<'a>() -> git2::RemoteCallbacks<'a> {
        let mut grcs = git2::RemoteCallbacks::<'a>::new();

        grcs
            .transfer_progress(|prog| {
                info!("total: {} received: {} indexed: {}",
                      prog.total_objects(),
                      prog.received_objects(),
                      prog.indexed_objects());
                true
            })
            .sideband_progress(|data| {
                match str::from_utf8(data) {
                    Ok(v) => println!("{}", v),
                    Err(e) => println!("not utf8 data: {:?}", e)
                };
                true
            });

        grcs
    }

    pub fn is_cloned(&self) -> bool {
        match self.sync_state {
            SyncState::NotCloned => false,
            _ => true
        }
    }

    pub fn dot_git_path(&self) -> PathBuf {
        self.path.join(".git")
    }

    pub fn dot_git_exists(&self) -> bool {
        match fs::metadata(self.dot_git_path().as_path()) {
            Ok(_) => true,
            Err(_) => {
                info!("repo doesn't exist at {:?}", self.path);
                false
            }
        }
    }

    pub fn find_in_db(&self, db: &db::Db) -> RepoResult<Option<db::Repository>> {
        db.find_repo_by_remote(&self.uri, &self.branch)
    }

    pub fn find_or_create_in_db(&mut self, db: &db::Db) -> RepoResult<db::Repository> {
        let maybe_repo = try!(self.find_in_db(db));

        match maybe_repo {
            Some(existing_repo) => {
                Ok(existing_repo)
            }
            None => {
                info!("creating new db repo entry for {:?}", self);

                let remote_uri = &self.uri;
                let remote_branch = &self.branch;
                let repo_path = try!(self.path.to_str().ok_or(RepoError::PathUnicodeError));

                let new_repo = db::Repository::new_from_remote(remote_uri.clone(), remote_branch.clone(), repo_path.to_string());
                try!(db.insert_repo(&new_repo));

                info!("created db repo entry {:?}", new_repo);

                Ok(new_repo)
            }
        }
    }

    pub fn update_repo_in_db(&mut self, db: &db::Db) -> RepoResult<()> {
        info!("updating db repo entry to match cloned repo...");

        let mut db_repo = try!(self.find_or_create_in_db(db));

        if self.commit.is_none() {
            self.commit = db_repo.indexed_commit.clone();
        }

        match db_repo.sync_state {
            SyncState::NotCloned => {
                db_repo.sync_state = self.sync_state;
            },
            SyncState::Cloned => {
                db_repo.sync_state = self.sync_state;
            },
            other_state => {
                self.sync_state = other_state;
            }
        }

        try!(db.update_repo(&db_repo));

        Ok(())
    }

    pub fn probe_fs(&mut self) -> RepoResult<()> {
        info!("probing cloned repo {}", self.uri);

        if !self.dot_git_exists() {
            self.set_state(SyncState::NotCloned);
            Ok(())
        } else {
            match self.sync_state {
                SyncState::NotCloned => {
                    self.set_state(SyncState::Cloned);
                }
                _ => {}
            }
            Ok(())
        }
    }

    pub fn clone_repo(&mut self) -> RepoResult<()> {
        self.git_repo = Some(Rc::new(try!(git2::Repository::clone(&self.uri, self.path.clone()))));

        self.sync_state = SyncState::Cloned;

        Ok(())
    }

    pub fn open_repo(&mut self) -> RepoResult<()> {
        self.git_repo = Some(Rc::new(try!(git2::Repository::open(self.path.clone()))));

        Ok(())
    }

    fn find_or_create_git_remote<'a> (&'a self, repo: &'a git2::Repository) -> RepoResult<git2::Remote> {
        // TODO: ensure returned remote has correct uri
        repo.find_remote("origin").map_err(|e| RepoError::GitError(e))
    }

    pub fn fetch_repo(&mut self) -> RepoResult<()> {
        let git_repo = try!(self.git_repo());

        let mut fo = git2::FetchOptions::new();
        let grcs = Repo::new_git_callbacks();

        fo.prune(git2::FetchPrune::On);
        fo.remote_callbacks(grcs);

        let mut remote = try!(self.find_or_create_git_remote(&git_repo));

        info!("fetching from remote");
        try!(remote.fetch(&[&self.branch], Some(&mut fo), None));

        Ok(())
    }

    pub fn checkout_head(&mut self) -> RepoResult<()> {
        let git_repo = try!(self.git_repo());

        let branch = try!(git_repo.find_branch(&self.branch, git2::BranchType::Local));
        let branch_fullname = try!(branch.get().name().ok_or(RepoError::StringUnicodeError));

        info!("branch full name {}", branch_fullname);
        try!(git_repo.set_head(branch_fullname));

        let mut cb = git2::build::CheckoutBuilder::new();
        cb.force();

        info!("checkout {}", self.branch);
        try!(git_repo.checkout_head(Some(&mut cb)).map_err(|e| RepoError::GitError(e)));

        Ok(())
    }

    pub fn pull_repo(&mut self) -> RepoResult<()> {
        try!(self.fetch_repo());

        try!(self.checkout_head());

        Ok(())
    }

    pub fn revwalk(&mut self) -> RepoResult<()> {
        let git_repo = try!(self.git_repo());

        let mut revwalk = try!(git_repo.revwalk());

        try!(revwalk.push_head());

        if self.commit.is_some() {
            let old_head = try!(git_repo.revparse_single(self.commit.as_ref().unwrap())).id();
            let current_head = try!(git_repo.head()).target().unwrap();

            let base = try!(git_repo.merge_base(old_head, current_head));

            try!(revwalk.hide(base));
        }

        info!("commit history:");
        for oid in revwalk {
            info!("{:?}", oid);
        }

        Ok(())
    }

    pub fn git_repo(&self) -> RepoResult<Rc<git2::Repository>> {
        match self.git_repo.as_ref() {
            Some(gr) => Ok(gr.clone()),
            None => Err(RepoError::InvalidState("git repo not opened".to_string())),
        }
    }

    pub fn set_state(&mut self, new_state: SyncState) {
        info!("repo {} {:?} --> {:?}", self.uri, self.sync_state, new_state);
        self.sync_state = new_state;
    }

    fn get_repo_path(config: &Config, _repo_loc: &RepoLocation) -> PathBuf {
        //TODO: either use hash or derive dir name from repo name in uri
        Path::new(&config.data_dir).join("the_repo".to_string())
    }
}

<commit_msg>make revwalk stop at merge-base and make pull actually update master branch target to origin/master<commit_after>use std::rc::Rc;
use std::path::{PathBuf,Path};
use std::str;
use std::str::FromStr;
use std::fs;
use std::fmt;
use git2;
use super::config::{Config,RepoLocation};
use super::result::*;
use super::db;

#[derive(Debug,Copy,Clone)]
pub enum SyncState {
    NotCloned,
    Cloned,
    Corrupted,
}

impl FromStr for SyncState {
    type Err = RepoError;
    fn from_str(s: &str) -> Result<SyncState, Self::Err> {
        match s {
            "NotCloned" => Ok(SyncState::NotCloned),
            "Cloned" => Ok(SyncState::Cloned),
            "Corrupted" => Ok(SyncState::Corrupted),
            _ => Err(RepoError::EnumParseError(s.to_string()))
        }
    }
}

impl ToString for SyncState {
    fn to_string(&self) -> String {
        match *self {
            SyncState::NotCloned => "NotCloned".to_string(),
            SyncState::Cloned => "Cloned".to_string(),
            SyncState::Corrupted => "Corrupted".to_string(),
        }
    }
}

#[derive(Clone)]
pub struct Repo {
    pub path: PathBuf,
    pub uri: String,
    pub branch: String,
    pub sync_state: SyncState,
    pub git_repo: Option<Rc<git2::Repository>>,
    pub commit: Option<String>,
}

impl fmt::Debug for Repo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Repo ({:?}, {}, {}, {:?})", self.path, self.uri, self.branch, self.sync_state)
    }
}

impl Repo {
    pub fn new_for_config(config: &Config) -> RepoResult<Repo> {
        let repo_loc = try!(config.repo_location.as_ref().ok_or(RepoError::NoRemote));

        let uri = try!(repo_loc.remote.as_ref().ok_or(RepoError::NoRemote));
        let branch = repo_loc.branch.clone();

        Ok(Repo::new(Repo::get_repo_path(config, repo_loc), uri.clone(), branch, SyncState::NotCloned))
    }

    pub fn new(path: PathBuf, uri: String, branch: Option<String>, sync_state: SyncState) -> Repo {
        Repo {
            path: path,
            uri: uri,
            branch: branch.unwrap_or("master".to_string()),
            sync_state: sync_state,
            git_repo: None,
            commit: None,
        }
    }

    fn new_git_callbacks<'a>() -> git2::RemoteCallbacks<'a> {
        let mut grcs = git2::RemoteCallbacks::<'a>::new();

        grcs
            .transfer_progress(|prog| {
                info!("total: {} received: {} indexed: {}",
                      prog.total_objects(),
                      prog.received_objects(),
                      prog.indexed_objects());
                true
            })
            .sideband_progress(|data| {
                match str::from_utf8(data) {
                    Ok(v) => println!("{}", v),
                    Err(e) => println!("not utf8 data: {:?}", e)
                };
                true
            });

        grcs
    }

    pub fn is_cloned(&self) -> bool {
        match self.sync_state {
            SyncState::NotCloned => false,
            _ => true
        }
    }

    pub fn dot_git_path(&self) -> PathBuf {
        self.path.join(".git")
    }

    pub fn dot_git_exists(&self) -> bool {
        match fs::metadata(self.dot_git_path().as_path()) {
            Ok(_) => true,
            Err(_) => {
                info!("repo doesn't exist at {:?}", self.path);
                false
            }
        }
    }

    pub fn find_in_db(&self, db: &db::Db) -> RepoResult<Option<db::Repository>> {
        db.find_repo_by_remote(&self.uri, &self.branch)
    }

    pub fn find_or_create_in_db(&mut self, db: &db::Db) -> RepoResult<db::Repository> {
        let maybe_repo = try!(self.find_in_db(db));

        match maybe_repo {
            Some(existing_repo) => {
                Ok(existing_repo)
            }
            None => {
                info!("creating new db repo entry for {:?}", self);

                let remote_uri = &self.uri;
                let remote_branch = &self.branch;
                let repo_path = try!(self.path.to_str().ok_or(RepoError::PathUnicodeError));

                let new_repo = db::Repository::new_from_remote(remote_uri.clone(), remote_branch.clone(), repo_path.to_string());
                try!(db.insert_repo(&new_repo));

                info!("created db repo entry {:?}", new_repo);

                Ok(new_repo)
            }
        }
    }

    pub fn update_repo_in_db(&mut self, db: &db::Db) -> RepoResult<()> {
        info!("updating db repo entry to match cloned repo...");

        let mut db_repo = try!(self.find_or_create_in_db(db));

        if self.commit.is_none() {
            self.commit = db_repo.indexed_commit.clone();
        }

        match db_repo.sync_state {
            SyncState::NotCloned => {
                db_repo.sync_state = self.sync_state;
            },
            SyncState::Cloned => {
                db_repo.sync_state = self.sync_state;
            },
            other_state => {
                self.sync_state = other_state;
            }
        }

        try!(db.update_repo(&db_repo));

        Ok(())
    }

    pub fn probe_fs(&mut self) -> RepoResult<()> {
        info!("probing cloned repo {}", self.uri);

        if !self.dot_git_exists() {
            self.set_state(SyncState::NotCloned);
            Ok(())
        } else {
            match self.sync_state {
                SyncState::NotCloned => {
                    self.set_state(SyncState::Cloned);
                }
                _ => {}
            }
            Ok(())
        }
    }

    pub fn clone_repo(&mut self) -> RepoResult<()> {
        self.git_repo = Some(Rc::new(try!(git2::Repository::clone(&self.uri, self.path.clone()))));

        self.sync_state = SyncState::Cloned;

        Ok(())
    }

    pub fn open_repo(&mut self) -> RepoResult<()> {
        self.git_repo = Some(Rc::new(try!(git2::Repository::open(self.path.clone()))));

        Ok(())
    }

    fn find_or_create_git_remote<'a> (&'a self, repo: &'a git2::Repository) -> RepoResult<git2::Remote> {
        // TODO: ensure returned remote has correct uri
        repo.find_remote("origin").map_err(|e| RepoError::GitError(e))
    }

    pub fn fetch_repo(&mut self) -> RepoResult<()> {
        let git_repo = try!(self.git_repo());

        let mut fo = git2::FetchOptions::new();
        let grcs = Repo::new_git_callbacks();

        fo.prune(git2::FetchPrune::On);
        fo.remote_callbacks(grcs);

        let mut remote = try!(self.find_or_create_git_remote(&git_repo));

        info!("fetching from remote");
        try!(remote.fetch(&[&self.branch], Some(&mut fo), None));

        Ok(())
    }

    pub fn checkout_head(&mut self) -> RepoResult<()> {
        let git_repo = try!(self.git_repo());

        let branch = try!(git_repo.find_branch(&self.branch, git2::BranchType::Local));
        let branch_fullname = try!(branch.get().name().ok_or(RepoError::StringUnicodeError));

        info!("branch full name {}", branch_fullname);
        try!(git_repo.set_head(branch_fullname));

        let mut cb = git2::build::CheckoutBuilder::new();
        cb.force();

        info!("checkout {}", self.branch);
        try!(git_repo.checkout_head(Some(&mut cb)).map_err(|e| RepoError::GitError(e)));

        Ok(())
    }

    /// like git update-ref refs/heads/master refs/remotes/origin/master
    pub fn repoint_head_to_origin(&mut self) -> RepoResult<()> {
        let git_repo = try!(self.git_repo());

        let remote = try!(self.find_or_create_git_remote(&git_repo));

        let remote_name = remote.name().unwrap();
        let branch_name = &self.branch;
        let remote_ref = format!("refs/remotes/{}/{}", remote_name, branch_name);
        let local_ref = format!("refs/heads/{}", branch_name);
        let local_oid = try!(git_repo.refname_to_id(&local_ref));
        let remote_oid = try!(git_repo.refname_to_id(&remote_ref));

        let reflog_msg = format!("update-ref: moving {} from {} to {}", local_ref, local_oid, remote_oid);
        try!(git_repo.reference(&local_ref, remote_oid, true, &reflog_msg));

        Ok(())
    }

    pub fn pull_repo(&mut self) -> RepoResult<()> {
        try!(self.fetch_repo());

        try!(self.repoint_head_to_origin());

        try!(self.checkout_head());

        Ok(())
    }

    /// walks commits from current head to merge-base of self.commit if any
    pub fn revwalk(&mut self) -> RepoResult<()> {
        let git_repo = try!(self.git_repo());

        let mut revwalk = try!(git_repo.revwalk());

        try!(revwalk.push_head());

        if self.commit.is_some() {
            let old_head = try!(git_repo.revparse_single(self.commit.as_ref().unwrap())).id();
            let current_head = try!(git_repo.head()).target().unwrap();

            let base = try!(git_repo.merge_base(old_head, current_head));

            try!(revwalk.hide(base));
        }

        info!("commit history:");
        for oid in revwalk {
            info!("{:?}", oid);
        }

        Ok(())
    }

    pub fn git_repo(&self) -> RepoResult<Rc<git2::Repository>> {
        match self.git_repo.as_ref() {
            Some(gr) => Ok(gr.clone()),
            None => Err(RepoError::InvalidState("git repo not opened".to_string())),
        }
    }

    pub fn set_state(&mut self, new_state: SyncState) {
        info!("repo {} {:?} --> {:?}", self.uri, self.sync_state, new_state);
        self.sync_state = new_state;
    }

    fn get_repo_path(config: &Config, _repo_loc: &RepoLocation) -> PathBuf {
        //TODO: either use hash or derive dir name from repo name in uri
        Path::new(&config.data_dir).join("the_repo".to_string())
    }
}

<|endoftext|>


<commit_before>use std::io::BufWriter;
use clog::Clog;
use clog::fmt::MarkdownWriter;

pub fn write(repository_path: &str, old_version: &str, new_version: &str) -> Result<(), String> {
    let mut clog = try!(Clog::with_dir(repository_path).map_err(|_| "Clog failed".to_owned()));

    // TODO: Make this configurable? Rely on clog's own configuration?
    clog.changelog("Changelog.md")
        .from(format!("v{}", old_version))
        .version(format!("v{}", new_version));

    clog.write_changelog().map_err(|_| "Failed to write Changelog.md".to_owned())
}

pub fn generate(repository_path: &str, old_version: &str, new_version: &str) -> Result<String, String> {
    let mut clog = try!(Clog::with_dir(repository_path).map_err(|_| "Clog failed".to_owned()));

    clog
        .from(format!("v{}", old_version))
        .version(format!("v{}", new_version));

    let mut out_buf = BufWriter::new(Vec::new());

    {
        let mut writer = MarkdownWriter::new(&mut out_buf);
        try!(clog.write_changelog_with(&mut writer)
             .map_err(|_| "Genearting changelog failed"))
    }

    let out_buf = out_buf.into_inner().unwrap();
    let changelog = String::from_utf8(out_buf).unwrap();

    match changelog.find('\n') {
        Some(newline_offset) => Ok(changelog[newline_offset+1..].into()),
        None => Ok(changelog)
    }
}
<commit_msg>fix: Place changelog in repository's folder<commit_after>use std::io::BufWriter;
use clog::Clog;
use clog::fmt::MarkdownWriter;
use std::path::PathBuf;

pub fn write(repository_path: &str, old_version: &str, new_version: &str) -> Result<(), String> {
    let mut clog = try!(Clog::with_dir(repository_path).map_err(|_| "Clog failed".to_owned()));

    let mut clog_file = PathBuf::from(repository_path);
    clog_file.push("Changelog.md");

    // TODO: Make this configurable? Rely on clog's own configuration?
    clog.changelog(clog_file.to_str().unwrap())
        .from(format!("v{}", old_version))
        .version(format!("v{}", new_version));

    clog.write_changelog().map_err(|_| "Failed to write Changelog.md".to_owned())
}

pub fn generate(repository_path: &str, old_version: &str, new_version: &str) -> Result<String, String> {
    let mut clog = try!(Clog::with_dir(repository_path).map_err(|_| "Clog failed".to_owned()));

    clog
        .from(format!("v{}", old_version))
        .version(format!("v{}", new_version));

    let mut out_buf = BufWriter::new(Vec::new());

    {
        let mut writer = MarkdownWriter::new(&mut out_buf);
        try!(clog.write_changelog_with(&mut writer)
             .map_err(|_| "Genearting changelog failed"))
    }

    let out_buf = out_buf.into_inner().unwrap();
    let changelog = String::from_utf8(out_buf).unwrap();

    match changelog.find('\n') {
        Some(newline_offset) => Ok(changelog[newline_offset+1..].into()),
        None => Ok(changelog)
    }
}
<|endoftext|>


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

use length::Length;
use num::Zero;

use num_lib::NumCast;
use std::fmt::{self, Formatter};
use std::ops::{Mul, Div};

#[derive(Clone, Copy, RustcDecodable, RustcEncodable, PartialEq)]
pub struct Size2D<T> {
    pub width: T,
    pub height: T
}

impl<T: fmt::Debug> fmt::Debug for Size2D<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}×{:?}", self.width, self.height)
    }
}

impl<T: fmt::Display> fmt::Display for Size2D<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "({}x{})", self.width, self.height)
    }
}

impl<T: Clone> Size2D<T> {
    pub fn new(width: T, height: T) -> Size2D<T> {
        Size2D {
            width: width,
            height: height
        }
    }
}

impl<T:Copy + Clone + Mul<T, Output=U>, U> Size2D<T> {
    pub fn area(&self) -> U { self.width * self.height }
}

impl<T: Zero> Size2D<T> {
    pub fn zero() -> Size2D<T> {
        Size2D {
            width: Zero::zero(),
            height: Zero::zero(),
        }
    }
}

impl<T: Zero> Zero for Size2D<T> {
    fn zero() -> Size2D<T> {
        Size2D {
            width: Zero::zero(),
            height: Zero::zero(),
        }
    }
}

impl<Scale: Copy, T0: Mul<Scale, Output=T1>, T1: Clone> Mul<Scale> for Size2D<T0> {
    type Output = Size2D<T1>;
    #[inline]
    fn mul(self, scale: Scale) -> Size2D<T1> {
        Size2D::new(self.width * scale, self.height * scale)
    }
}

impl<Scale: Copy, T0: Div<Scale, Output=T1>, T1: Clone> Div<Scale> for Size2D<T0> {
    type Output = Size2D<T1>;
    #[inline]
    fn div(self, scale: Scale) -> Size2D<T1> {
        Size2D::new(self.width / scale, self.height / scale)
    }
}

// Convenient aliases for Size2D with typed units

pub type TypedSize2D<Unit, T> = Size2D<Length<Unit, T>>;

pub fn TypedSize2D<Unit, T: Clone>(width: T, height: T) -> TypedSize2D<Unit, T> {
    Size2D::new(Length::new(width), Length::new(height))
}

impl<Unit, T: Clone> Size2D<Length<Unit, T>> {
    /// Drop the units, preserving only the numeric value.
    pub fn to_untyped(&self) -> Size2D<T> {
        Size2D::new(self.width.get(), self.height.get())
    }

    /// Tag a unitless value with units.
    pub fn from_untyped(p: &Size2D<T>) -> TypedSize2D<Unit, T> {
        Size2D::new(Length::new(p.width.clone()), Length::new(p.height.clone()))
    }
}

impl<Unit, T0: NumCast + Clone> Size2D<Length<Unit, T0>> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast<T1: NumCast + Clone>(&self) -> Option<Size2D<Length<Unit, T1>>> {
        match (self.width.cast(), self.height.cast()) {
            (Some(w), Some(h)) => Some(Size2D::new(w, h)),
            _ => None
        }
    }
}

// Convenience functions for common casts
impl<Unit, T: NumCast + Clone> Size2D<Length<Unit, T>> {
    pub fn as_f32(&self) -> Size2D<Length<Unit, f32>> {
        self.cast().unwrap()
    }

    pub fn as_uint(&self) -> Size2D<Length<Unit, usize>> {
        self.cast().unwrap()
    }
}
<commit_msg>Migrate TypedSize2D primary constructor to associated fn<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use length::Length;
use num::Zero;

use num_lib::NumCast;
use std::fmt::{self, Formatter};
use std::ops::{Mul, Div};

#[derive(Clone, Copy, RustcDecodable, RustcEncodable, PartialEq)]
pub struct Size2D<T> {
    pub width: T,
    pub height: T
}

impl<T: fmt::Debug> fmt::Debug for Size2D<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}×{:?}", self.width, self.height)
    }
}

impl<T: fmt::Display> fmt::Display for Size2D<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "({}x{})", self.width, self.height)
    }
}

impl<T: Clone> Size2D<T> {
    pub fn new(width: T, height: T) -> Size2D<T> {
        Size2D {
            width: width,
            height: height
        }
    }
}

impl<T:Copy + Clone + Mul<T, Output=U>, U> Size2D<T> {
    pub fn area(&self) -> U { self.width * self.height }
}

impl<T: Zero> Size2D<T> {
    pub fn zero() -> Size2D<T> {
        Size2D {
            width: Zero::zero(),
            height: Zero::zero(),
        }
    }
}

impl<T: Zero> Zero for Size2D<T> {
    fn zero() -> Size2D<T> {
        Size2D {
            width: Zero::zero(),
            height: Zero::zero(),
        }
    }
}

impl<Scale: Copy, T0: Mul<Scale, Output=T1>, T1: Clone> Mul<Scale> for Size2D<T0> {
    type Output = Size2D<T1>;
    #[inline]
    fn mul(self, scale: Scale) -> Size2D<T1> {
        Size2D::new(self.width * scale, self.height * scale)
    }
}

impl<Scale: Copy, T0: Div<Scale, Output=T1>, T1: Clone> Div<Scale> for Size2D<T0> {
    type Output = Size2D<T1>;
    #[inline]
    fn div(self, scale: Scale) -> Size2D<T1> {
        Size2D::new(self.width / scale, self.height / scale)
    }
}

// Convenient aliases for Size2D with typed units

pub type TypedSize2D<Unit, T> = Size2D<Length<Unit, T>>;

impl<Unit, T: Clone> Size2D<Length<Unit, T>> {
    pub fn typed(width: T, height: T) -> TypedSize2D<Unit, T> {
        Size2D::new(Length::new(width), Length::new(height))
    }

    /// Drop the units, preserving only the numeric value.
    pub fn to_untyped(&self) -> Size2D<T> {
        Size2D::new(self.width.get(), self.height.get())
    }

    /// Tag a unitless value with units.
    pub fn from_untyped(p: &Size2D<T>) -> TypedSize2D<Unit, T> {
        Size2D::new(Length::new(p.width.clone()), Length::new(p.height.clone()))
    }
}

impl<Unit, T0: NumCast + Clone> Size2D<Length<Unit, T0>> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast<T1: NumCast + Clone>(&self) -> Option<Size2D<Length<Unit, T1>>> {
        match (self.width.cast(), self.height.cast()) {
            (Some(w), Some(h)) => Some(Size2D::new(w, h)),
            _ => None
        }
    }
}

// Convenience functions for common casts
impl<Unit, T: NumCast + Clone> Size2D<Length<Unit, T>> {
    pub fn as_f32(&self) -> Size2D<Length<Unit, f32>> {
        self.cast().unwrap()
    }

    pub fn as_uint(&self) -> Size2D<Length<Unit, usize>> {
        self.cast().unwrap()
    }
}
<|endoftext|>


<commit_before>//! Provides state machine that is guarded by Mutex
//!
//! This allows the machine to be manipulated from multiple threads. But you
//! must be careful to not to break the state machine
use std::mem;
use std::sync::{Arc, Mutex};

use rotor::{Machine, EventSet, Scope, Response};
use rotor::{Void};

pub struct Mutexed<M>(Arc<Mutex<M>>);

/// A trait which allows to replace the state machine with dummy/null/None
///
/// Since we put machine (used with `Mutexed`) into a `Arc<Mutex<M>>` we need
/// to replace it with some other value while the real value is moved off the
/// state machine to be able to replace it by code, having self by-value.
///
/// When the thread working with the state machine panics while machine is
/// moved off the place, the poisoned lock is left with `Replaceable::empty`
/// value. When lock is poisoned we unwrap the value and use it as a valid
/// state machine. So you can continue to work after panic with the clean
/// state after a crash (perhaps if the panic was in different thread).
///
/// The text above means you should be able to "restart" the state machine
/// from the `empty()` state.
trait Replaceable: Machine {
    /// Return the empty value that may be used as replacement
    ///
    /// **The method must be cheap to compute**. Because it's executed on
    /// every action of a state machine.
    fn empty() -> Self;
    /// Restart a state machine from `empty()` state
    ///
    /// This method is called before calling any other action methods when
    /// lock holding the state machine was poisoned.
    ///
    /// Note that after the `restart` current event is discarded, it's assumed
    /// that state machine is already arranged to receive some new events
    /// (i.e. it's useless to keep old `ready()` event if new connection is
    /// just being established)
    ///
    /// While you can check the state of the old machine (a `self`), and even
    /// return it as is, it's strongly discouraged, as you can't know exact
    /// kind of failure that happened in other thread (when lock was
    /// poisoned). But in case protocol is super-simple (like line-based
    /// without exceptions) and it's not security critical (i.e. monitoring
    /// using graphite), you may reuse old state machine or parts there of.
    ///
    /// Default implementation is just to panic
    fn restart(self, _scope: &mut Scope<Self::Context>)
        -> Response<Self, Self::Seed>
    {
        panic!("State machine has been poisoned");
    }
}

#[inline]
fn locked_call<M, F>(scope: &mut Scope<M::Context>, me: Mutexed<M>,
    fun: F)
    -> Response<Mutexed<M>, M::Seed>
    where M: Replaceable,
          F: FnOnce(M, &mut Scope<M::Context>) -> Response<M, M::Seed>
{
    let fake_result = match me.0.lock() {
        Ok(mut guard) => {
            let fsm = mem::replace(&mut *guard, Replaceable::empty());
            let res = fun(fsm, scope);
            res.wrap(|new_machine| {
                // thows off an `empty()` instance
                mem::replace(&mut *guard, new_machine);
                ()
            })
        }
        Err(poisoned) => {
            let mut guard = poisoned.into_inner();
            let fsm = mem::replace(&mut *guard, Replaceable::empty());
            let res = fsm.restart(scope);
            res.wrap(|new_machine| {
                // thows off an `empty()` instance
                mem::replace(&mut *guard, new_machine);
                ()
            })
        }
    };
    fake_result.wrap(|()| me)
}

impl<M: Replaceable> Machine for Mutexed<M> {
    type Context = M::Context;
    type Seed = M::Seed;
    fn create(seed: Self::Seed, scope: &mut Scope<M::Context>)
        -> Response<Self, Void>
    {
        M::create(seed, scope).wrap(Mutex::new).wrap(Arc::new).wrap(Mutexed)
    }
    fn ready(self, events: EventSet, scope: &mut Scope<M::Context>)
        -> Response<Self, Self::Seed>
    {
        locked_call(scope, self, |fsm, scope| fsm.ready(events, scope))
    }
    fn spawned(self, scope: &mut Scope<M::Context>)
        -> Response<Self, Self::Seed>
    {
        locked_call(scope, self, |fsm, scope| fsm.spawned(scope))
    }
    fn timeout(self, scope: &mut Scope<M::Context>)
        -> Response<Self, Self::Seed>
    {
        locked_call(scope, self, |fsm, scope| fsm.timeout(scope))
    }
    fn wakeup(self, scope: &mut Scope<M::Context>)
        -> Response<Self, Self::Seed>
    {
        locked_call(scope, self, |fsm, scope| fsm.wakeup(scope))
    }
}
<commit_msg>Made `Replaceable` trait public<commit_after>//! Provides state machine that is guarded by Mutex
//!
//! This allows the machine to be manipulated from multiple threads. But you
//! must be careful to not to break the state machine
use std::mem;
use std::sync::{Arc, Mutex};

use rotor::{Machine, EventSet, Scope, Response};
use rotor::{Void};

pub struct Mutexed<M>(Arc<Mutex<M>>);

/// A trait which allows to replace the state machine with dummy/null/None
///
/// Since we put machine (used with `Mutexed`) into a `Arc<Mutex<M>>` we need
/// to replace it with some other value while the real value is moved off the
/// state machine to be able to replace it by code, having self by-value.
///
/// When the thread working with the state machine panics while machine is
/// moved off the place, the poisoned lock is left with `Replaceable::empty`
/// value. When lock is poisoned we unwrap the value and use it as a valid
/// state machine. So you can continue to work after panic with the clean
/// state after a crash (perhaps if the panic was in different thread).
///
/// The text above means you should be able to "restart" the state machine
/// from the `empty()` state.
pub trait Replaceable: Machine {
    /// Return the empty value that may be used as replacement
    ///
    /// **The method must be cheap to compute**. Because it's executed on
    /// every action of a state machine.
    fn empty() -> Self;
    /// Restart a state machine from `empty()` state
    ///
    /// This method is called before calling any other action methods when
    /// lock holding the state machine was poisoned.
    ///
    /// Note that after the `restart` current event is discarded, it's assumed
    /// that state machine is already arranged to receive some new events
    /// (i.e. it's useless to keep old `ready()` event if new connection is
    /// just being established)
    ///
    /// While you can check the state of the old machine (a `self`), and even
    /// return it as is, it's strongly discouraged, as you can't know exact
    /// kind of failure that happened in other thread (when lock was
    /// poisoned). But in case protocol is super-simple (like line-based
    /// without exceptions) and it's not security critical (i.e. monitoring
    /// using graphite), you may reuse old state machine or parts there of.
    ///
    /// Default implementation is just to panic
    fn restart(self, _scope: &mut Scope<Self::Context>)
        -> Response<Self, Self::Seed>
    {
        panic!("State machine has been poisoned");
    }
}

#[inline]
fn locked_call<M, F>(scope: &mut Scope<M::Context>, me: Mutexed<M>,
    fun: F)
    -> Response<Mutexed<M>, M::Seed>
    where M: Replaceable,
          F: FnOnce(M, &mut Scope<M::Context>) -> Response<M, M::Seed>
{
    let fake_result = match me.0.lock() {
        Ok(mut guard) => {
            let fsm = mem::replace(&mut *guard, Replaceable::empty());
            let res = fun(fsm, scope);
            res.wrap(|new_machine| {
                // thows off an `empty()` instance
                mem::replace(&mut *guard, new_machine);
                ()
            })
        }
        Err(poisoned) => {
            let mut guard = poisoned.into_inner();
            let fsm = mem::replace(&mut *guard, Replaceable::empty());
            let res = fsm.restart(scope);
            res.wrap(|new_machine| {
                // thows off an `empty()` instance
                mem::replace(&mut *guard, new_machine);
                ()
            })
        }
    };
    fake_result.wrap(|()| me)
}

impl<M: Replaceable> Machine for Mutexed<M> {
    type Context = M::Context;
    type Seed = M::Seed;
    fn create(seed: Self::Seed, scope: &mut Scope<M::Context>)
        -> Response<Self, Void>
    {
        M::create(seed, scope).wrap(Mutex::new).wrap(Arc::new).wrap(Mutexed)
    }
    fn ready(self, events: EventSet, scope: &mut Scope<M::Context>)
        -> Response<Self, Self::Seed>
    {
        locked_call(scope, self, |fsm, scope| fsm.ready(events, scope))
    }
    fn spawned(self, scope: &mut Scope<M::Context>)
        -> Response<Self, Self::Seed>
    {
        locked_call(scope, self, |fsm, scope| fsm.spawned(scope))
    }
    fn timeout(self, scope: &mut Scope<M::Context>)
        -> Response<Self, Self::Seed>
    {
        locked_call(scope, self, |fsm, scope| fsm.timeout(scope))
    }
    fn wakeup(self, scope: &mut Scope<M::Context>)
        -> Response<Self, Self::Seed>
    {
        locked_call(scope, self, |fsm, scope| fsm.wakeup(scope))
    }
}
<|endoftext|>


<commit_before>use std::{cmp, io};
use std::io::Write as IoWrite;
use std::fmt::Write;
use std::collections::VecDeque;

use http::{StatusCode, Version};
use http::header::{HeaderValue,
                   CONNECTION, CONTENT_TYPE, CONTENT_LENGTH, TRANSFER_ENCODING, DATE};
use bytes::BytesMut;
use futures::{Async, Future, Poll, Stream};
use tokio_core::net::TcpStream;

use date;
use route::Frame;
use httpmessage::{Body, HttpResponse};

type FrameStream = Stream<Item=Frame, Error=io::Error>;
const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific
const MAX_WRITE_BUFFER_SIZE: usize = 65_536; // max buffer size 64k

#[derive(PartialEq, Debug)]
enum TaskRunningState {
    Paused,
    Running,
    Done,
}

impl TaskRunningState {
    fn is_done(&self) -> bool {
        *self == TaskRunningState::Done
    }
}

#[derive(PartialEq, Debug)]
enum TaskIOState {
    ReadingMessage,
    ReadingPayload,
    Done,
}

impl TaskIOState {
    fn is_done(&self) -> bool {
        *self == TaskIOState::Done
    }
}

pub struct Task {
    state: TaskRunningState,
    iostate: TaskIOState,
    frames: VecDeque<Frame>,
    stream: Option<Box<FrameStream>>,
    encoder: Encoder,
    buffer: BytesMut,
    upgraded: bool,
}

impl Task {

    pub(crate) fn reply(msg: HttpResponse) -> Self {
        let mut frames = VecDeque::new();
        frames.push_back(Frame::Message(msg));
        frames.push_back(Frame::Payload(None));

        Task {
            state: TaskRunningState::Running,
            iostate: TaskIOState::Done,
            frames: frames,
            stream: None,
            encoder: Encoder::length(0),
            buffer: BytesMut::new(),
            upgraded: false,
        }
    }

    pub(crate) fn with_stream<S>(stream: S) -> Self
        where S: Stream<Item=Frame, Error=io::Error> + 'static
    {
        Task {
            state: TaskRunningState::Running,
            iostate: TaskIOState::ReadingMessage,
            frames: VecDeque::new(),
            stream: Some(Box::new(stream)),
            encoder: Encoder::length(0),
            buffer: BytesMut::new(),
            upgraded: false,
        }
    }

    fn prepare(&mut self, mut msg: HttpResponse)
    {
        trace!("Prepare message status={:?}", msg.status);

        let mut extra = 0;
        let body = msg.replace_body(Body::Empty);

        match body {
            Body::Empty => {
                if msg.chunked() {
                    error!("Chunked transfer is enabled but body is set to Empty");
                }
                msg.headers.insert(CONTENT_LENGTH, HeaderValue::from_static("0"));
                msg.headers.remove(TRANSFER_ENCODING);
                self.encoder = Encoder::length(0);
            },
            Body::Length(n) => {
                if msg.chunked() {
                    error!("Chunked transfer is enabled but body with specific length is specified");
                }
                msg.headers.insert(
                    CONTENT_LENGTH,
                    HeaderValue::from_str(format!("{}", n).as_str()).unwrap());
                msg.headers.remove(TRANSFER_ENCODING);
                self.encoder = Encoder::length(n);
            },
            Body::Binary(ref bytes) => {
                extra = bytes.len();
                msg.headers.insert(
                    CONTENT_LENGTH,
                    HeaderValue::from_str(format!("{}", bytes.len()).as_str()).unwrap());
                msg.headers.remove(TRANSFER_ENCODING);
                self.encoder = Encoder::length(0);
            }
            Body::Streaming => {
                if msg.chunked() {
                    if msg.version < Version::HTTP_11 {
                        error!("Chunked transfer encoding is forbidden for {:?}", msg.version);
                    }
                    msg.headers.remove(CONTENT_LENGTH);
                    msg.headers.insert(TRANSFER_ENCODING, HeaderValue::from_static("chunked"));
                    self.encoder = Encoder::chunked();
                } else {
                    self.encoder = Encoder::eof();
                }
            }
            Body::Upgrade => {
                msg.headers.insert(CONNECTION, HeaderValue::from_static("upgrade"));
                self.encoder = Encoder::eof();
            }
        }

        // keep-alive
        if msg.keep_alive() {
            if msg.version < Version::HTTP_11 {
                msg.headers.insert(CONNECTION, HeaderValue::from_static("keep-alive"));
            }
        } else if msg.version >= Version::HTTP_11 {
            msg.headers.insert(CONNECTION, HeaderValue::from_static("close"));
        }

        // render message
        let init_cap = 100 + msg.headers.len() * AVERAGE_HEADER_SIZE + extra;
        self.buffer.reserve(init_cap);

        if msg.version == Version::HTTP_11 && msg.status == StatusCode::OK {
            self.buffer.extend(b"HTTP/1.1 200 OK\r\n");
        } else {
            let _ = write!(self.buffer, "{:?} {}\r\n", msg.version, msg.status);
        }
        for (key, value) in &msg.headers {
            let t: &[u8] = key.as_ref();
            self.buffer.extend(t);
            self.buffer.extend(b": ");
            self.buffer.extend(value.as_ref());
            self.buffer.extend(b"\r\n");
        }

        // using http::h1::date is quite a lot faster than generating
        // a unique Date header each time like req/s goes up about 10%
        if !msg.headers.contains_key(DATE) {
            self.buffer.reserve(date::DATE_VALUE_LENGTH + 8);
            self.buffer.extend(b"Date: ");
            date::extend(&mut self.buffer);
            self.buffer.extend(b"\r\n");
        }

        // default content-type
        if !msg.headers.contains_key(CONTENT_TYPE) {
            self.buffer.extend(b"ContentType: application/octet-stream\r\n".as_ref());
        }

        self.buffer.extend(b"\r\n");

        if let Body::Binary(ref bytes) = *msg.body() {
            self.buffer.extend(bytes);
            return
        }
        msg.replace_body(body);
    }

    pub(crate) fn poll_io(&mut self, io: &mut TcpStream) -> Poll<bool, ()> {
        println!("POLL-IO {:?}", self.frames.len());
        // response is completed
        if self.frames.is_empty() && self.iostate.is_done() {
            return Ok(Async::Ready(self.state.is_done()));
        } else {
            // poll stream
            if self.state == TaskRunningState::Running {
                match self.poll() {
                    Ok(Async::Ready(_)) => {
                        self.state = TaskRunningState::Done;
                    }
                    Ok(Async::NotReady) => (),
                    Err(_) => return Err(())
                }
            }

            // use exiting frames
            while let Some(frame) = self.frames.pop_front() {
                match frame {
                    Frame::Message(message) => {
                        self.prepare(message);
                    }
                    Frame::Payload(chunk) => {
                        match chunk {
                            Some(chunk) => {
                                // TODO: add warning, write after EOF
                                self.encoder.encode(&mut self.buffer, chunk.as_ref());
                            }
                            None => {
                                // TODO: add error "not eof""
                                if !self.encoder.encode(&mut self.buffer, [].as_ref()) {
                                    debug!("last payload item, but it is not EOF ");
                                    return Err(())
                                }
                                break
                            }
                        }
                    },
                }
            }
        }

        // write bytes to TcpStream
        while !self.buffer.is_empty() {
            match io.write(self.buffer.as_ref()) {
                Ok(n) => {
                    self.buffer.split_to(n);
                },
                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                    break
                }
                Err(_) => return Err(()),
            }
        }

        // should pause task
        if self.state != TaskRunningState::Done {
            if self.buffer.len() > MAX_WRITE_BUFFER_SIZE {
                self.state = TaskRunningState::Paused;
            } else if self.state == TaskRunningState::Paused {
                self.state = TaskRunningState::Running;
            }
        }

        // response is completed
        if self.buffer.is_empty() && self.iostate.is_done() {
            Ok(Async::Ready(self.state.is_done()))
        } else {
            Ok(Async::NotReady)
        }
    }
}

impl Future for Task {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Some(ref mut stream) = self.stream {
            loop {
                match stream.poll() {
                    Ok(Async::Ready(Some(frame))) => {
                        match frame {
                            Frame::Message(ref msg) => {
                                if self.iostate != TaskIOState::ReadingMessage {
                                    error!("Non expected frame {:?}", frame);
                                    return Err(())
                                }
                                self.upgraded = msg.upgrade();
                                if self.upgraded || msg.body().has_body() {
                                    self.iostate = TaskIOState::ReadingPayload;
                                } else {
                                    self.iostate = TaskIOState::Done;
                                }
                            },
                            Frame::Payload(ref chunk) => {
                                if chunk.is_none() {
                                    self.iostate = TaskIOState::Done;
                                } else if self.iostate != TaskIOState::ReadingPayload {
                                    error!("Non expected frame {:?}", self.iostate);
                                    return Err(())
                                }
                            },
                        }
                        self.frames.push_back(frame)
                    },
                    Ok(Async::Ready(None)) =>
                        return Ok(Async::Ready(())),
                    Ok(Async::NotReady) =>
                        return Ok(Async::NotReady),
                    Err(_) =>
                        return Err(())
                }
            }
        } else {
            Ok(Async::Ready(()))
        }
    }
}

/// Encoders to handle different Transfer-Encodings.
#[derive(Debug, Clone)]
struct Encoder {
    kind: Kind,
}

#[derive(Debug, PartialEq, Clone)]
enum Kind {
    /// An Encoder for when Transfer-Encoding includes `chunked`.
    Chunked(bool),
    /// An Encoder for when Content-Length is set.
    ///
    /// Enforces that the body is not longer than the Content-Length header.
    Length(u64),
    /// An Encoder for when Content-Length is not known.
    ///
    /// Appliction decides when to stop writing.
    Eof,
}

impl Encoder {

    pub fn eof() -> Encoder {
        Encoder {
            kind: Kind::Eof,
        }
    }

    pub fn chunked() -> Encoder {
        Encoder {
            kind: Kind::Chunked(false),
        }
    }

    pub fn length(len: u64) -> Encoder {
        Encoder {
            kind: Kind::Length(len),
        }
    }

    /*pub fn is_eof(&self) -> bool {
        match self.kind {
            Kind::Eof | Kind::Length(0) => true,
            Kind::Chunked(eof) => eof,
            _ => false,
        }
    }*/

    /// Encode message. Return `EOF` state of encoder
    pub fn encode(&mut self, dst: &mut BytesMut, msg: &[u8]) -> bool {
        match self.kind {
            Kind::Eof => {
                dst.extend(msg);
                msg.is_empty()
            },
            Kind::Chunked(ref mut eof) => {
                if *eof {
                    return true;
                }

                if msg.is_empty() {
                    *eof = true;
                    dst.extend(b"0\r\n\r\n");
                } else {
                    write!(dst, "{:X}\r\n", msg.len()).unwrap();
                    dst.extend(msg);
                    dst.extend(b"\r\n");
                }
                *eof
            },
            Kind::Length(ref mut remaining) => {
                if msg.is_empty() {
                    return *remaining == 0
                }
                let max = cmp::min(*remaining, msg.len() as u64);
                trace!("sized write = {}", max);
                dst.extend(msg[..max as usize].as_ref());

                *remaining -= max as u64;
                trace!("encoded {} bytes, remaining = {}", max, remaining);
                *remaining == 0
            },
        }
    }
}
<commit_msg>fix connection upgrade<commit_after>use std::{cmp, io};
use std::io::Write as IoWrite;
use std::fmt::Write;
use std::collections::VecDeque;

use http::{StatusCode, Version};
use http::header::{HeaderValue,
                   CONNECTION, CONTENT_TYPE, CONTENT_LENGTH, TRANSFER_ENCODING, DATE};
use bytes::BytesMut;
use futures::{Async, Future, Poll, Stream};
use tokio_core::net::TcpStream;

use date;
use route::Frame;
use httpmessage::{Body, HttpResponse};

type FrameStream = Stream<Item=Frame, Error=io::Error>;
const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific
const MAX_WRITE_BUFFER_SIZE: usize = 65_536; // max buffer size 64k

#[derive(PartialEq, Debug)]
enum TaskRunningState {
    Paused,
    Running,
    Done,
}

impl TaskRunningState {
    fn is_done(&self) -> bool {
        *self == TaskRunningState::Done
    }
}

#[derive(PartialEq, Debug)]
enum TaskIOState {
    ReadingMessage,
    ReadingPayload,
    Done,
}

impl TaskIOState {
    fn is_done(&self) -> bool {
        *self == TaskIOState::Done
    }
}

pub struct Task {
    state: TaskRunningState,
    iostate: TaskIOState,
    frames: VecDeque<Frame>,
    stream: Option<Box<FrameStream>>,
    encoder: Encoder,
    buffer: BytesMut,
    upgraded: bool,
}

impl Task {

    pub(crate) fn reply(msg: HttpResponse) -> Self {
        let mut frames = VecDeque::new();
        frames.push_back(Frame::Message(msg));
        frames.push_back(Frame::Payload(None));

        Task {
            state: TaskRunningState::Running,
            iostate: TaskIOState::Done,
            frames: frames,
            stream: None,
            encoder: Encoder::length(0),
            buffer: BytesMut::new(),
            upgraded: false,
        }
    }

    pub(crate) fn with_stream<S>(stream: S) -> Self
        where S: Stream<Item=Frame, Error=io::Error> + 'static
    {
        Task {
            state: TaskRunningState::Running,
            iostate: TaskIOState::ReadingMessage,
            frames: VecDeque::new(),
            stream: Some(Box::new(stream)),
            encoder: Encoder::length(0),
            buffer: BytesMut::new(),
            upgraded: false,
        }
    }

    fn prepare(&mut self, mut msg: HttpResponse)
    {
        trace!("Prepare message status={:?}", msg.status);

        let mut extra = 0;
        let body = msg.replace_body(Body::Empty);

        match body {
            Body::Empty => {
                if msg.chunked() {
                    error!("Chunked transfer is enabled but body is set to Empty");
                }
                msg.headers.insert(CONTENT_LENGTH, HeaderValue::from_static("0"));
                msg.headers.remove(TRANSFER_ENCODING);
                self.encoder = Encoder::length(0);
            },
            Body::Length(n) => {
                if msg.chunked() {
                    error!("Chunked transfer is enabled but body with specific length is specified");
                }
                msg.headers.insert(
                    CONTENT_LENGTH,
                    HeaderValue::from_str(format!("{}", n).as_str()).unwrap());
                msg.headers.remove(TRANSFER_ENCODING);
                self.encoder = Encoder::length(n);
            },
            Body::Binary(ref bytes) => {
                extra = bytes.len();
                msg.headers.insert(
                    CONTENT_LENGTH,
                    HeaderValue::from_str(format!("{}", bytes.len()).as_str()).unwrap());
                msg.headers.remove(TRANSFER_ENCODING);
                self.encoder = Encoder::length(0);
            }
            Body::Streaming => {
                if msg.chunked() {
                    if msg.version < Version::HTTP_11 {
                        error!("Chunked transfer encoding is forbidden for {:?}", msg.version);
                    }
                    msg.headers.remove(CONTENT_LENGTH);
                    msg.headers.insert(TRANSFER_ENCODING, HeaderValue::from_static("chunked"));
                    self.encoder = Encoder::chunked();
                } else {
                    self.encoder = Encoder::eof();
                }
            }
            Body::Upgrade => {
                msg.headers.insert(CONNECTION, HeaderValue::from_static("upgrade"));
                self.encoder = Encoder::eof();
            }
        }

        // Connection upgrade
        if msg.upgrade() {
            msg.headers.insert(CONNECTION, HeaderValue::from_static("upgrade"));
        }
        // keep-alive
        else if msg.keep_alive() {
            if msg.version < Version::HTTP_11 {
                msg.headers.insert(CONNECTION, HeaderValue::from_static("keep-alive"));
            }
        } else if msg.version >= Version::HTTP_11 {
            msg.headers.insert(CONNECTION, HeaderValue::from_static("close"));
        }

        // render message
        let init_cap = 100 + msg.headers.len() * AVERAGE_HEADER_SIZE + extra;
        self.buffer.reserve(init_cap);

        if msg.version == Version::HTTP_11 && msg.status == StatusCode::OK {
            self.buffer.extend(b"HTTP/1.1 200 OK\r\n");
        } else {
            let _ = write!(self.buffer, "{:?} {}\r\n", msg.version, msg.status);
        }
        for (key, value) in &msg.headers {
            let t: &[u8] = key.as_ref();
            self.buffer.extend(t);
            self.buffer.extend(b": ");
            self.buffer.extend(value.as_ref());
            self.buffer.extend(b"\r\n");
        }

        // using http::h1::date is quite a lot faster than generating
        // a unique Date header each time like req/s goes up about 10%
        if !msg.headers.contains_key(DATE) {
            self.buffer.reserve(date::DATE_VALUE_LENGTH + 8);
            self.buffer.extend(b"Date: ");
            date::extend(&mut self.buffer);
            self.buffer.extend(b"\r\n");
        }

        // default content-type
        if !msg.headers.contains_key(CONTENT_TYPE) {
            self.buffer.extend(b"ContentType: application/octet-stream\r\n".as_ref());
        }

        self.buffer.extend(b"\r\n");

        if let Body::Binary(ref bytes) = *msg.body() {
            self.buffer.extend(bytes);
            return
        }
        msg.replace_body(body);
    }

    pub(crate) fn poll_io(&mut self, io: &mut TcpStream) -> Poll<bool, ()> {
        println!("POLL-IO {:?}", self.frames.len());
        // response is completed
        if self.frames.is_empty() && self.iostate.is_done() {
            return Ok(Async::Ready(self.state.is_done()));
        } else {
            // poll stream
            if self.state == TaskRunningState::Running {
                match self.poll() {
                    Ok(Async::Ready(_)) => {
                        self.state = TaskRunningState::Done;
                    }
                    Ok(Async::NotReady) => (),
                    Err(_) => return Err(())
                }
            }

            // use exiting frames
            while let Some(frame) = self.frames.pop_front() {
                match frame {
                    Frame::Message(message) => {
                        self.prepare(message);
                    }
                    Frame::Payload(chunk) => {
                        match chunk {
                            Some(chunk) => {
                                // TODO: add warning, write after EOF
                                self.encoder.encode(&mut self.buffer, chunk.as_ref());
                            }
                            None => {
                                // TODO: add error "not eof""
                                if !self.encoder.encode(&mut self.buffer, [].as_ref()) {
                                    debug!("last payload item, but it is not EOF ");
                                    return Err(())
                                }
                                break
                            }
                        }
                    },
                }
            }
        }

        // write bytes to TcpStream
        while !self.buffer.is_empty() {
            match io.write(self.buffer.as_ref()) {
                Ok(n) => {
                    self.buffer.split_to(n);
                },
                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                    break
                }
                Err(_) => return Err(()),
            }
        }

        // should pause task
        if self.state != TaskRunningState::Done {
            if self.buffer.len() > MAX_WRITE_BUFFER_SIZE {
                self.state = TaskRunningState::Paused;
            } else if self.state == TaskRunningState::Paused {
                self.state = TaskRunningState::Running;
            }
        }

        // response is completed
        if self.buffer.is_empty() && self.iostate.is_done() {
            Ok(Async::Ready(self.state.is_done()))
        } else {
            Ok(Async::NotReady)
        }
    }
}

impl Future for Task {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Some(ref mut stream) = self.stream {
            loop {
                match stream.poll() {
                    Ok(Async::Ready(Some(frame))) => {
                        match frame {
                            Frame::Message(ref msg) => {
                                if self.iostate != TaskIOState::ReadingMessage {
                                    error!("Non expected frame {:?}", frame);
                                    return Err(())
                                }
                                self.upgraded = msg.upgrade();
                                if self.upgraded || msg.body().has_body() {
                                    self.iostate = TaskIOState::ReadingPayload;
                                } else {
                                    self.iostate = TaskIOState::Done;
                                }
                            },
                            Frame::Payload(ref chunk) => {
                                if chunk.is_none() {
                                    self.iostate = TaskIOState::Done;
                                } else if self.iostate != TaskIOState::ReadingPayload {
                                    error!("Non expected frame {:?}", self.iostate);
                                    return Err(())
                                }
                            },
                        }
                        self.frames.push_back(frame)
                    },
                    Ok(Async::Ready(None)) =>
                        return Ok(Async::Ready(())),
                    Ok(Async::NotReady) =>
                        return Ok(Async::NotReady),
                    Err(_) =>
                        return Err(())
                }
            }
        } else {
            Ok(Async::Ready(()))
        }
    }
}

/// Encoders to handle different Transfer-Encodings.
#[derive(Debug, Clone)]
struct Encoder {
    kind: Kind,
}

#[derive(Debug, PartialEq, Clone)]
enum Kind {
    /// An Encoder for when Transfer-Encoding includes `chunked`.
    Chunked(bool),
    /// An Encoder for when Content-Length is set.
    ///
    /// Enforces that the body is not longer than the Content-Length header.
    Length(u64),
    /// An Encoder for when Content-Length is not known.
    ///
    /// Appliction decides when to stop writing.
    Eof,
}

impl Encoder {

    pub fn eof() -> Encoder {
        Encoder {
            kind: Kind::Eof,
        }
    }

    pub fn chunked() -> Encoder {
        Encoder {
            kind: Kind::Chunked(false),
        }
    }

    pub fn length(len: u64) -> Encoder {
        Encoder {
            kind: Kind::Length(len),
        }
    }

    /*pub fn is_eof(&self) -> bool {
        match self.kind {
            Kind::Eof | Kind::Length(0) => true,
            Kind::Chunked(eof) => eof,
            _ => false,
        }
    }*/

    /// Encode message. Return `EOF` state of encoder
    pub fn encode(&mut self, dst: &mut BytesMut, msg: &[u8]) -> bool {
        match self.kind {
            Kind::Eof => {
                dst.extend(msg);
                msg.is_empty()
            },
            Kind::Chunked(ref mut eof) => {
                if *eof {
                    return true;
                }

                if msg.is_empty() {
                    *eof = true;
                    dst.extend(b"0\r\n\r\n");
                } else {
                    write!(dst, "{:X}\r\n", msg.len()).unwrap();
                    dst.extend(msg);
                    dst.extend(b"\r\n");
                }
                *eof
            },
            Kind::Length(ref mut remaining) => {
                if msg.is_empty() {
                    return *remaining == 0
                }
                let max = cmp::min(*remaining, msg.len() as u64);
                trace!("sized write = {}", max);
                dst.extend(msg[..max as usize].as_ref());

                *remaining -= max as u64;
                trace!("encoded {} bytes, remaining = {}", max, remaining);
                *remaining == 0
            },
        }
    }
}
<|endoftext|>


<commit_before>use {ffi, FswSession};

fn get_default_session() -> FswSession {
  FswSession::default().unwrap()
}

#[test]
fn create_and_destroy_session() {
  let handle = {
    let session = get_default_session();
    session.handle
  };
  // Check that the handle was created successfully.
  assert!(handle != ffi::FSW_INVALID_HANDLE);
  // Check that trying to destroy the handle after the session wrapper goes out of scope fails.
  // This should fail because the wrapper going out of scope should automatically destroy the
  // session.
  assert!(unsafe { ffi::fsw_destroy_session(handle) } != ffi::FSW_OK);
}

#[test]
fn add_path() {
  let session = get_default_session();
  session.add_path("./").unwrap();
}

#[test]
fn add_property() {
  let session = get_default_session();
  session.add_property("test_name", "test_value").unwrap();
}

#[test]
fn set_allow_overflow() {
  let session = get_default_session();
  session.set_allow_overflow(true).unwrap();
}

#[test]
fn set_callback() {
  let session = get_default_session();
  session.set_callback(|_| {
    println!("Hi!");
  }).unwrap();
}

#[test]
#[should_panic]
fn start_empty() {
  get_default_session().start_monitor().unwrap();
}

#[test]
fn start_without_callback() {
  let session = get_default_session();
  session.add_path("./").unwrap();
  assert!(session.start_monitor().is_err());
}

#[test]
fn start_without_path() {
  let session = get_default_session();
  session.set_callback(|_| println!("Hello")).unwrap();
  assert!(session.start_monitor().is_err());
}
<commit_msg>refactor: update tests to use a full builder<commit_after>use {ffi, FswSession, FswError, FswMonitorType, FswMonitorFilter, FswFilterType, FswEventFlag};

fn get_default_session() -> FswSession {
  FswSession::default().unwrap()
}

fn create_sample_filter() -> FswMonitorFilter {
  FswMonitorFilter::new("\\w+\\.txt$", FswFilterType::Include, false, false)
}

#[test]
fn create_and_destroy_session() {
  let handle = {
    let session = get_default_session();
    session.handle
  };
  // Check that the handle was created successfully.
  assert!(handle != ffi::FSW_INVALID_HANDLE);
  // Check that trying to destroy the handle after the session wrapper goes out of scope fails.
  // This should fail because the wrapper going out of scope should automatically destroy the
  // session.
  assert!(unsafe { ffi::fsw_destroy_session(handle) } != ffi::FSW_OK);
}

#[test]
fn create_session_from_builder() {
  FswSession::builder()
    .add_path("./")
    .property("test_name", "test_value")
    .overflow(Some(true))
    .monitor(FswMonitorType::SystemDefault)
    .latency(Some(1.0))
    .recursive(Some(true))
    .directory_only(Some(false))
    .follow_symlinks(Some(true))
    .add_event_filter(FswEventFlag::Created)
    .add_filter(create_sample_filter())
    .build_callback(|events| println!("{:#?}", events))
    .unwrap();
}

#[test]
fn start_empty() {
  assert_eq!(Err(FswError::MissingRequiredParameters), get_default_session().start_monitor());
}

#[test]
fn start_without_callback() {
  let session = get_default_session();
  session.add_path("./").unwrap();
  assert_eq!(Err(FswError::MissingRequiredParameters), session.start_monitor());
}

#[test]
fn start_without_path() {
  let session = get_default_session();
  session.set_callback(|_| println!("Hello")).unwrap();
  assert_eq!(Err(FswError::MissingRequiredParameters), session.start_monitor());
}
<|endoftext|>


<commit_before>//TODO
//should directly test the plugins, because why not?
//maybe ladspa should have some testing facilities built in.

use super::get_ladspa_descriptor;
use ladspa::{Data, Port, PortConnection, PortData};
use std::cell::RefCell;
use std::thread;
use std::time::Duration;

const SAMPLE_RATE: u64 = 44100;

#[derive(Debug)]
enum OwnedPortData {
    AudioInput(Vec<Data>),
    AudioOutput(Vec<Data>),
    ControlInput(Data),
    ControlOutput(Data),
}

impl PartialEq for OwnedPortData {
    fn eq(&self, other: &Self) -> bool {
        use self::OwnedPortData::*;

        match *self {
            AudioInput(ref a) | AudioOutput(ref a) => {
                match *other {
                    AudioInput(ref b) | AudioOutput(ref b) => a == b,
                    _ => false,
                }
            },
            ControlInput(ref a) | ControlOutput(ref a) => {
                match *other {
                    ControlInput(ref b) | ControlOutput(ref b) => a == b,
                    _ => false,
                }
            }
        }
    }
}

struct OwnedPortConnection {
    port: Port,
    data: OwnedPortData,
}

//TODO port is fragile
fn make_owned_port_connections(ports: &[Port], size: usize, port_tag: f32, input_tag: f32, output_tag: f32) -> Vec<OwnedPortConnection> {
    use ladspa::PortDescriptor::*;

    let mut out = Vec::new();
    for port in ports {
        let data = match port.desc {
            AudioInput => OwnedPortData::AudioInput(vec![input_tag; size]),
            AudioOutput => OwnedPortData::AudioOutput(vec![output_tag; size]),
            ControlInput => OwnedPortData::ControlInput(port_tag),
            ControlOutput => OwnedPortData::ControlOutput(port_tag),
            Invalid => panic!(),
        };
        out.push(OwnedPortConnection {
            port: port.clone(),
            data: data,
        });
    }
    out
}

fn make_port_connections<'a>(owned: &'a mut [OwnedPortConnection]) -> Vec<PortConnection<'a>> {
    let mut out = Vec::new();
    for port in owned {
        let data = match port.data {
            OwnedPortData::AudioInput(ref data) => PortData::AudioInput(data),
            OwnedPortData::AudioOutput(ref mut data) => PortData::AudioOutput(RefCell::new(data)),
            OwnedPortData::ControlInput(ref data) => PortData::ControlInput(data),
            OwnedPortData::ControlOutput(ref mut data) => PortData::ControlOutput(RefCell::new(data)),
        };

        out.push(PortConnection {
            port: port.port,
            data: data,
        });
    }
    out
}

fn borrow_port_connections<'a>(ports: &'a [PortConnection<'a>]) -> Vec<&'a PortConnection<'a>> {
    ports.iter().map(|x| x).collect()
}

//TODO immediately: factor

#[test]
fn test_working_basic() {
    let sample_count = super::packet::BUFFER_SIZE;

    let tx_desc = get_ladspa_descriptor(0).unwrap();
    let rx_desc = get_ladspa_descriptor(1).unwrap();
    let mut tx = (tx_desc.new)(&tx_desc, SAMPLE_RATE);
    let mut rx = (rx_desc.new)(&rx_desc, SAMPLE_RATE);

    rx.activate();
    tx.activate();

    let mut tx_owned = make_owned_port_connections(&tx_desc.ports, sample_count, 0.0, 1.0, 0.0);
    let mut rx_owned = make_owned_port_connections(&rx_desc.ports, sample_count, 0.0, 0.0, 0.0);
    {
        let tx_ports = make_port_connections(&mut tx_owned);
        let rx_ports = make_port_connections(&mut rx_owned);
        let tx_ports = borrow_port_connections(&tx_ports);
        let rx_ports = borrow_port_connections(&rx_ports);

        tx.run(sample_count, &tx_ports);
        thread::sleep(Duration::from_millis(100)); // wait for recv
        rx.run(sample_count, &rx_ports);
    }

    for i in 0..2 {
        assert_eq!(tx_owned[i].data, rx_owned[i+2].data);
    }

    rx.deactivate();
    tx.deactivate();
}

#[test]
fn test_working_multi_packet() {
    let sample_count = super::packet::BUFFER_SIZE*4;

    let tx_desc = get_ladspa_descriptor(0).unwrap();
    let rx_desc = get_ladspa_descriptor(1).unwrap();
    let mut tx = (tx_desc.new)(&tx_desc, SAMPLE_RATE);
    let mut rx = (rx_desc.new)(&rx_desc, SAMPLE_RATE);

    rx.activate();
    tx.activate();

    let mut tx_owned = make_owned_port_connections(&tx_desc.ports, sample_count, 1.0, 1.0, 0.0);
    let mut rx_owned = make_owned_port_connections(&rx_desc.ports, sample_count, 1.0, 0.0, 0.0);
    {
        let tx_ports = make_port_connections(&mut tx_owned);
        let rx_ports = make_port_connections(&mut rx_owned);
        let tx_ports = borrow_port_connections(&tx_ports);
        let rx_ports = borrow_port_connections(&rx_ports);

        tx.run(sample_count, &tx_ports);
        thread::sleep(Duration::from_millis(100)); // wait for recv
        rx.run(sample_count, &rx_ports);
    }

    for i in 0..2 {
        assert_eq!(tx_owned[i].data, rx_owned[i+2].data);
    }

    rx.deactivate();
    tx.deactivate();
}
<commit_msg>factor<commit_after>//TODO
//should directly test the plugins, because why not?
//maybe ladspa should have some testing facilities built in.

use super::get_ladspa_descriptor;
use ladspa::{Data, Port, PortConnection, PortData};
use std::cell::RefCell;
use std::thread;
use std::time::Duration;

const SAMPLE_RATE: u64 = 44100;

#[derive(Debug)]
enum OwnedPortData {
    AudioInput(Vec<Data>),
    AudioOutput(Vec<Data>),
    ControlInput(Data),
    ControlOutput(Data),
}

impl PartialEq for OwnedPortData {
    fn eq(&self, other: &Self) -> bool {
        use self::OwnedPortData::*;

        match *self {
            AudioInput(ref a) | AudioOutput(ref a) => {
                match *other {
                    AudioInput(ref b) | AudioOutput(ref b) => a == b,
                    _ => false,
                }
            },
            ControlInput(ref a) | ControlOutput(ref a) => {
                match *other {
                    ControlInput(ref b) | ControlOutput(ref b) => a == b,
                    _ => false,
                }
            }
        }
    }
}

struct OwnedPortConnection {
    port: Port,
    data: OwnedPortData,
}

//TODO port is fragile
fn make_owned_port_connections(ports: &[Port], size: usize, port_tag: f32, input_tag: f32, output_tag: f32) -> Vec<OwnedPortConnection> {
    use ladspa::PortDescriptor::*;

    let mut out = Vec::new();
    for port in ports {
        let data = match port.desc {
            AudioInput => OwnedPortData::AudioInput(vec![input_tag; size]),
            AudioOutput => OwnedPortData::AudioOutput(vec![output_tag; size]),
            ControlInput => OwnedPortData::ControlInput(port_tag),
            ControlOutput => OwnedPortData::ControlOutput(port_tag),
            Invalid => panic!(),
        };
        out.push(OwnedPortConnection {
            port: port.clone(),
            data: data,
        });
    }
    out
}

fn make_port_connections<'a>(owned: &'a mut [OwnedPortConnection]) -> Vec<PortConnection<'a>> {
    let mut out = Vec::new();
    for port in owned {
        let data = match port.data {
            OwnedPortData::AudioInput(ref data) => PortData::AudioInput(data),
            OwnedPortData::AudioOutput(ref mut data) => PortData::AudioOutput(RefCell::new(data)),
            OwnedPortData::ControlInput(ref data) => PortData::ControlInput(data),
            OwnedPortData::ControlOutput(ref mut data) => PortData::ControlOutput(RefCell::new(data)),
        };

        out.push(PortConnection {
            port: port.port,
            data: data,
        });
    }
    out
}

fn borrow_port_connections<'a>(ports: &'a [PortConnection<'a>]) -> Vec<&'a PortConnection<'a>> {
    ports.iter().map(|x| x).collect()
}

//TODO immediately: factor

#[test]
fn test_working_basic() {
    let sample_count = super::packet::BUFFER_SIZE;
    test_sample_count(sample_count, 0);
}

#[test]
fn test_working_multi_packet() {
    let sample_count = super::packet::BUFFER_SIZE*4;
    test_sample_count(sample_count, 1);
}

fn test_sample_count(sample_count: usize, port: u8) {
    let tx_desc = get_ladspa_descriptor(0).unwrap();
    let rx_desc = get_ladspa_descriptor(1).unwrap();
    let mut tx = (tx_desc.new)(&tx_desc, SAMPLE_RATE);
    let mut rx = (rx_desc.new)(&rx_desc, SAMPLE_RATE);

    rx.activate();
    tx.activate();

    let mut tx_owned = make_owned_port_connections(&tx_desc.ports, sample_count, port as f32, 1.0, 0.0);
    let mut rx_owned = make_owned_port_connections(&rx_desc.ports, sample_count, port as f32, 0.0, 0.0);
    {
        let tx_ports = make_port_connections(&mut tx_owned);
        let rx_ports = make_port_connections(&mut rx_owned);
        let tx_ports = borrow_port_connections(&tx_ports);
        let rx_ports = borrow_port_connections(&rx_ports);

        tx.run(sample_count, &tx_ports);
        thread::sleep(Duration::from_millis(100)); // wait for recv
        rx.run(sample_count, &rx_ports);
    }

    for i in 0..2 {
        assert_eq!(tx_owned[i].data, rx_owned[i+2].data);
    }

    rx.deactivate();
    tx.deactivate();
}
<|endoftext|>