<commit_before>use av_format::error::*;
use std::io::SeekFrom;
use av_data::packet::Packet;
use av_data::timeinfo::TimeInfo;
use av_data::params::*;
use av_format::stream::Stream;
use av_format::buffer::Buffered;
use av_format::demuxer::{Demuxer, Event};
use av_format::demuxer::{Descr, Descriptor};
use av_format::demuxer::GlobalInfo;
use std::collections::VecDeque;
use rational::Rational64;

use ebml::{ebml_header, EBMLHeader};
use elements::{segment, segment_element, Cluster, SeekHead, Info, Tracks, TrackEntry,
               SegmentElement, simple_block};
use nom::{self, Err, IResult, Offset};

#[derive(Debug, Clone, PartialEq)]
pub struct MkvDemuxer {
    pub header: Option<EBMLHeader>,
    pub seek_head: Option<SeekHead>,
    pub info: Option<Info>,
    pub tracks: Option<Tracks>,
    pub queue: VecDeque<Event>,
    pub blockstream: Vec<u8>,
}

impl MkvDemuxer {
    pub fn new() -> MkvDemuxer {
        MkvDemuxer {
            header: None,
            seek_head: None,
            info: None,
            tracks: None,
            queue: VecDeque::new(),
            blockstream: Vec::new(),
        }
    }

    pub fn parse_until_tracks<'a>(&mut self, original_input: &'a [u8]) -> IResult<&'a [u8], ()> {
        let (i1, header) = try_parse!(original_input, ebml_header);

        self.header = Some(header);

        let (mut input, _) = try_parse!(i1, segment);

        self.seek_head = None;
        self.info = None;
        self.tracks = None;

        loop {
            if self.seek_head.is_some() && self.info.is_some() && self.tracks.is_some() {
                return Ok((input, ()));
            }

            println!("offset: {}", original_input.offset(input));

            let (i3, element) = try_parse!(input, segment_element);

            match element {
                SegmentElement::SeekHead(s) => {
                    println!("got seek head: {:#?}", s);
                    if self.seek_head.is_some() {
                        return Err(Err::Error(error_position!(nom::ErrorKind::Custom(1), input)));
                    } else {
                        self.seek_head = Some(s);
                    }
                }
                SegmentElement::Info(i) => {
                    println!("got info: {:#?}", i);
                    if self.info.is_some() {
                        return Err(Err::Error(error_position!(nom::ErrorKind::Custom(1), input)));
                    } else {
                        self.info = Some(i);
                    }
                }
                SegmentElement::Tracks(t) => {
                    println!("got tracks: {:#?}", t);
                    if self.tracks.is_some() {
                        return Err(Err::Error(error_position!(nom::ErrorKind::Custom(1), input)));
                    } else {
                        self.tracks = Some(t);
                    }
                }
                SegmentElement::Cluster(c) => {
                    println!("got a cluster: {:#?}", c);
                    //self.clusters.push(c);
                }
                el => {
                    println!("got element: {:#?}", el);
                }
            }

            input = i3;
        }
    }
}

use nom::Needed;

impl Demuxer for MkvDemuxer {
    fn read_headers(&mut self, buf: &Box<Buffered>, info: &mut GlobalInfo) -> Result<SeekFrom> {
        match self.parse_until_tracks(buf.data()) {
            Ok((i, _)) => {
                info.duration = self.info.as_ref().and_then(|info| info.duration).map(|d| d as u64);
                if let Some(ref t) = self.tracks {
                    info.streams = t.tracks.iter().map(|tr| {
                        track_to_stream(self.info.as_ref().unwrap(), tr)
                    }).collect();
                }
                Ok(SeekFrom::Current(buf.data().offset(i) as i64))
            },
            Err(Err::Incomplete(needed)) => {
                let sz = match needed {
                    Needed::Size(size) => size,
                    _ => 1024,
                };
                Err(ErrorKind::MoreDataNeeded(sz).into())
            },
            e => {
                println!("error reading headers: {:?}", e);
                Err(ErrorKind::InvalidData.into())
            }
        }
    }

    fn read_event(&mut self, buf: &Box<Buffered>) -> Result<(SeekFrom, Event)> {
        if let Some(event) = self.queue.pop_front() {
            Ok((SeekFrom::Current(0), event))
        } else {
            println!("no more stored packet, parsing a new one");
            match segment_element(buf.data()) {
                Ok((i, element)) => {
                    let seek = SeekFrom::Current(buf.data().offset(i) as i64);
                    match element {
                        SegmentElement::Cluster(c) => {
                            //self.clusters.push(c);
                            println!("got cluster element at timecode: {}", c.timecode);
                            let mut packets = c.generate_packets();
                            self.queue.extend(packets.drain(..));
                            if let Some(event) = self.queue.pop_front() {
                                return Ok((seek, event));
                            }
                        }
                        el => {
                            println!("got element: {:#?}", el);
                        }
                    }
                    Ok((seek, Event::MoreDataNeeded(0)))
                },
                Err(Err::Incomplete(Needed::Size(size))) => {
                    Err(ErrorKind::MoreDataNeeded(size).into())
                },
                e => {
                    println!("parsing issue: {:?}", e);
                    Err(ErrorKind::InvalidData.into())
                }
            }
        }
    }
}

fn track_entry_codec_id(t: &TrackEntry) -> Option<String> {
    // TODO: Support V_QUICKTIME and V_MS/VFW/FOURCC
    match t.codec_id.as_ref() {
        "A_OPUS" => Some("opus".to_owned()),
        "V_VP9" => Some("vp9".to_owned()),
        _ => None,
    }
}

fn track_entry_video_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref video) = t.video {
        let v = VideoInfo {
            width: video.pixel_width as usize,
            height: video.pixel_height as usize,
            // TODO parse Colour and/or CodecPrivate to extract the format
            format: None,
        };
        Some(MediaKind::Video(v))
    } else {
        None
    }
}

fn track_entry_audio_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref audio) = t.audio {
        let rate = if let Some(r) = audio.output_sampling_frequency {
            r
        } else {
            audio.sampling_frequency
        };
        // TODO: complete it
        let a = AudioInfo {
            rate: rate as usize,
            map: None,
            format: None,
        };
        Some(MediaKind::Audio(a))
    } else {
        None
    }
}

fn track_entry_media_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Use an enum for the track type
    match t.track_type {
        0x1 => track_entry_video_kind(t),
        0x2 => track_entry_audio_kind(t),
        _ => None,
    }
}

// TODO: make sure the timecode_scale isn't 0
pub fn track_to_stream(info: &Info, t: &TrackEntry) -> Stream {
    let num = if let Some(ts) = t.track_timecode_scale  {
        (ts * info.timecode_scale as f64) as i64
    } else {
        info.timecode_scale as i64
    };

    Stream {
        id: t.track_uid as usize,
        index: t.track_number as usize,
        start: None,
        duration: t.default_duration,
        timebase: Rational64::new(num, 1000 * 1000 * 1000),
        // TODO: Extend CodecParams and fill it with the remaining information
        params: CodecParams {
            extradata: t.codec_private.clone(),
            bit_rate: 0,
            delay: t.codec_delay.unwrap_or(0) as usize,
            convergence_window: t.seek_pre_roll.unwrap_or(0) as usize,
            codec_id: track_entry_codec_id(t),
            kind: track_entry_media_kind(t),
        },
    }
}

impl<'a> Cluster<'a> {
    pub fn generate_packets(&self) -> Vec<Event> {
        let mut v = Vec::new();

        for block_data in self.simple_block.iter() {
            if let Ok((i, block)) = simple_block(block_data) {
                //println!("parsing simple block: {:?}", block);
                let packet = Packet {
                    data: i.into(),
                    t: TimeInfo {
                        pts: Some(block.timecode as i64),
                        dts: None,
                        duration: None,
                        timebase: None,
                    },
                    pos: None,
                    stream_index: block.track_number as isize,
                    is_key: block.keyframe,
                    is_corrupted: false,
                };

                v.push(Event::NewPacket(packet));
            } else {
                println!("error parsing simple block");
            }
        }

        v
    }
}

struct Des {
    d: Descr,
}

impl Descriptor for Des {
    fn create(&self) -> Box<Demuxer> {
        Box::new(MkvDemuxer::new())
    }
    fn describe<'a>(&'a self) -> &'a Descr {
        &self.d
    }
    fn probe(&self, data: &[u8]) -> u8 {
        match ebml_header(&data[..100]) {
            Ok(_) => 100,
            _ => 0,
        }
    }
}

pub const MKV_DESC: &Descriptor = &Des {
    d: Descr {
        name: "matroska",
        demuxer: "mkv",
        description: "Nom-based Matroska demuxer",
        extensions: &["mkv", "webm", "mka"],
        mime: &["video/x-matroska", "audio/x-matroska"],
    }
};

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;
    use nom::Offset;
    use av_format::demuxer::Context;
    use av_format::buffer::*;

    const webm: &'static [u8] = include_bytes!("../assets/bbb-vp9-opus.webm");

    #[test]
    fn parse_headers() {
        let mut demuxer = MkvDemuxer::new();

        let res = demuxer.parse_until_tracks(webm);
        println!("got parsing res: {:?}", res);
        match res {
            Ok((i, _)) => {
                println!("offset: {} bytes", webm.offset(i));
            }
            e => {
                println!("could not parse: {:?}", e);
            }
        }

        println!("demuxer: {:#?}", demuxer);
    }

    #[test]
    fn parse_headers_incremental_buffer() {
        let mut demuxer = MkvDemuxer::new();

        for n in 100..2000 {
            let res = demuxer.parse_until_tracks(&webm[0..n]);
            match res {
                Ok(_) => println!("Size {} ok", n),
                Err(Err::Incomplete(needed)) => println!("Incomplete {} needs {:?}", n, needed),
                Err(e) => {
                    println!("Error at size {}", n);
                    panic!();
                }
            }
        }
    }

    #[test]
    fn context() {
        let mut context = Context::new(Box::new(MkvDemuxer::new()),
                                       Box::new(AccReader::new(Cursor::new(webm))));
        println!("DEMUXER CONTEXT read headers: {:?}", context.read_headers());
        println!("DEMUXER CONTEXT streams: {:?}", context.info.streams);
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        panic!();
    }
}
<commit_msg>Update to the current API<commit_after>use av_format::error::*;
use std::io::SeekFrom;
use av_data::packet::Packet;
use av_data::timeinfo::TimeInfo;
use av_data::params::*;
use av_format::stream::Stream;
use av_format::buffer::Buffered;
use av_format::demuxer::{Demuxer, Event};
use av_format::demuxer::{Descr, Descriptor};
use av_format::common::GlobalInfo;
use std::collections::VecDeque;
use rational::Rational64;

use ebml::{ebml_header, EBMLHeader};
use elements::{segment, segment_element, Cluster, SeekHead, Info, Tracks, TrackEntry,
               SegmentElement, simple_block};
use nom::{self, Err, IResult, Offset};

#[derive(Debug, Clone, PartialEq)]
pub struct MkvDemuxer {
    pub header: Option<EBMLHeader>,
    pub seek_head: Option<SeekHead>,
    pub info: Option<Info>,
    pub tracks: Option<Tracks>,
    pub queue: VecDeque<Event>,
    pub blockstream: Vec<u8>,
}

impl MkvDemuxer {
    pub fn new() -> MkvDemuxer {
        MkvDemuxer {
            header: None,
            seek_head: None,
            info: None,
            tracks: None,
            queue: VecDeque::new(),
            blockstream: Vec::new(),
        }
    }

    pub fn parse_until_tracks<'a>(&mut self, original_input: &'a [u8]) -> IResult<&'a [u8], ()> {
        let (i1, header) = try_parse!(original_input, ebml_header);

        self.header = Some(header);

        let (mut input, _) = try_parse!(i1, segment);

        self.seek_head = None;
        self.info = None;
        self.tracks = None;

        loop {
            if self.seek_head.is_some() && self.info.is_some() && self.tracks.is_some() {
                return Ok((input, ()));
            }

            println!("offset: {}", original_input.offset(input));

            let (i3, element) = try_parse!(input, segment_element);

            match element {
                SegmentElement::SeekHead(s) => {
                    println!("got seek head: {:#?}", s);
                    if self.seek_head.is_some() {
                        return Err(Err::Error(error_position!(nom::ErrorKind::Custom(1), input)));
                    } else {
                        self.seek_head = Some(s);
                    }
                }
                SegmentElement::Info(i) => {
                    println!("got info: {:#?}", i);
                    if self.info.is_some() {
                        return Err(Err::Error(error_position!(nom::ErrorKind::Custom(1), input)));
                    } else {
                        self.info = Some(i);
                    }
                }
                SegmentElement::Tracks(t) => {
                    println!("got tracks: {:#?}", t);
                    if self.tracks.is_some() {
                        return Err(Err::Error(error_position!(nom::ErrorKind::Custom(1), input)));
                    } else {
                        self.tracks = Some(t);
                    }
                }
                SegmentElement::Cluster(c) => {
                    println!("got a cluster: {:#?}", c);
                    //self.clusters.push(c);
                }
                el => {
                    println!("got element: {:#?}", el);
                }
            }

            input = i3;
        }
    }
}

use nom::Needed;

impl Demuxer for MkvDemuxer {
    fn read_headers(&mut self, buf: &Box<Buffered>, info: &mut GlobalInfo) -> Result<SeekFrom> {
        match self.parse_until_tracks(buf.data()) {
            Ok((i, _)) => {
                info.duration = self.info.as_ref().and_then(|info| info.duration).map(|d| d as u64);
                if let Some(ref t) = self.tracks {
                    info.streams = t.tracks.iter().map(|tr| {
                        track_to_stream(self.info.as_ref().unwrap(), tr)
                    }).collect();
                }
                Ok(SeekFrom::Current(buf.data().offset(i) as i64))
            },
            Err(Err::Incomplete(needed)) => {
                let sz = match needed {
                    Needed::Size(size) => size,
                    _ => 1024,
                };
                Err(ErrorKind::MoreDataNeeded(sz).into())
            },
            e => {
                println!("error reading headers: {:?}", e);
                Err(ErrorKind::InvalidData.into())
            }
        }
    }

    fn read_event(&mut self, buf: &Box<Buffered>) -> Result<(SeekFrom, Event)> {
        if let Some(event) = self.queue.pop_front() {
            Ok((SeekFrom::Current(0), event))
        } else {
            println!("no more stored packet, parsing a new one");
            match segment_element(buf.data()) {
                Ok((i, element)) => {
                    let seek = SeekFrom::Current(buf.data().offset(i) as i64);
                    match element {
                        SegmentElement::Cluster(c) => {
                            //self.clusters.push(c);
                            println!("got cluster element at timecode: {}", c.timecode);
                            let mut packets = c.generate_packets();
                            self.queue.extend(packets.drain(..));
                            if let Some(event) = self.queue.pop_front() {
                                return Ok((seek, event));
                            }
                        }
                        el => {
                            println!("got element: {:#?}", el);
                        }
                    }
                    Ok((seek, Event::MoreDataNeeded(0)))
                },
                Err(Err::Incomplete(Needed::Size(size))) => {
                    Err(ErrorKind::MoreDataNeeded(size).into())
                },
                e => {
                    println!("parsing issue: {:?}", e);
                    Err(ErrorKind::InvalidData.into())
                }
            }
        }
    }
}

fn track_entry_codec_id(t: &TrackEntry) -> Option<String> {
    // TODO: Support V_QUICKTIME and V_MS/VFW/FOURCC
    match t.codec_id.as_ref() {
        "A_OPUS" => Some("opus".to_owned()),
        "V_VP9" => Some("vp9".to_owned()),
        _ => None,
    }
}

fn track_entry_video_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref video) = t.video {
        let v = VideoInfo {
            width: video.pixel_width as usize,
            height: video.pixel_height as usize,
            // TODO parse Colour and/or CodecPrivate to extract the format
            format: None,
        };
        Some(MediaKind::Video(v))
    } else {
        None
    }
}

fn track_entry_audio_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref audio) = t.audio {
        let rate = if let Some(r) = audio.output_sampling_frequency {
            r
        } else {
            audio.sampling_frequency
        };
        // TODO: complete it
        let a = AudioInfo {
            rate: rate as usize,
            map: None,
            format: None,
        };
        Some(MediaKind::Audio(a))
    } else {
        None
    }
}

fn track_entry_media_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Use an enum for the track type
    match t.track_type {
        0x1 => track_entry_video_kind(t),
        0x2 => track_entry_audio_kind(t),
        _ => None,
    }
}

// TODO: make sure the timecode_scale isn't 0
pub fn track_to_stream(info: &Info, t: &TrackEntry) -> Stream {
    let num = if let Some(ts) = t.track_timecode_scale  {
        (ts * info.timecode_scale as f64) as i64
    } else {
        info.timecode_scale as i64
    };

    Stream {
        id: t.track_uid as usize,
        index: t.track_number as usize,
        start: None,
        duration: t.default_duration,
        timebase: Rational64::new(num, 1000 * 1000 * 1000),
        // TODO: Extend CodecParams and fill it with the remaining information
        params: CodecParams {
            extradata: t.codec_private.clone(),
            bit_rate: 0,
            delay: t.codec_delay.unwrap_or(0) as usize,
            convergence_window: t.seek_pre_roll.unwrap_or(0) as usize,
            codec_id: track_entry_codec_id(t),
            kind: track_entry_media_kind(t),
        },
    }
}

impl<'a> Cluster<'a> {
    pub fn generate_packets(&self) -> Vec<Event> {
        let mut v = Vec::new();

        for block_data in self.simple_block.iter() {
            if let Ok((i, block)) = simple_block(block_data) {
                //println!("parsing simple block: {:?}", block);
                let packet = Packet {
                    data: i.into(),
                    t: TimeInfo {
                        pts: Some(block.timecode as i64),
                        dts: None,
                        duration: None,
                        timebase: None,
                    },
                    pos: None,
                    stream_index: block.track_number as isize,
                    is_key: block.keyframe,
                    is_corrupted: false,
                };

                v.push(Event::NewPacket(packet));
            } else {
                println!("error parsing simple block");
            }
        }

        v
    }
}

struct Des {
    d: Descr,
}

impl Descriptor for Des {
    fn create(&self) -> Box<Demuxer> {
        Box::new(MkvDemuxer::new())
    }
    fn describe<'a>(&'a self) -> &'a Descr {
        &self.d
    }
    fn probe(&self, data: &[u8]) -> u8 {
        match ebml_header(&data[..100]) {
            Ok(_) => 100,
            _ => 0,
        }
    }
}

pub const MKV_DESC: &Descriptor = &Des {
    d: Descr {
        name: "matroska",
        demuxer: "mkv",
        description: "Nom-based Matroska demuxer",
        extensions: &["mkv", "webm", "mka"],
        mime: &["video/x-matroska", "audio/x-matroska"],
    }
};

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;
    use nom::Offset;
    use av_format::demuxer::Context;
    use av_format::buffer::*;

    const webm: &'static [u8] = include_bytes!("../assets/bbb-vp9-opus.webm");

    #[test]
    fn parse_headers() {
        let mut demuxer = MkvDemuxer::new();

        let res = demuxer.parse_until_tracks(webm);
        println!("got parsing res: {:?}", res);
        match res {
            Ok((i, _)) => {
                println!("offset: {} bytes", webm.offset(i));
            }
            e => {
                println!("could not parse: {:?}", e);
            }
        }

        println!("demuxer: {:#?}", demuxer);
    }

    #[test]
    fn parse_headers_incremental_buffer() {
        let mut demuxer = MkvDemuxer::new();

        for n in 100..2000 {
            let res = demuxer.parse_until_tracks(&webm[0..n]);
            match res {
                Ok(_) => println!("Size {} ok", n),
                Err(Err::Incomplete(needed)) => println!("Incomplete {} needs {:?}", n, needed),
                Err(e) => {
                    println!("Error at size {}", n);
                    panic!();
                }
            }
        }
    }

    #[test]
    fn context() {
        let mut context = Context::new(Box::new(MkvDemuxer::new()),
                                       Box::new(AccReader::new(Cursor::new(webm))));
        println!("DEMUXER CONTEXT read headers: {:?}", context.read_headers());
        println!("DEMUXER CONTEXT streams: {:?}", context.info.streams);
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        println!("DEMUXER CONTEXT event: {:?}", context.read_event());
        panic!();
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::io::{self};
use std::error::Error;
use std::net::{UdpSocket, SocketAddr, ToSocketAddrs};
use std::fmt;

use bincode::serde::{DeserializeError, SerializeError, serialize, deserialize};
use bincode;
use serde::{Serialize, Deserialize};

pub struct Transit<T> {
    socket: UdpSocket,
    packet_type: PhantomData<T>,
}

#[derive(Debug)]
pub enum TransitError {
    IoError(io::Error),
    SerializeError(SerializeError),
    DeserializeError(DeserializeError),
}

impl Error for TransitError {
    fn description(&self) -> &str {
        match *self {
            TransitError::IoError(ref err) => Error::description(err),
            TransitError::SerializeError(ref err) => Error::description(err),
            TransitError::DeserializeError(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            TransitError::IoError(ref err) => err.cause(),
            TransitError::SerializeError(ref err) => err.cause(),
            TransitError::DeserializeError(ref err) => err.cause(),
        }
    }
}

impl From<io::Error> for TransitError {
    fn from(err: io::Error) -> TransitError {
        TransitError::IoError(err)
    }
}

impl From<DeserializeError> for TransitError {
    fn from(err: DeserializeError) -> TransitError {
        TransitError::DeserializeError(err)
    }
}

impl From<SerializeError> for TransitError {
    fn from(err: SerializeError) -> TransitError {
        TransitError::SerializeError(err)
    }
}

impl fmt::Display for TransitError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TransitError::IoError(ref err) =>
                write!(fmt, "IoError: {}", err),
            TransitError::DeserializeError(ref err) =>
                write!(fmt, "DeserializeError: {}", err),
            TransitError::SerializeError(ref err) =>
                write!(fmt, "SerializeError: {}", err),
        }
    }
}

/// Sends and receives types over UDP, removing any knowledge of buffers and dealing with the std
/// library.
///
/// This use the `bincode` crate to serialize objects. Does not currently support securely sending
/// packets over the network or ensuring that only packets of the correct type are serialized.
///
/// # Examples
///
/// ```rust
/// use std::io;
/// use transit::udp::*;
///
/// let transit = Transit::new("localhost:65000").unwrap();
/// let transit2 = Transit::new("localhost:65001").unwrap();
/// let test = String::from("hello, rust");
///
/// let res = transit.send_to(&test, "localhost:65001");
/// assert!(res.is_ok());
/// let res: Result<(String, _), TransitError> = transit2.recv_from();
/// assert!(res.is_ok());
/// let (data, _addr) = res.unwrap();
/// assert_eq!(data, "hello, rust");
/// ```
impl<T> Transit<T> {
    pub fn new<A>(addr: A) -> Result<Transit<T>, TransitError> where A: ToSocketAddrs {
        let socket = try!(UdpSocket::bind(addr));
        Ok(Transit {
            socket: socket,
            packet_type: PhantomData,
        })
    }

    /// On success, this function returns the type deserialized using the Deserialize trait
    /// implementation. It is not defined what happens when Transit trys to deserialize a different
    /// type into another currently.
    pub fn recv_from(&self) -> Result<(T, SocketAddr), TransitError> where T: Deserialize {
        let mut buf = [0; 65535]; // Max size of UDP packet
        let (n, addr) = try!(self.socket.recv_from(&mut buf));
        let data = try!(deserialize(&buf[..n]));
        Ok((data, addr))
    }

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<A>(&self, pkt: &T, addr: A) -> Result<(), TransitError> where T: Serialize, A: ToSocketAddrs {
        let sizelimit = bincode::SizeLimit::Bounded(65535);
        let vec = try!(serialize(pkt, sizelimit));
        try!(self.socket.send_to(&vec[..], addr));
        Ok(())
    }

    pub fn local_addr(&self)  -> Result<SocketAddr, TransitError> {
        let addr = try!(self.socket.local_addr());
        Ok(addr)
    }
}

#[cfg(test)]
mod test {
    use udp::*;

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Test {
        ten: u8,
    }

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Another {
        data: String,
    }

    #[test]
    fn test_send_recv() {
        let addr1 = "127.0.0.1:61001";
        let addr2 = "127.0.0.1:61002";
        let transit1: Transit<Test> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = Test { ten: 10 };

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_string() {
        let addr1 = "127.0.0.1:63001";
        let addr2 = "127.0.0.1:63002";
        let transit1: Transit<String> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = String::from("hello");

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_bytes() {
        let addr1 = "127.0.0.1:64001";
        let addr2 = "127.0.0.1:64002";
        let transit1 = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let vec = vec!(9u8);
        let slice = &vec[..];

        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());
        let res: Result<(Vec<u8>, _), TransitError> = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, vec);
    }

    // TODO: How to ensure different types are not deserialized as each other with bincode?
    // #[test]
    // fn test_packet_type() {
    //     let addr1 = "127.0.0.1:62001";
    //     let addr2 = "127.0.0.1:62002";
    //     let transit1: Transit<Another> = Transit::new(addr1).unwrap();
    //     let transit2: Transit<Test> = Transit::new(addr2).unwrap();
    //     let test = Another { data: String::from("Hello") };

    //     let res = transit1.send_to(&test, addr2);
    //     assert!(res.is_ok());
    //     let res = transit2.recv_from();
    //     assert!(res.is_err());
    // }
}
<commit_msg>Use abstract UnderlyingError for errors that might change<commit_after>use std::marker::PhantomData;
use std::io::{self};
use std::error::Error;
use std::net::{UdpSocket, SocketAddr, ToSocketAddrs};
use std::fmt;

use bincode::serde::{DeserializeError, SerializeError, serialize, deserialize};
use bincode;
use serde::{Serialize, Deserialize};

pub struct Transit<T> {
    socket: UdpSocket,
    packet_type: PhantomData<T>,
}

pub type UnderlyingError = Box<Error + Send + Sync>;
#[derive(Debug)]
pub enum TransitError {
    IoError(io::Error),
    SerializeError(UnderlyingError),
    DeserializeError(UnderlyingError),
}

impl Error for TransitError {
    fn description(&self) -> &str {
        match *self {
            TransitError::IoError(ref err) => err.description(),
            TransitError::SerializeError(ref err) => err.description(),
            TransitError::DeserializeError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            TransitError::IoError(ref err) => err.cause(),
            TransitError::SerializeError(ref err) => err.cause(),
            TransitError::DeserializeError(ref err) => err.cause(),
        }
    }
}

impl From<io::Error> for TransitError {
    fn from(err: io::Error) -> TransitError {
        TransitError::IoError(err)
    }
}

impl From<DeserializeError> for TransitError {
    fn from(err: DeserializeError) -> TransitError {
        TransitError::DeserializeError(Box::new(err))
    }
}

impl From<SerializeError> for TransitError {
    fn from(err: SerializeError) -> TransitError {
        TransitError::SerializeError(Box::new(err))
    }
}

impl fmt::Display for TransitError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TransitError::IoError(ref err) =>
                write!(fmt, "IoError: {}", err),
            TransitError::DeserializeError(ref err) =>
                write!(fmt, "DeserializeError: {}", err),
            TransitError::SerializeError(ref err) =>
                write!(fmt, "SerializeError: {}", err),
        }
    }
}

/// Sends and receives types over UDP, removing any knowledge of buffers and dealing with the std
/// library.
///
/// This use the `bincode` crate to serialize objects. Does not currently support securely sending
/// packets over the network or ensuring that only packets of the correct type are serialized.
///
/// # Examples
///
/// ```rust
/// use std::io;
/// use transit::udp::*;
///
/// let transit = Transit::new("localhost:65000").unwrap();
/// let transit2 = Transit::new("localhost:65001").unwrap();
/// let test = String::from("hello, rust");
///
/// let res = transit.send_to(&test, "localhost:65001");
/// assert!(res.is_ok());
/// let res: Result<(String, _), TransitError> = transit2.recv_from();
/// assert!(res.is_ok());
/// let (data, _addr) = res.unwrap();
/// assert_eq!(data, "hello, rust");
/// ```
impl<T> Transit<T> {
    pub fn new<A>(addr: A) -> Result<Transit<T>, TransitError> where A: ToSocketAddrs {
        let socket = try!(UdpSocket::bind(addr));
        Ok(Transit {
            socket: socket,
            packet_type: PhantomData,
        })
    }

    /// On success, this function returns the type deserialized using the Deserialize trait
    /// implementation. It is not defined what happens when Transit trys to deserialize a different
    /// type into another currently.
    pub fn recv_from(&self) -> Result<(T, SocketAddr), TransitError> where T: Deserialize {
        let mut buf = [0; 65535]; // Max size of UDP packet
        let (n, addr) = try!(self.socket.recv_from(&mut buf));
        let data = try!(deserialize(&buf[..n]));
        Ok((data, addr))
    }

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<A>(&self, pkt: &T, addr: A) -> Result<(), TransitError> where T: Serialize, A: ToSocketAddrs {
        let sizelimit = bincode::SizeLimit::Bounded(65535);
        let vec = try!(serialize(pkt, sizelimit));
        try!(self.socket.send_to(&vec[..], addr));
        Ok(())
    }

    pub fn local_addr(&self)  -> Result<SocketAddr, TransitError> {
        let addr = try!(self.socket.local_addr());
        Ok(addr)
    }
}

#[cfg(test)]
mod test {
    use udp::*;

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Test {
        ten: u8,
    }

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Another {
        data: String,
    }

    #[test]
    fn test_send_recv() {
        let addr1 = "127.0.0.1:61001";
        let addr2 = "127.0.0.1:61002";
        let transit1: Transit<Test> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = Test { ten: 10 };

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_string() {
        let addr1 = "127.0.0.1:63001";
        let addr2 = "127.0.0.1:63002";
        let transit1: Transit<String> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = String::from("hello");

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_bytes() {
        let addr1 = "127.0.0.1:64001";
        let addr2 = "127.0.0.1:64002";
        let transit1 = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let vec = vec!(9u8);
        let slice = &vec[..];

        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());
        let res: Result<(Vec<u8>, _), TransitError> = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, vec);
    }

    // TODO: How to ensure different types are not deserialized as each other with bincode?
    // #[test]
    // fn test_packet_type() {
    //     let addr1 = "127.0.0.1:62001";
    //     let addr2 = "127.0.0.1:62002";
    //     let transit1: Transit<Another> = Transit::new(addr1).unwrap();
    //     let transit2: Transit<Test> = Transit::new(addr2).unwrap();
    //     let test = Another { data: String::from("Hello") };

    //     let res = transit1.send_to(&test, addr2);
    //     assert!(res.is_ok());
    //     let res = transit2.recv_from();
    //     assert!(res.is_err());
    // }
}
<|endoftext|>


<commit_before>use crate::{Command, Entry, Record};
use chrono::{DateTime, Local, Utc};
use colored::Colorize;
use std::fmt::{self, Write};

/// Configurable display formatting of structures.
///
/// # Examples
/// ```no_run
/// # use undo::{Command, Record};
/// # fn foo() -> Record<String> {
/// let record = Record::default();
/// println!("{}", record.display().colored(false).detailed(false));
/// # record
/// # }
/// ```
#[derive(Copy, Clone, Debug)]
pub struct Display<'a, T: 'static> {
    record: &'a Record<T>,
    format: Format,
}

impl<T> Display<'_, T> {
    /// Show colored output (on by default).
    pub fn colored(&mut self, on: bool) -> &mut Self {
        self.format.colored = on;
        self
    }

    /// Show the current position in the output (on by default).
    pub fn current(&mut self, on: bool) -> &mut Self {
        self.format.current = on;
        self
    }

    /// Show detailed output (on by default).
    pub fn detailed(&mut self, on: bool) -> &mut Self {
        self.format.detailed = on;
        self
    }

    /// Show the position of the command (on by default).
    pub fn position(&mut self, on: bool) -> &mut Self {
        self.format.position = on;
        self
    }

    /// Show the saved command (on by default).
    pub fn saved(&mut self, on: bool) -> &mut Self {
        self.format.saved = on;
        self
    }
}

impl<T> Display<'_, T> {
    fn fmt_list(&self, f: &mut fmt::Formatter, at: usize, entry: Option<&Entry<T>>) -> fmt::Result {
        self.format.position(f, at)?;
        if let Some(entry) = entry {
            if self.format.detailed {
                self.format.timestamp(f, &entry.timestamp)?;
            }
        }
        self.format
            .labels(f, at, self.record.current(), self.record.saved)?;
        if let Some(entry) = entry {
            if self.format.detailed {
                writeln!(f)?;
                self.format.message(f, entry.text())?;
            } else {
                f.write_char(' ')?;
                self.format.message(f, entry.text())?;
                writeln!(f)?;
            }
        }
        Ok(())
    }
}

impl<'a, T> From<&'a Record<T>> for Display<'a, T> {
    fn from(record: &'a Record<T>) -> Self {
        Display {
            record,
            format: Format::default(),
        }
    }
}

impl<T> fmt::Display for Display<'_, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for (i, entry) in self.record.entries.iter().enumerate().rev() {
            self.fmt_list(f, i + 1, Some(entry))?;
        }
        self.fmt_list(f, 0, None)?;
        Ok(())
    }
}

#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
struct Format {
    colored: bool,
    current: bool,
    detailed: bool,
    position: bool,
    saved: bool,
}

impl Default for Format {
    fn default() -> Self {
        Format {
            colored: true,
            current: true,
            detailed: true,
            position: true,
            saved: true,
        }
    }
}

impl Format {
    fn message(self, f: &mut fmt::Formatter, msg: String) -> fmt::Result {
        let lines = msg.lines();
        if self.detailed {
            for line in lines {
                writeln!(f, "{}", line.trim())?;
            }
        } else if let Some(line) = lines.map(str::trim).find(|s| !s.is_empty()) {
            f.write_str(&line)?;
        }
        Ok(())
    }

    fn position(self, f: &mut fmt::Formatter, at: usize) -> fmt::Result {
        if self.position {
            if self.colored {
                write!(f, "{}", format!("{}", at).yellow().bold())
            } else {
                write!(f, "{}", at)
            }
        } else {
            Ok(())
        }
    }

    fn labels(
        self,
        f: &mut fmt::Formatter,
        at: usize,
        current: usize,
        saved: Option<usize>,
    ) -> fmt::Result {
        match (
            self.current && at == current,
            self.saved && saved.map_or(false, |saved| saved == at),
            self.colored,
        ) {
            (true, true, true) => write!(
                f,
                " {}{}{} {}{}",
                "(".yellow(),
                "current".cyan().bold(),
                ",".yellow(),
                "saved".green().bold(),
                ")".yellow()
            ),
            (true, true, false) => f.write_str(" (current, saved)"),
            (true, false, true) => write!(
                f,
                " {}{}{}",
                "(".yellow(),
                "current".cyan().bold(),
                ")".yellow()
            ),
            (true, false, false) => f.write_str(" (current)"),
            (false, true, true) => write!(
                f,
                " {}{}{}",
                "(".yellow(),
                "saved".green().bold(),
                ")".yellow()
            ),
            (false, true, false) => f.write_str(" (saved)"),
            (false, false, _) => Ok(()),
        }
    }

    fn timestamp(self, f: &mut fmt::Formatter, timestamp: &DateTime<Utc>) -> fmt::Result {
        let rfc2822 = timestamp.with_timezone(&Local).to_rfc2822();
        if self.colored {
            write!(f, " {}{}{}", "".yellow(), rfc2822.yellow(), "".yellow())
        } else {
            write!(f, " [{}]", rfc2822)
        }
    }
}
<commit_msg>Fix early return<commit_after>use crate::{Command, Entry, Record};
use chrono::{DateTime, Local, Utc};
use colored::Colorize;
use std::fmt::{self, Write};

/// Configurable display formatting of structures.
///
/// # Examples
/// ```no_run
/// # use undo::{Command, Record};
/// # fn foo() -> Record<String> {
/// let record = Record::default();
/// println!("{}", record.display().colored(false).detailed(false));
/// # record
/// # }
/// ```
#[derive(Copy, Clone, Debug)]
pub struct Display<'a, T: 'static> {
    record: &'a Record<T>,
    format: Format,
}

impl<T> Display<'_, T> {
    /// Show colored output (on by default).
    pub fn colored(&mut self, on: bool) -> &mut Self {
        self.format.colored = on;
        self
    }

    /// Show the current position in the output (on by default).
    pub fn current(&mut self, on: bool) -> &mut Self {
        self.format.current = on;
        self
    }

    /// Show detailed output (on by default).
    pub fn detailed(&mut self, on: bool) -> &mut Self {
        self.format.detailed = on;
        self
    }

    /// Show the position of the command (on by default).
    pub fn position(&mut self, on: bool) -> &mut Self {
        self.format.position = on;
        self
    }

    /// Show the saved command (on by default).
    pub fn saved(&mut self, on: bool) -> &mut Self {
        self.format.saved = on;
        self
    }
}

impl<T> Display<'_, T> {
    fn fmt_list(&self, f: &mut fmt::Formatter, at: usize, entry: Option<&Entry<T>>) -> fmt::Result {
        self.format.position(f, at)?;
        if let Some(entry) = entry {
            if self.format.detailed {
                self.format.timestamp(f, &entry.timestamp)?;
            }
        }
        self.format
            .labels(f, at, self.record.current(), self.record.saved)?;
        if let Some(entry) = entry {
            if self.format.detailed {
                writeln!(f)?;
                self.format.message(f, entry.text())?;
            } else {
                f.write_char(' ')?;
                self.format.message(f, entry.text())?;
                writeln!(f)?;
            }
        }
        Ok(())
    }
}

impl<'a, T> From<&'a Record<T>> for Display<'a, T> {
    fn from(record: &'a Record<T>) -> Self {
        Display {
            record,
            format: Format::default(),
        }
    }
}

impl<T> fmt::Display for Display<'_, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for (i, entry) in self.record.entries.iter().enumerate().rev() {
            self.fmt_list(f, i + 1, Some(entry))?;
        }
        self.fmt_list(f, 0, None)
    }
}

#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
struct Format {
    colored: bool,
    current: bool,
    detailed: bool,
    position: bool,
    saved: bool,
}

impl Default for Format {
    fn default() -> Self {
        Format {
            colored: true,
            current: true,
            detailed: true,
            position: true,
            saved: true,
        }
    }
}

impl Format {
    fn message(self, f: &mut fmt::Formatter, msg: String) -> fmt::Result {
        let lines = msg.lines();
        if self.detailed {
            for line in lines {
                writeln!(f, "{}", line.trim())?;
            }
        } else if let Some(line) = lines.map(str::trim).find(|s| !s.is_empty()) {
            f.write_str(&line)?;
        }
        Ok(())
    }

    fn position(self, f: &mut fmt::Formatter, at: usize) -> fmt::Result {
        if self.position {
            if self.colored {
                write!(f, "{}", format!("{}", at).yellow().bold())
            } else {
                write!(f, "{}", at)
            }
        } else {
            Ok(())
        }
    }

    fn labels(
        self,
        f: &mut fmt::Formatter,
        at: usize,
        current: usize,
        saved: Option<usize>,
    ) -> fmt::Result {
        match (
            self.current && at == current,
            self.saved && saved.map_or(false, |saved| saved == at),
            self.colored,
        ) {
            (true, true, true) => write!(
                f,
                " {}{}{} {}{}",
                "(".yellow(),
                "current".cyan().bold(),
                ",".yellow(),
                "saved".green().bold(),
                ")".yellow()
            ),
            (true, true, false) => f.write_str(" (current, saved)"),
            (true, false, true) => write!(
                f,
                " {}{}{}",
                "(".yellow(),
                "current".cyan().bold(),
                ")".yellow()
            ),
            (true, false, false) => f.write_str(" (current)"),
            (false, true, true) => write!(
                f,
                " {}{}{}",
                "(".yellow(),
                "saved".green().bold(),
                ")".yellow()
            ),
            (false, true, false) => f.write_str(" (saved)"),
            (false, false, _) => Ok(()),
        }
    }

    fn timestamp(self, f: &mut fmt::Formatter, timestamp: &DateTime<Utc>) -> fmt::Result {
        let rfc2822 = timestamp.with_timezone(&Local).to_rfc2822();
        if self.colored {
            write!(f, " {}{}{}", "".yellow(), rfc2822.yellow(), "".yellow())
        } else {
            write!(f, " [{}]", rfc2822)
        }
    }
}
<|endoftext|>


<commit_before>use libc::{c_char, c_uint};
use ffi;
use ffi::{QVariant, QrsVariantType, QVariantList};

pub enum Variant {
    I64(i64),
    Bool(bool),
    String(String),
}

pub trait FromQVariant {
    fn from_qvariant(arg: *const QVariant) -> Option<Self>;
}

impl FromQVariant for i64 {
    fn from_qvariant(var: *const QVariant) -> Option<i64> {
        unsafe {
            if ffi::qmlrs_variant_get_type(var) == QrsVariantType::Int64 {
                let mut x: i64 = 0;
                ffi::qmlrs_variant_get_int64(var, &mut x);
                Some(x)
            } else {
                None
            }
        }
    }
}

impl FromQVariant for bool {
    fn from_qvariant(var: *const QVariant) -> Option<bool> {
        unsafe {
            if ffi::qmlrs_variant_get_type(var) == QrsVariantType::Bool {
                let mut x: bool = false;
                ffi::qmlrs_variant_get_bool(var, &mut x);
                Some(x)
            } else {
                None
            }
        }
    }
}

impl FromQVariant for String {
    fn from_qvariant(var: *const QVariant) -> Option<String> {
        unsafe {
            if ffi::qmlrs_variant_get_type(var) == QrsVariantType::String {
                let mut len: c_uint = 0;
                ffi::qmlrs_variant_get_string_length(var, &mut len);

                let mut data: Vec<u8> = Vec::with_capacity(len as usize);
                ffi::qmlrs_variant_get_string_data(var, data.as_mut_ptr() as *mut c_char);
                data.set_len(len as usize);

                Some(String::from_utf8_unchecked(data))
            } else {
                None
            }
        }
    }
}

impl FromQVariant for Variant {
    fn from_qvariant(var: *const QVariant) -> Option<Variant> {
        use ffi::QrsVariantType::*;
        unsafe {
            match ffi::qmlrs_variant_get_type(var) {
                Int64 =>
                    Some(Variant::I64(FromQVariant::from_qvariant(var).unwrap())),
                Bool =>
                    Some(Variant::Bool(FromQVariant::from_qvariant(var).unwrap())),
                String =>
                    Some(Variant::String(FromQVariant::from_qvariant(var).unwrap())),
                _ => None
            }
        }
    }
}

pub trait ToQVariant {
    fn to_qvariant(&self, var: *mut QVariant);
}

impl ToQVariant for () {
    fn to_qvariant(&self, var: *mut QVariant) {
        unsafe {
            ffi::qmlrs_variant_set_invalid(var);
        }
    }
}

impl ToQVariant for i64 {
    fn to_qvariant(&self, var: *mut QVariant) {
        unsafe {
            ffi::qmlrs_variant_set_int64(var, *self);
        }
    }
}

impl ToQVariant for bool {
    fn to_qvariant(&self, var: *mut QVariant) {
        unsafe {
            ffi::qmlrs_variant_set_bool(var, *self);
        }
    }
}

macro_rules! int_toqvar {
    ($($t:ty)*) => (
        $(
        impl ToQVariant for $t {
            fn to_qvariant(&self, var: *mut QVariant) {
                (*self as i64).to_qvariant(var);
            }
        }
        )*
    )
}

int_toqvar!(u8 u16 u32 i8 i16 i32 isize);

impl ToQVariant for str {
    fn to_qvariant(&self, var: *mut QVariant) {
        unsafe {
            ffi::qmlrs_variant_set_string(var, self.len() as c_uint,
                                          self.as_ptr() as *const c_char);
        }
    }
}

impl ToQVariant for Variant {
    fn to_qvariant(&self, var: *mut QVariant) {
        match *self {
            Variant::I64(ref x) => x.to_qvariant(var),
            Variant::Bool(ref x) => x.to_qvariant(var),
            Variant::String(ref s) => s.to_qvariant(var),
        }
    }
}

pub fn unpack_varlist(p: *const QVariantList) -> Vec<Variant> {
    let mut ret = Vec::new();
    let mut i = 0;
    let len = unsafe { ffi::qmlrs_varlist_length(p) };

    while i < len {
        let x = unsafe { ffi::qmlrs_varlist_get(p,i) };
        if let Some(v) = Variant::from_qvariant(x) {
            ret.push(v)
        }

        i += 1;
    }

    ret
}
<commit_msg>add some traits to Variant<commit_after>use libc::{c_char, c_uint};
use ffi;
use ffi::{QVariant, QrsVariantType, QVariantList};

#[derive(PartialEq,Eq,Clone,Debug)]
pub enum Variant {
    I64(i64),
    Bool(bool),
    String(String),
}

pub trait FromQVariant {
    fn from_qvariant(arg: *const QVariant) -> Option<Self>;
}

impl FromQVariant for i64 {
    fn from_qvariant(var: *const QVariant) -> Option<i64> {
        unsafe {
            if ffi::qmlrs_variant_get_type(var) == QrsVariantType::Int64 {
                let mut x: i64 = 0;
                ffi::qmlrs_variant_get_int64(var, &mut x);
                Some(x)
            } else {
                None
            }
        }
    }
}

impl FromQVariant for bool {
    fn from_qvariant(var: *const QVariant) -> Option<bool> {
        unsafe {
            if ffi::qmlrs_variant_get_type(var) == QrsVariantType::Bool {
                let mut x: bool = false;
                ffi::qmlrs_variant_get_bool(var, &mut x);
                Some(x)
            } else {
                None
            }
        }
    }
}

impl FromQVariant for String {
    fn from_qvariant(var: *const QVariant) -> Option<String> {
        unsafe {
            if ffi::qmlrs_variant_get_type(var) == QrsVariantType::String {
                let mut len: c_uint = 0;
                ffi::qmlrs_variant_get_string_length(var, &mut len);

                let mut data: Vec<u8> = Vec::with_capacity(len as usize);
                ffi::qmlrs_variant_get_string_data(var, data.as_mut_ptr() as *mut c_char);
                data.set_len(len as usize);

                Some(String::from_utf8_unchecked(data))
            } else {
                None
            }
        }
    }
}

impl FromQVariant for Variant {
    fn from_qvariant(var: *const QVariant) -> Option<Variant> {
        use ffi::QrsVariantType::*;
        unsafe {
            match ffi::qmlrs_variant_get_type(var) {
                Int64 =>
                    Some(Variant::I64(FromQVariant::from_qvariant(var).unwrap())),
                Bool =>
                    Some(Variant::Bool(FromQVariant::from_qvariant(var).unwrap())),
                String =>
                    Some(Variant::String(FromQVariant::from_qvariant(var).unwrap())),
                _ => None
            }
        }
    }
}

pub trait ToQVariant {
    fn to_qvariant(&self, var: *mut QVariant);
}

impl ToQVariant for () {
    fn to_qvariant(&self, var: *mut QVariant) {
        unsafe {
            ffi::qmlrs_variant_set_invalid(var);
        }
    }
}

impl ToQVariant for i64 {
    fn to_qvariant(&self, var: *mut QVariant) {
        unsafe {
            ffi::qmlrs_variant_set_int64(var, *self);
        }
    }
}

impl ToQVariant for bool {
    fn to_qvariant(&self, var: *mut QVariant) {
        unsafe {
            ffi::qmlrs_variant_set_bool(var, *self);
        }
    }
}

macro_rules! int_toqvar {
    ($($t:ty)*) => (
        $(
        impl ToQVariant for $t {
            fn to_qvariant(&self, var: *mut QVariant) {
                (*self as i64).to_qvariant(var);
            }
        }
        )*
    )
}

int_toqvar!(u8 u16 u32 i8 i16 i32 isize);

impl ToQVariant for str {
    fn to_qvariant(&self, var: *mut QVariant) {
        unsafe {
            ffi::qmlrs_variant_set_string(var, self.len() as c_uint,
                                          self.as_ptr() as *const c_char);
        }
    }
}

impl ToQVariant for Variant {
    fn to_qvariant(&self, var: *mut QVariant) {
        match *self {
            Variant::I64(ref x) => x.to_qvariant(var),
            Variant::Bool(ref x) => x.to_qvariant(var),
            Variant::String(ref s) => s.to_qvariant(var),
        }
    }
}

pub fn unpack_varlist(p: *const QVariantList) -> Vec<Variant> {
    let mut ret = Vec::new();
    let mut i = 0;
    let len = unsafe { ffi::qmlrs_varlist_length(p) };

    while i < len {
        let x = unsafe { ffi::qmlrs_varlist_get(p,i) };
        if let Some(v) = Variant::from_qvariant(x) {
            ret.push(v)
        }

        i += 1;
    }

    ret
}
<|endoftext|>


<commit_before>use types::{Result, OscType, OscPacket, OscBundle, OscMessage};
use errors::OscError;
use utils;

use byteorder::{ByteOrder, BigEndian};
use std::iter;

pub fn encode_packet(packet: OscPacket) -> Result<Vec<u8>> {
    match packet {
        OscPacket::Message(msg) => encode_message(msg),
        OscPacket::Bundle(bundle) => encode_bundle(bundle),
    }
}

fn encode_message(msg: OscMessage) -> Result<Vec<u8>> {
    let mut msg_bytes: Vec<u8> = Vec::new();

    msg_bytes.extend(encode_string(msg.addr));
    // save address

    if msg.args.is_some() {
        let args: Vec<OscType> = msg.args.unwrap();
        let mut type_tags: Vec<char> = Vec::with_capacity(args.len());
        // Possible optimization: write this as iterator
        for arg in args {
            let (bytes, tag): (Option<Vec<u8>>, char) = try!(encode(arg));

            type_tags.push(tag);
            if bytes.is_some() {
                msg_bytes.extend(bytes.unwrap());
            }
        }
    }

    Ok(msg_bytes)
}

fn encode_bundle(bundle: OscBundle) -> Result<Vec<u8>> {
    Err(OscError::Unimplemented)
}

fn encode(arg: OscType) -> Result<(Option<Vec<u8>>, char)> {
    match arg {
        OscType::Int(x) => {
            let mut bytes = Vec::with_capacity(4);
            BigEndian::write_i32(&mut bytes, x);
            Ok((Some(bytes), 'i'))
        }
        OscType::Long(x) => {
            let mut bytes = Vec::with_capacity(8);
            BigEndian::write_i64(&mut bytes, x);
            Ok((Some(bytes), 'h'))
        }
        OscType::Float(x) => {
            let mut bytes = Vec::with_capacity(4);
            BigEndian::write_f32(&mut bytes, x);
            Ok((Some(bytes), 'f'))
        }
        OscType::Double(x) => {
            let mut bytes = Vec::with_capacity(8);
            BigEndian::write_f64(&mut bytes, x);
            Ok((Some(bytes), 'd'))
        }
        OscType::Char(x) => {
            let mut bytes = Vec::with_capacity(4);
            BigEndian::write_u32(&mut bytes, x as u32);
            Ok((Some(bytes), 'c'))
        }
        OscType::String(x) => {
            Ok((Some(encode_string(x)), 's'))
        }
        OscType::Blob(x) => {
            let mut bytes = x.clone();
            pad_bytes(&mut bytes);
            Ok((Some(bytes), 'b'))
        }
        OscType::Time(x, y) => {
            Ok((Some(encode_time_tag(x, y)), 't'))
        }
        OscType::Midi(x) => {
            Ok((Some(vec![x.port, x.status, x.data1, x.data2]), 'm'))
        }
        OscType::Bool(x) => {
            if x {
                Ok((None, 'T'))
            } else {
                Ok((None, 'F'))
            }
        }
        OscType::Nil => {
            Ok((None, 'N'))
        }
        OscType::Inf => {
            Ok((None, 'I'))
        }
        _ => Err(OscError::Unimplemented),
    }
}

fn encode_string(s: String) -> Vec<u8> {
    let mut bytes: Vec<u8> = s.as_bytes()
                              .iter()
                              .cloned()
                              .chain(iter::once(0u8))
                              .collect();
    pad_bytes(&mut bytes);
    bytes
}

fn pad_bytes(bytes: &mut Vec<u8>) {
    let padded_lengh = utils::pad(bytes.len() as u64);
    while bytes.len() < padded_lengh as usize {
        bytes.push(0u8)
    }
}

fn encode_time_tag(sec: u32, frac: u32) -> Vec<u8> {
    let mut bytes = Vec::with_capacity(8);
    BigEndian::write_u32(&mut bytes[..3], sec);
    BigEndian::write_u32(&mut bytes[4..], frac);
    bytes
}
<commit_msg>Fix message encoding by converting type_tags to an OSC string<commit_after>use types::{Result, OscType, OscPacket, OscBundle, OscMessage};
use errors::OscError;
use utils;

use byteorder::{ByteOrder, BigEndian};
use std::{iter, str};

pub fn encode_packet(packet: OscPacket) -> Result<Vec<u8>> {
    match packet {
        OscPacket::Message(msg) => encode_message(msg),
        OscPacket::Bundle(bundle) => encode_bundle(bundle),
    }
}

fn encode_message(msg: OscMessage) -> Result<Vec<u8>> {
    let mut msg_bytes: Vec<u8> = Vec::new();

    msg_bytes.extend(encode_string(msg.addr));
    let mut type_tags: Vec<char> = vec![','];
    let mut arg_bytes: Vec<u8> = Vec::new();

    if msg.args.is_some() {
        let args: Vec<OscType> = msg.args.unwrap();
        // Possible optimization: write this as iterator
        for arg in args {
            let (bytes, tag): (Option<Vec<u8>>, char) = try!(encode(arg));

            type_tags.push(tag);
            if bytes.is_some() {
                arg_bytes.extend(bytes.unwrap());
            }
        }
    }

    msg_bytes.extend(encode_string(type_tags.iter()
                                            .cloned()
                                            .collect()));
    if arg_bytes.len() > 0 {
        msg_bytes.extend(arg_bytes);
    }
    Ok(msg_bytes)
}

fn encode_bundle(bundle: OscBundle) -> Result<Vec<u8>> {
    Err(OscError::Unimplemented)
}

fn encode(arg: OscType) -> Result<(Option<Vec<u8>>, char)> {
    match arg {
        OscType::Int(x) => {
            let mut bytes = Vec::with_capacity(4);
            BigEndian::write_i32(&mut bytes, x);
            Ok((Some(bytes), 'i'))
        }
        OscType::Long(x) => {
            let mut bytes = Vec::with_capacity(8);
            BigEndian::write_i64(&mut bytes, x);
            Ok((Some(bytes), 'h'))
        }
        OscType::Float(x) => {
            let mut bytes = Vec::with_capacity(4);
            BigEndian::write_f32(&mut bytes, x);
            Ok((Some(bytes), 'f'))
        }
        OscType::Double(x) => {
            let mut bytes = Vec::with_capacity(8);
            BigEndian::write_f64(&mut bytes, x);
            Ok((Some(bytes), 'd'))
        }
        OscType::Char(x) => {
            let mut bytes = Vec::with_capacity(4);
            BigEndian::write_u32(&mut bytes, x as u32);
            Ok((Some(bytes), 'c'))
        }
        OscType::String(x) => {
            Ok((Some(encode_string(x)), 's'))
        }
        OscType::Blob(x) => {
            let mut bytes = x.clone();
            pad_bytes(&mut bytes);
            Ok((Some(bytes), 'b'))
        }
        OscType::Time(x, y) => {
            Ok((Some(encode_time_tag(x, y)), 't'))
        }
        OscType::Midi(x) => {
            Ok((Some(vec![x.port, x.status, x.data1, x.data2]), 'm'))
        }
        OscType::Bool(x) => {
            if x {
                Ok((None, 'T'))
            } else {
                Ok((None, 'F'))
            }
        }
        OscType::Nil => {
            Ok((None, 'N'))
        }
        OscType::Inf => {
            Ok((None, 'I'))
        }
        _ => Err(OscError::Unimplemented),
    }
}

fn encode_string(s: String) -> Vec<u8> {
    let mut bytes: Vec<u8> = s.as_bytes()
                              .iter()
                              .cloned()
                              .chain(iter::once(0u8))
                              .collect();
    pad_bytes(&mut bytes);
    bytes
}

fn pad_bytes(bytes: &mut Vec<u8>) {
    let padded_lengh = utils::pad(bytes.len() as u64);
    while bytes.len() < padded_lengh as usize {
        bytes.push(0u8)
    }
}

fn encode_time_tag(sec: u32, frac: u32) -> Vec<u8> {
    let mut bytes = Vec::with_capacity(8);
    BigEndian::write_u32(&mut bytes[..3], sec);
    BigEndian::write_u32(&mut bytes[4..], frac);
    bytes
}
<|endoftext|>


<commit_before>//! The configuration format for the program container

use typedef::*;

pub const DEFAULT_SCALE: f64 = 4.0;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct DisplayConfig {
    #[serde(default)]
    pub resolution: DisplayResolution,
    pub default_scale: Float,
    #[serde(default)]
    pub hide_cursor: bool,
}

impl Default for DisplayConfig {
    fn default() -> Self {
        DisplayConfig {
            resolution: Default::default(),
            default_scale: DEFAULT_SCALE,
            hide_cursor: true,
        }
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct DisplayResolution {
    pub width: usize,
    pub height: usize,
}

impl Default for DisplayResolution {
    fn default() -> Self {
        DisplayResolution {
            width: 160,
            height: 100,
        }
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Config {
    #[serde(default)]
    pub title: String,
    #[serde(default)]
    pub display: DisplayConfig,
    #[serde(default)]
    pub input_enabled: bool,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            title: "bakerVM".into(),
            display: Default::default(),
            input_enabled: true,
        }
    }
}
<commit_msg>Moved some definitions into constants<commit_after>//! The configuration format for the program container

use typedef::*;

pub const DEFAULT_SCALE: f64 = 4.0;

pub const DEFAULT_SCREEN_WIDTH: usize = 160;
pub const DEFAULT_SCREEN_HEIGHT: usize = 100;

pub const DEFAULT_WINDOW_TITLE: &str = "bakerVM";

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct DisplayConfig {
    #[serde(default)]
    pub resolution: DisplayResolution,
    pub default_scale: Float,
    #[serde(default)]
    pub hide_cursor: bool,
}

impl Default for DisplayConfig {
    fn default() -> Self {
        DisplayConfig {
            resolution: Default::default(),
            default_scale: DEFAULT_SCALE,
            hide_cursor: true,
        }
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct DisplayResolution {
    pub width: usize,
    pub height: usize,
}

impl Default for DisplayResolution {
    fn default() -> Self {
        DisplayResolution {
            width: DEFAULT_SCREEN_WIDTH,
            height: DEFAULT_SCREEN_HEIGHT,
        }
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Config {
    #[serde(default)]
    pub title: String,
    #[serde(default)]
    pub display: DisplayConfig,
    #[serde(default)]
    pub input_enabled: bool,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            title: DEFAULT_WINDOW_TITLE.into(),
            display: Default::default(),
            input_enabled: true,
        }
    }
}
<|endoftext|>


<commit_before>//src: https://rustbyexample.com/primitives/tuples.html

use std::fmt;

// Tuples can be used as function arguments and as return values
fn reverse(pair: (i32, bool)) -> (bool, i32) {
    // `let` can be used to bind the members of a tuple to variables
    let (integer, boolean) = pair;

    (boolean, integer)
}

// The following struct is for the activity.
#[derive(Debug)]
struct Matrix(f32, f32, f32, f32);

impl fmt::Display for Matrix {
  fn fmt(&self, f:&mut fmt::Formatter) -> fmt::Result {
	  // Write strictly the first element into the supplied output
	  // stream: `f`. Returns `fmt::Result` which indicates whether the
	  // operation succeeded or failed. Note that `write!` uses syntax which
	  // is very similar to `println!`.
	  try!(write!(f, "( {} {} )\n", self.0, self.1));
	  write!(f, "( {} {} )", self.2, self.3)//no ; so to return a fmt::Result value
  }
}

fn main() {
    // A tuple with a bunch of different types
    let long_tuple = (1u8, 2u16, 3u32, 4u64,
                      -1i8, -2i16, -3i32, -4i64,
                      0.1f32, 0.2f64,
                      'a', true);

    // Values can be extracted from the tuple using tuple indexing
    println!("long tuple first value: {}", long_tuple.0);
    println!("long tuple second value: {}", long_tuple.1);

    // Tuples can be tuple members
    let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);

    // Tuples are printable
    println!("tuple of tuples: {:?}", tuple_of_tuples);

    let pair = (1, true);
    println!("pair is {:?}", pair);

    println!("the reversed pair is {:?}", reverse(pair));

    // To create one element tuples, the comma is required to tell them apart
    // from a literal surrounded by parentheses
    println!("one element tuple: {:?}", (5u32,));
    println!("just an integer: {:?}", (5u32));

    //tuples can be destructured to create bindings
    let tuple = (1, "hello", 4.5, true);

    let (a, b, c, d) = tuple;
    println!("{:?}, {:?}, {:?}, {:?}", a, b, c, d);

    let matrix = Matrix(1.1, 1.2, 2.1, 2.2);
    println!("{:?}", matrix);
    println!("{}", matrix);

}
<commit_msg>do the transpose activity for 2.2<commit_after>//src: https://rustbyexample.com/primitives/tuples.html

use std::fmt;

// Tuples can be used as function arguments and as return values
fn reverse(pair: (i32, bool)) -> (bool, i32) {
    // `let` can be used to bind the members of a tuple to variables
    let (integer, boolean) = pair;

    (boolean, integer)
}

//this moves
fn transpose(m: Matrix) -> Matrix {
    // `let` can be used to bind the members of a tuple to variables
    let m=Matrix(m.0,m.2,m.1,m.3);

    m
}

//this borrows
fn transpose2(m: &Matrix) -> Matrix {
    // `let` can be used to bind the members of a tuple to variables
    let m=Matrix(m.0,m.2,m.1,m.3);

    m
}

// The following struct is for the activity.
#[derive(Debug)]
struct Matrix(f32, f32, f32, f32);

impl fmt::Display for Matrix {
  fn fmt(&self, f:&mut fmt::Formatter) -> fmt::Result {
	  // Write strictly the first element into the supplied output
	  // stream: `f`. Returns `fmt::Result` which indicates whether the
	  // operation succeeded or failed. Note that `write!` uses syntax which
	  // is very similar to `println!`.
	  try!(write!(f, "( {} {} )\n", self.0, self.1));
	  write!(f, "( {} {} )", self.2, self.3)//no ";" so to return a fmt::Result value
  }
}

fn main() {
    // A tuple with a bunch of different types
    let long_tuple = (1u8, 2u16, 3u32, 4u64,
                      -1i8, -2i16, -3i32, -4i64,
                      0.1f32, 0.2f64,
                      'a', true);

    // Values can be extracted from the tuple using tuple indexing
    println!("long tuple first value: {}", long_tuple.0);
    println!("long tuple second value: {}", long_tuple.1);

    // Tuples can be tuple members
    let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);

    // Tuples are printable
    println!("tuple of tuples: {:?}", tuple_of_tuples);

    let pair = (1, true);
    println!("pair is {:?}", pair);

    println!("the reversed pair is {:?}", reverse(pair));

    // To create one element tuples, the comma is required to tell them apart
    // from a literal surrounded by parentheses
    println!("one element tuple: {:?}", (5u32,));
    println!("just an integer: {:?}", (5u32));

    //tuples can be destructured to create bindings
    let tuple = (1, "hello", 4.5, true);

    let (a, b, c, d) = tuple;
    println!("{:?}, {:?}, {:?}, {:?}", a, b, c, d);

    let matrix = Matrix(1.1, 1.2, 2.1, 2.2);
    println!("{:?}", matrix);
    println!("{}", matrix);

    println!("Matrix:\n{}", matrix);
	println!("Transpose2:\n{}", transpose2(&matrix));//moves!
    println!("Matrix:\n{}", matrix);
	println!("Transpose:\n{}", transpose(matrix));//moves!
    //println!("Matrix:\n{}", matrix);//can't - moved!

}
<|endoftext|>


<commit_before>use std::sync::Arc;

use ctxt::VM;
use gc::{fill_region, Address, Region, K};
use threads::{DoraThread, THREAD};

pub const TLAB_SIZE: usize = 32 * K;
pub const TLAB_OBJECT_SIZE: usize = 8 * K;

pub fn initialize(tlab: Region) {
    THREAD.with(|thread| {
        thread.borrow().tld.tlab_initialize(tlab.start, tlab.end);
    });
}

pub fn calculate_size(additional: usize) -> usize {
    assert!(additional < TLAB_OBJECT_SIZE);

    TLAB_SIZE + additional
}

pub fn allocate(size: usize) -> Option<Address> {
    assert!(size < TLAB_OBJECT_SIZE);

    THREAD.with(|thread| {
        let thread = thread.borrow();
        let tlab = thread.tld.tlab_region();

        if size <= tlab.size() {
            thread
                .tld
                .tlab_initialize(tlab.start.offset(size), tlab.end);
            Some(tlab.start)
        } else {
            None
        }
    })
}

pub fn make_iterable_all(vm: &VM, threads: &[Arc<DoraThread>]) {
    for thread in threads {
        let tlab = thread.tld.tlab_region();
        fill_region(vm, tlab.start, tlab.end);

        let n = Address::null();
        thread.tld.tlab_initialize(n, n);
    }
}

pub fn make_iterable_current(vm: &VM) {
    THREAD.with(|thread| {
        let thread = thread.borrow();
        let tlab = thread.tld.tlab_region();

        fill_region(vm, tlab.start, tlab.end);

        let n = Address::null();
        thread.tld.tlab_initialize(n, n);
    });
}

pub fn make_iterable_region(vm: &VM, start: Address, end: Address) {
    THREAD.with(|thread| {
        let thread = thread.borrow();
        fill_region(vm, start, end);

        let n = Address::null();
        thread.tld.tlab_initialize(n, n);
    });
}
<commit_msg>remove make_iterable_region<commit_after>use std::sync::Arc;

use ctxt::VM;
use gc::{fill_region, Address, Region, K};
use threads::{DoraThread, THREAD};

pub const TLAB_SIZE: usize = 32 * K;
pub const TLAB_OBJECT_SIZE: usize = 8 * K;

pub fn initialize(tlab: Region) {
    THREAD.with(|thread| {
        thread.borrow().tld.tlab_initialize(tlab.start, tlab.end);
    });
}

pub fn calculate_size(additional: usize) -> usize {
    assert!(additional < TLAB_OBJECT_SIZE);

    TLAB_SIZE + additional
}

pub fn allocate(size: usize) -> Option<Address> {
    assert!(size < TLAB_OBJECT_SIZE);

    THREAD.with(|thread| {
        let thread = thread.borrow();
        let tlab = thread.tld.tlab_region();

        if size <= tlab.size() {
            thread
                .tld
                .tlab_initialize(tlab.start.offset(size), tlab.end);
            Some(tlab.start)
        } else {
            None
        }
    })
}

pub fn make_iterable_all(vm: &VM, threads: &[Arc<DoraThread>]) {
    for thread in threads {
        let tlab = thread.tld.tlab_region();
        fill_region(vm, tlab.start, tlab.end);

        let n = Address::null();
        thread.tld.tlab_initialize(n, n);
    }
}

pub fn make_iterable_current(vm: &VM) {
    THREAD.with(|thread| {
        let thread = thread.borrow();
        let tlab = thread.tld.tlab_region();

        fill_region(vm, tlab.start, tlab.end);

        let n = Address::null();
        thread.tld.tlab_initialize(n, n);
    });
}
<|endoftext|>


<commit_before>#[phase(plugin)]
extern crate regex_macros;
extern crate regex;
extern crate "rustc-serialize" as rustc_serialize;
#[phase(plugin, link)] extern crate log;

pub use errors;

use std::io::process::Command;
use utils::say::{say, sayln, spinner};
use errors::{DeliveryError, Kind};
use std::sync::mpsc::channel;
use std::thread::Thread;

pub fn get_head() -> Result<String, DeliveryError> {
    let gitr = try!(git_command(&["branch"]));
    let result = try!(parse_get_head(gitr.stdout.as_slice()));
    Ok(result)
}

fn parse_get_head(stdout: &str) -> Result<String, DeliveryError> {
    for line in stdout.lines_any() {
        let r = regex!(r"(.) (.+)");
        let caps_result = r.captures(line);
        let caps = match caps_result {
            Some(caps) => caps,
            None => { return Err(DeliveryError{ kind: Kind::BadGitOutputMatch, detail: Some(format!("Failed to match: {}", line)) }) }
        };
        let token = caps.at(1).unwrap();
        if token == "*" {
            let branch = caps.at(2).unwrap();
            return Ok(String::from_str(branch));
        }
    }
    return Err(DeliveryError{ kind: Kind::NotOnABranch, detail: None });
}

#[test]
fn test_parse_get_head() {
    let stdout = "  adam/review
  adam/test
  adam/test6
  builder
  first
  foo
  foo2
* master
  snazzy
  testerton";
    let result = parse_get_head(stdout);
    match result {
        Ok(branch) => {
            assert_eq!(branch.as_slice(), "master");
        },
        Err(e) => panic!("No result")
    };
}

pub struct GitResult {
    stdout: String,
    stderr: String
}

fn git_command(args: &[&str]) -> Result<GitResult, DeliveryError> {
    let (tx, rx) = channel::<int>();
    let (tx2, rx2) = channel::<int>();
    let thread_guard = Thread::spawn(move|| { spinner(rx, tx2) });
    let mut command = Command::new("git");
    command.args(args);
    debug!("Git command: {}", command);
    let output = match command.output() {
        Ok(o) => o,
        Err(e) => { let _ = tx.send(1); return Err(DeliveryError{ kind: Kind::FailedToExecute, detail: Some(format!("failed to execute git: {}", e.desc))}) },
    };
    debug!("Git exited: {}", output.status);
    let _ = tx.send(1);
    let _ = rx2.recv();
    let _ = thread_guard.join();
    if !output.status.success() {
        return Err(DeliveryError{ kind: Kind::GitFailed, detail: Some(format!("STDOUT: {}\nSTDERR: {}\n", String::from_utf8_lossy(output.output.as_slice()), String::from_utf8_lossy(output.error.as_slice())))});
    }
    let stdout = String::from_utf8_lossy(output.output.as_slice()).to_string();
    debug!("Git stdout: {}", stdout);
    let stderr = String::from_utf8_lossy(output.error.as_slice()).to_string();
    debug!("Git stderr: {}", stderr);
    Ok(GitResult{ stdout: stdout, stderr: stderr })
}

pub fn git_push(branch: &str, target: &str) -> Result<String, DeliveryError> {
    let gitr = try!(git_command(&[
                     "push", "--porcelain", "--progress", "--verbose", "delivery", format!("{}:_for/{}/{}", branch, target, branch).as_slice()
                     ]));
    let output = try!(parse_git_push_output(gitr.stdout.as_slice(), gitr.stderr.as_slice()));
    for result in output.iter() {
        match result.flag {
            PushResultFlags::SuccessfulFastForward => sayln("green", format!("Updated change: {}", result.reason).as_slice()),
            PushResultFlags::SuccessfulForcedUpdate => sayln("green", format!("Force updated change: {}", result.reason).as_slice()),
            PushResultFlags::SuccessfulDeletedRef => sayln("red", format!("Deleted change: {}", result.reason).as_slice()),
            PushResultFlags::SuccessfulPushedNewRef => sayln("green", format!("Created change: {}", result.reason).as_slice()),
            PushResultFlags::Rejected => sayln("red", format!("Rejected change: {}", result.reason).as_slice()),
            PushResultFlags::UpToDate => sayln("yellow", format!("Nothing added to the existing change").as_slice()),
        }
    }
    Ok(gitr.stdout.to_string())
}

pub enum PushResultFlags {
    SuccessfulFastForward,
    SuccessfulForcedUpdate,
    SuccessfulDeletedRef,
    SuccessfulPushedNewRef,
    Rejected,
    UpToDate,
}

impl Copy for PushResultFlags { }

pub struct PushResult {
    flag: PushResultFlags,
    from: String,
    to: String,
    reason: String
}

pub fn parse_git_push_output(push_output: &str, push_error: &str) -> Result<Vec<PushResult>, DeliveryError> {
    let mut push_results: Vec<PushResult> = Vec::new();
    for line in push_error.lines_any() {
        debug!("error: {}", line);
        if line.starts_with("remote") {
            let r = regex!(r"remote: (.+)");
            let caps_result = r.captures(line);
            match caps_result {
                Some(caps) => sayln("white", format!("{}", caps.at(1).unwrap()).as_slice()),
                None => {}
            }
        }
    }
    for line in push_output.lines_any() {
        debug!("output: {}", line);
        if line.starts_with("To") {
            continue;
        } else if line.starts_with("Done") {
            continue;
        }
        let r = regex!(r"(.)\t(.+):(.+)\t\[(.+)\]");
        let caps_result = r.captures(line);
        let caps = match caps_result {
            Some(caps) => caps,
            None => { return Err(DeliveryError{ kind: Kind::BadGitOutputMatch, detail: Some(format!("Failed to match: {}", line)) }) }
        };
        let result_flag = match caps.at(1).unwrap() {
            " " => PushResultFlags::SuccessfulFastForward,
            "+" => PushResultFlags::SuccessfulForcedUpdate,
            "-" => PushResultFlags::SuccessfulDeletedRef,
            "*" => PushResultFlags::SuccessfulPushedNewRef,
            "!" => PushResultFlags::Rejected,
            "=" => PushResultFlags::UpToDate,
            _ => { return Err(DeliveryError{ kind: Kind::BadGitOutputMatch, detail: Some(format!("Unknown result flag")) }) }
        };
        push_results.push(
            PushResult{
                flag: result_flag,
                from: String::from_str(caps.at(2).unwrap()),
                to: String::from_str(caps.at(3).unwrap()),
                reason: String::from_str(caps.at(4).unwrap())
            }
        )
    }
    Ok(push_results)
}

#[test]
fn test_parse_git_push_output_success() {
    let stdout = "To ssh://adam@127.0.0.1/Users/adam/src/opscode/delivery/opscode/delivery-cli2
=	refs/heads/foo:refs/heads/_for/master/foo	[up to date]
Done";
    let stderr = "Pushing to ssh://adam@Chef@172.31.6.130:8989/Chef/adam_universe/delivery-cli
Total 0 (delta 0), reused 0 (delta 0)
remote: Patchset already up to date, nothing to do
remote: https://172.31.6.130/e/Chef/#/organizations/adam_universe/projects/delivery-cli/changes/146a9573-1bd0-4a27-a106-528347761811
updating local tracking ref 'refs/remotes/origin/_for/master/adam/test6'";
    let result = parse_git_push_output(stdout, stderr);
    match result {
        Ok(pr_vec) => {
            assert_eq!(pr_vec[0].from.as_slice(), "refs/heads/foo");
            assert_eq!(pr_vec[0].to.as_slice(), "refs/heads/_for/master/foo");
            assert_eq!(pr_vec[0].reason.as_slice(), "up to date");
        },
        Err(_) => panic!("No result")
    };
}

pub fn set_config(user: &str, server: &str, ent: &str, org: &str, proj: &str) -> Result<(), DeliveryError> {
    let result = git_command(&["remote", "add", "delivery", format!("ssh://{}@{}@{}:8989/{}/{}/{}", user, ent, server, ent, org, proj).as_slice()]);
    match result {
        Ok(_) => return Ok(()),
        Err(e) => {
            match e.detail {
                Some(msg) => {
                    if msg.contains("remote delivery already exists") {
                        return Err(DeliveryError{ kind: Kind::GitSetupFailed, detail: None });
                    }
                },
                None => {
                    return Err(e)
                }
            }
        },
    }
    Ok(())
}

pub fn checkout_branch_name(change: &str, patchset: &str) -> String {
    if patchset == "latest" {
        return String::from_str(change);
    } else {
        return format!("{}/{}", change, patchset);
    }
}

pub fn diff(change: &str, patchset: &str, pipeline: &str, local: &bool) -> Result<(), DeliveryError> {
    try!(git_command(&["fetch", "delivery"]));
    let mut first_branch = format!("delivery/{}", pipeline);
    if *local {
        first_branch = String::from_str("HEAD");
    }
    let diff = try!(git_command(&["diff", "--color=always", first_branch.as_slice(), format!("delivery/_reviews/{}/{}/{}", pipeline, change, patchset).as_slice()]));
    say("white", "\n");
    sayln("white", diff.stdout.as_slice());
    Ok(())
}

pub fn checkout_review(change: &str, patchset: &str, pipeline: &str) -> Result<(), DeliveryError> {
    try!(git_command(&["fetch", "delivery"]));
    let branchname = checkout_branch_name(change, patchset);
    let result = git_command(&["branch", "--track", branchname.as_slice(), format!("delivery/_reviews/{}/{}/{}", pipeline, change, patchset).as_slice()]);
    match result {
        Ok(_) => {
            try!(git_command(&["checkout", branchname.as_slice()]));
            return Ok(())
        },
        Err(e) => {
            match e.detail {
                Some(msg) => {
                    if msg.contains("already exists.") {
                        try!(git_command(&["checkout", branchname.as_slice()]));
                        sayln("white", "Branch already exists, checking it out.");
                        let r = try!(git_command(&["status"]));
                        sayln("white", r.stdout.as_slice());
                        return Ok(())
                    } else {
                        return Err(DeliveryError{kind: Kind::GitFailed, detail: Some(msg)});
                    }
                },
                None => {
                    return Err(e)
                }
            }
        },
    }
}
<commit_msg>Remove odd test<commit_after>#[phase(plugin)]
extern crate regex_macros;
extern crate regex;
extern crate "rustc-serialize" as rustc_serialize;
#[phase(plugin, link)] extern crate log;

pub use errors;

use std::io::process::Command;
use utils::say::{say, sayln, spinner};
use errors::{DeliveryError, Kind};
use std::sync::mpsc::channel;
use std::thread::Thread;

pub fn get_head() -> Result<String, DeliveryError> {
    let gitr = try!(git_command(&["branch"]));
    let result = try!(parse_get_head(gitr.stdout.as_slice()));
    Ok(result)
}

fn parse_get_head(stdout: &str) -> Result<String, DeliveryError> {
    for line in stdout.lines_any() {
        let r = regex!(r"(.) (.+)");
        let caps_result = r.captures(line);
        let caps = match caps_result {
            Some(caps) => caps,
            None => { return Err(DeliveryError{ kind: Kind::BadGitOutputMatch, detail: Some(format!("Failed to match: {}", line)) }) }
        };
        let token = caps.at(1).unwrap();
        if token == "*" {
            let branch = caps.at(2).unwrap();
            return Ok(String::from_str(branch));
        }
    }
    return Err(DeliveryError{ kind: Kind::NotOnABranch, detail: None });
}

#[test]
fn test_parse_get_head() {
    let stdout = "  adam/review
  adam/test
  adam/test6
  builder
  first
  foo
  foo2
* master
  snazzy
  testerton";
    let result = parse_get_head(stdout);
    match result {
        Ok(branch) => {
            assert_eq!(branch.as_slice(), "master");
        },
        Err(e) => panic!("No result")
    };
}

pub struct GitResult {
    stdout: String,
    stderr: String
}

fn git_command(args: &[&str]) -> Result<GitResult, DeliveryError> {
    let (tx, rx) = channel::<int>();
    let (tx2, rx2) = channel::<int>();
    let thread_guard = Thread::spawn(move|| { spinner(rx, tx2) });
    let mut command = Command::new("git");
    command.args(args);
    debug!("Git command: {}", command);
    let output = match command.output() {
        Ok(o) => o,
        Err(e) => { let _ = tx.send(1); return Err(DeliveryError{ kind: Kind::FailedToExecute, detail: Some(format!("failed to execute git: {}", e.desc))}) },
    };
    debug!("Git exited: {}", output.status);
    let _ = tx.send(1);
    let _ = rx2.recv();
    let _ = thread_guard.join();
    if !output.status.success() {
        return Err(DeliveryError{ kind: Kind::GitFailed, detail: Some(format!("STDOUT: {}\nSTDERR: {}\n", String::from_utf8_lossy(output.output.as_slice()), String::from_utf8_lossy(output.error.as_slice())))});
    }
    let stdout = String::from_utf8_lossy(output.output.as_slice()).to_string();
    debug!("Git stdout: {}", stdout);
    let stderr = String::from_utf8_lossy(output.error.as_slice()).to_string();
    debug!("Git stderr: {}", stderr);
    Ok(GitResult{ stdout: stdout, stderr: stderr })
}

pub fn git_push(branch: &str, target: &str) -> Result<String, DeliveryError> {
    let gitr = try!(git_command(&[
                     "push", "--porcelain", "--progress", "--verbose", "delivery", format!("{}:_for/{}/{}", branch, target, branch).as_slice()
                     ]));
    let output = try!(parse_git_push_output(gitr.stdout.as_slice(), gitr.stderr.as_slice()));
    for result in output.iter() {
        match result.flag {
            PushResultFlags::SuccessfulFastForward => sayln("green", format!("Updated change: {}", result.reason).as_slice()),
            PushResultFlags::SuccessfulForcedUpdate => sayln("green", format!("Force updated change: {}", result.reason).as_slice()),
            PushResultFlags::SuccessfulDeletedRef => sayln("red", format!("Deleted change: {}", result.reason).as_slice()),
            PushResultFlags::SuccessfulPushedNewRef => sayln("green", format!("Created change: {}", result.reason).as_slice()),
            PushResultFlags::Rejected => sayln("red", format!("Rejected change: {}", result.reason).as_slice()),
            PushResultFlags::UpToDate => sayln("yellow", format!("Nothing added to the existing change").as_slice()),
        }
    }
    Ok(gitr.stdout.to_string())
}

pub enum PushResultFlags {
    SuccessfulFastForward,
    SuccessfulForcedUpdate,
    SuccessfulDeletedRef,
    SuccessfulPushedNewRef,
    Rejected,
    UpToDate,
}

impl Copy for PushResultFlags { }

pub struct PushResult {
    flag: PushResultFlags,
    from: String,
    to: String,
    reason: String
}

pub fn parse_git_push_output(push_output: &str, push_error: &str) -> Result<Vec<PushResult>, DeliveryError> {
    let mut push_results: Vec<PushResult> = Vec::new();
    for line in push_error.lines_any() {
        debug!("error: {}", line);
        if line.starts_with("remote") {
            let r = regex!(r"remote: (.+)");
            let caps_result = r.captures(line);
            match caps_result {
                Some(caps) => sayln("white", format!("{}", caps.at(1).unwrap()).as_slice()),
                None => {}
            }
        }
    }
    for line in push_output.lines_any() {
        debug!("output: {}", line);
        if line.starts_with("To") {
            continue;
        } else if line.starts_with("Done") {
            continue;
        }
        let r = regex!(r"(.)\t(.+):(.+)\t\[(.+)\]");
        let caps_result = r.captures(line);
        let caps = match caps_result {
            Some(caps) => caps,
            None => { return Err(DeliveryError{ kind: Kind::BadGitOutputMatch, detail: Some(format!("Failed to match: {}", line)) }) }
        };
        let result_flag = match caps.at(1).unwrap() {
            " " => PushResultFlags::SuccessfulFastForward,
            "+" => PushResultFlags::SuccessfulForcedUpdate,
            "-" => PushResultFlags::SuccessfulDeletedRef,
            "*" => PushResultFlags::SuccessfulPushedNewRef,
            "!" => PushResultFlags::Rejected,
            "=" => PushResultFlags::UpToDate,
            _ => { return Err(DeliveryError{ kind: Kind::BadGitOutputMatch, detail: Some(format!("Unknown result flag")) }) }
        };
        push_results.push(
            PushResult{
                flag: result_flag,
                from: String::from_str(caps.at(2).unwrap()),
                to: String::from_str(caps.at(3).unwrap()),
                reason: String::from_str(caps.at(4).unwrap())
            }
        )
    }
    Ok(push_results)
}

// #[test]
// fn test_parse_git_push_output_success() {
//     let stdout = "To ssh://adam@127.0.0.1/Users/adam/src/opscode/delivery/opscode/delivery-cli2
// =	refs/heads/foo:refs/heads/_for/master/foo	[up to date]
// Done";
//     let stderr = "Pushing to ssh://adam@Chef@172.31.6.130:8989/Chef/adam_universe/delivery-cli
// Total 0 (delta 0), reused 0 (delta 0)
// remote: Patchset already up to date, nothing to do
// remote: https://172.31.6.130/e/Chef/#/organizations/adam_universe/projects/delivery-cli/changes/146a9573-1bd0-4a27-a106-528347761811
// updating local tracking ref 'refs/remotes/origin/_for/master/adam/test6'";
//     let result = parse_git_push_output(stdout, stderr);
//     match result {
//         Ok(pr_vec) => {
//             assert_eq!(pr_vec[0].from.as_slice(), "refs/heads/foo");
//             assert_eq!(pr_vec[0].to.as_slice(), "refs/heads/_for/master/foo");
//             assert_eq!(pr_vec[0].reason.as_slice(), "up to date");
//         },
//         Err(_) => panic!("No result")
//     };
// }

pub fn set_config(user: &str, server: &str, ent: &str, org: &str, proj: &str) -> Result<(), DeliveryError> {
    let result = git_command(&["remote", "add", "delivery", format!("ssh://{}@{}@{}:8989/{}/{}/{}", user, ent, server, ent, org, proj).as_slice()]);
    match result {
        Ok(_) => return Ok(()),
        Err(e) => {
            match e.detail {
                Some(msg) => {
                    if msg.contains("remote delivery already exists") {
                        return Err(DeliveryError{ kind: Kind::GitSetupFailed, detail: None });
                    }
                },
                None => {
                    return Err(e)
                }
            }
        },
    }
    Ok(())
}

pub fn checkout_branch_name(change: &str, patchset: &str) -> String {
    if patchset == "latest" {
        return String::from_str(change);
    } else {
        return format!("{}/{}", change, patchset);
    }
}

pub fn diff(change: &str, patchset: &str, pipeline: &str, local: &bool) -> Result<(), DeliveryError> {
    try!(git_command(&["fetch", "delivery"]));
    let mut first_branch = format!("delivery/{}", pipeline);
    if *local {
        first_branch = String::from_str("HEAD");
    }
    let diff = try!(git_command(&["diff", "--color=always", first_branch.as_slice(), format!("delivery/_reviews/{}/{}/{}", pipeline, change, patchset).as_slice()]));
    say("white", "\n");
    sayln("white", diff.stdout.as_slice());
    Ok(())
}

pub fn checkout_review(change: &str, patchset: &str, pipeline: &str) -> Result<(), DeliveryError> {
    try!(git_command(&["fetch", "delivery"]));
    let branchname = checkout_branch_name(change, patchset);
    let result = git_command(&["branch", "--track", branchname.as_slice(), format!("delivery/_reviews/{}/{}/{}", pipeline, change, patchset).as_slice()]);
    match result {
        Ok(_) => {
            try!(git_command(&["checkout", branchname.as_slice()]));
            return Ok(())
        },
        Err(e) => {
            match e.detail {
                Some(msg) => {
                    if msg.contains("already exists.") {
                        try!(git_command(&["checkout", branchname.as_slice()]));
                        sayln("white", "Branch already exists, checking it out.");
                        let r = try!(git_command(&["status"]));
                        sayln("white", r.stdout.as_slice());
                        return Ok(())
                    } else {
                        return Err(DeliveryError{kind: Kind::GitFailed, detail: Some(msg)});
                    }
                },
                None => {
                    return Err(e)
                }
            }
        },
    }
}
<|endoftext|>


<commit_before>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};

static IP: &'static str  = "127.0.0.1";
static PORT:        int  = 4414;
static mut visitor_count: uint = 0;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {println(format!("Received connection from: [{:s}]", pn.to_str()));},
                                None => ()
                             }
                           },
                None => ()
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);
            println(format!("Received request :\n{:s}", request_str));
            unsafe { atomic_add(&mut visitor_count, 1);
                     println!("Visitor count: {:u}", visitor_count);
            }
            let response: ~str =
                ~"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: "
                    + unsafe{
                        visitor_count.to_str()
                    } + "

                 \r\n";
            stream.write(response.as_bytes());
            println!("Connection terminates.");
        }
    }
}

fn atomic_add(var: &mut uint, count: uint) -> uint {
    let oldval = var.clone();
    *var = *var + count;
    return oldval;
}
<commit_msg>get the first line from the response header<commit_after>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};

static IP: &'static str  = "127.0.0.1";
static PORT:        int  = 4414;
static mut visitor_count: uint = 0;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {println(format!("Received connection from: [{:s}]", pn.to_str()));},
                                None => ()
                             }
                           },
                None => ()
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);
            let lines: ~[&str] = request_str.split('\n').collect();
            println(format!("line one: {:s}", lines[0]));
            println(format!("Received request :\n{:s}", request_str));
            unsafe { atomic_add(&mut visitor_count, 1);
                     println!("Visitor count: {:u}", visitor_count);
            }
            let response: ~str =
                ~"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: "
                    + unsafe{
                        visitor_count.to_str()
                    } + "

                 \r\n";
            stream.write(response.as_bytes());
            println!("Connection terminates.");
        }
    }
}

fn atomic_add(var: &mut uint, count: uint) -> uint {
    let oldval = var.clone();
    *var = *var + count;
    return oldval;
}
<|endoftext|>