<commit_before>use eventual::Async;
use protobuf::{self, Message};
use std::sync::{mpsc, MutexGuard};

use util;
use session::Session;
use util::SpotifyId;
use util::version::version_string;
use mercury::{MercuryRequest, MercuryMethod};

use librespot_protocol as protocol;
pub use librespot_protocol::spirc::PlayStatus;

pub struct SpircManager<'s, D: SpircDelegate> {
    delegate: D,
    session: &'s Session,

    username: String,
    state_update_id: i64,
    seq_nr: u32,

    name: String,
    ident: String,
    device_type: u8,
    can_play: bool,

    repeat: bool,
    shuffle: bool,
    volume: u16,

    is_active: bool,
    became_active_at: i64,

    last_command_ident: String,
    last_command_msgid: u32,

    tracks: Vec<SpotifyId>,
    index: u32
}

pub trait SpircDelegate {
    type State : SpircState;

    fn load(&self, track: SpotifyId,
            start_playing: bool, position_ms: u32);
    fn play(&self);
    fn pause(&self);
    fn seek(&self, position_ms: u32);
    fn stop(&self);

    fn state(&self) -> MutexGuard<Self::State>;
    fn updates(&self) -> mpsc::Receiver<i64>;
}

pub trait SpircState {
    fn status(&self) -> PlayStatus;
    fn position(&self) -> (u32, i64);
    fn update_time(&self) -> i64;
    fn end_of_track(&self) -> bool;
}

impl <'s, D: SpircDelegate> SpircManager<'s, D> {
    pub fn new(session: &'s Session, delegate: D,
               username: String, name: String) -> SpircManager<'s, D> {
        SpircManager {
            delegate: delegate,
            session: &session,

            username: username.clone(),
            state_update_id: 0,
            seq_nr: 0,

            name: name,
            ident: session.0.config.device_id.clone(),
            device_type: 5,
            can_play: true,

            repeat: false,
            shuffle: false,
            volume: 0x8000,

            is_active: false,
            became_active_at: 0,

            last_command_ident: String::new(),
            last_command_msgid: 0,

            tracks: Vec::new(),
            index: 0
        }
    }

    pub fn run(&mut self) {
        let rx = self.session.mercury_sub(format!("hm://remote/user/{}/v23", self.username));
        let updates = self.delegate.updates();

        loop {
            select! {
                pkt = rx.recv() => {
                    let frame = protobuf::parse_from_bytes::<protocol::spirc::Frame>(
                        pkt.unwrap().payload.first().unwrap()).unwrap();

                    println!("{:?} {} {} {} {}",
                             frame.get_typ(),
                             frame.get_device_state().get_name(),
                             frame.get_ident(),
                             frame.get_seq_nr(),
                             frame.get_state_update_id());
                    if frame.get_ident() != self.ident &&
                        (frame.get_recipient().len() == 0 ||
                         frame.get_recipient().contains(&self.ident)) {
                            self.handle(frame);
                        }
                },
                update_time = updates.recv() => {
                    let end_of_track = self.delegate.state().end_of_track();
                    if end_of_track {
                        self.index = (self.index + 1) % self.tracks.len() as u32;
                        let track = self.tracks[self.index as usize];
                        self.delegate.load(track, true, 0);
                    } else {
                        self.state_update_id = update_time.unwrap();
                        self.notify(None);
                    }
                }
            }
        }
    }

    fn handle(&mut self, frame: protocol::spirc::Frame) {
        if frame.get_recipient().len() > 0 {
            self.last_command_ident = frame.get_ident().to_owned();
            self.last_command_msgid = frame.get_seq_nr();
        }
        match frame.get_typ() {
            protocol::spirc::MessageType::kMessageTypeHello => {
                self.notify(Some(frame.get_ident()));
            }
            protocol::spirc::MessageType::kMessageTypeLoad => {
                if !self.is_active {
                    self.is_active = true;
                    self.became_active_at = util::now_ms();
                }

                self.index = frame.get_state().get_playing_track_index();
                self.tracks = frame.get_state().get_track().iter()
                    .map(|track| SpotifyId::from_raw(track.get_gid()))
                    .collect();

                let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
                let track = self.tracks[self.index as usize];
                let position = frame.get_state().get_position_ms();
                self.delegate.load(track, play, position);
            }
            protocol::spirc::MessageType::kMessageTypePlay => {
                self.delegate.play();
            }
            protocol::spirc::MessageType::kMessageTypePause => {
                self.delegate.pause();
            }
            protocol::spirc::MessageType::kMessageTypeSeek => {
                self.delegate.seek(frame.get_position());
            }
            protocol::spirc::MessageType::kMessageTypeNotify => {
                if self.is_active && frame.get_device_state().get_is_active() {
                    self.is_active = false;
                    self.delegate.stop();
                }
            }
            _ => ()
        }
    }

    fn notify(&mut self, recipient: Option<&str>) {
        let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), {
            version: 1,
            ident: self.ident.clone(),
            protocol_version: "2.0.0".to_owned(),
            seq_nr: { self.seq_nr += 1; self.seq_nr  },
            typ: protocol::spirc::MessageType::kMessageTypeNotify,
            device_state: self.device_state(),
            recipient: protobuf::RepeatedField::from_vec(
                recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![])
            ),
            state_update_id: self.state_update_id as i64
        });

        if self.is_active {
            pkt.set_state(self.spirc_state());
        }

        self.session.mercury(MercuryRequest{
            method: MercuryMethod::SEND,
            uri: format!("hm://remote/user/{}", self.username),
            content_type: None,
            payload: vec![ pkt.write_to_bytes().unwrap() ]
        }).await().unwrap();
    }

    fn spirc_state(&self) -> protocol::spirc::State {
        let state = self.delegate.state();
        let (position_ms, position_measured_at) = state.position();

        protobuf_init!(protocol::spirc::State::new(), {
            status: state.status(),
            position_ms: position_ms,
            position_measured_at: position_measured_at as u64,

            playing_track_index: self.index,
            track: self.tracks.iter().map(|track| {
                protobuf_init!(protocol::spirc::TrackRef::new(), {
                    gid: track.to_raw().to_vec()
                })
            }).collect(),

            shuffle: self.shuffle,
            repeat: self.repeat,

            playing_from_fallback: true,

            last_command_ident: self.last_command_ident.clone(),
            last_command_msgid: self.last_command_msgid
        })
    }

    fn device_state(&self) -> protocol::spirc::DeviceState {
        protobuf_init!(protocol::spirc::DeviceState::new(), {
            sw_version: version_string(),
            is_active: self.is_active,
            can_play: self.can_play,
            volume: self.volume as u32,
            name: self.name.clone(),
            error_code: 0,
            became_active_at: if self.is_active { self.became_active_at as i64 } else { 0 },
            capabilities => [
                @{
                    typ: protocol::spirc::CapabilityType::kCanBePlayer,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kDeviceType,
                    intValue => [ self.device_type as i64 ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kGaiaEqConnectId,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportsLogout,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kIsObservable,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kVolumeSteps,
                    intValue => [10]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedContexts,
                    stringValue => [
                        "album".to_owned(),
                        "playlist".to_owned(),
                        "search".to_owned(),
                        "inbox".to_owned(),
                        "toplist".to_owned(),
                        "starred".to_owned(),
                        "publishedstarred".to_owned(),
                        "track".to_owned(),
                    ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedTypes,
                    stringValue => [
                        "audio/local".to_owned(),
                        "audio/track".to_owned(),
                        "local".to_owned(),
                        "track".to_owned(),
                    ]
                }
            ],
        })
    }
}
<commit_msg>Fox subscription URL for spirc.<commit_after>use eventual::Async;
use protobuf::{self, Message};
use std::sync::{mpsc, MutexGuard};

use util;
use session::Session;
use util::SpotifyId;
use util::version::version_string;
use mercury::{MercuryRequest, MercuryMethod};

use librespot_protocol as protocol;
pub use librespot_protocol::spirc::PlayStatus;

pub struct SpircManager<'s, D: SpircDelegate> {
    delegate: D,
    session: &'s Session,

    username: String,
    state_update_id: i64,
    seq_nr: u32,

    name: String,
    ident: String,
    device_type: u8,
    can_play: bool,

    repeat: bool,
    shuffle: bool,
    volume: u16,

    is_active: bool,
    became_active_at: i64,

    last_command_ident: String,
    last_command_msgid: u32,

    tracks: Vec<SpotifyId>,
    index: u32
}

pub trait SpircDelegate {
    type State : SpircState;

    fn load(&self, track: SpotifyId,
            start_playing: bool, position_ms: u32);
    fn play(&self);
    fn pause(&self);
    fn seek(&self, position_ms: u32);
    fn stop(&self);

    fn state(&self) -> MutexGuard<Self::State>;
    fn updates(&self) -> mpsc::Receiver<i64>;
}

pub trait SpircState {
    fn status(&self) -> PlayStatus;
    fn position(&self) -> (u32, i64);
    fn update_time(&self) -> i64;
    fn end_of_track(&self) -> bool;
}

impl <'s, D: SpircDelegate> SpircManager<'s, D> {
    pub fn new(session: &'s Session, delegate: D,
               username: String, name: String) -> SpircManager<'s, D> {
        SpircManager {
            delegate: delegate,
            session: &session,

            username: username.clone(),
            state_update_id: 0,
            seq_nr: 0,

            name: name,
            ident: session.0.config.device_id.clone(),
            device_type: 5,
            can_play: true,

            repeat: false,
            shuffle: false,
            volume: 0x8000,

            is_active: false,
            became_active_at: 0,

            last_command_ident: String::new(),
            last_command_msgid: 0,

            tracks: Vec::new(),
            index: 0
        }
    }

    pub fn run(&mut self) {
        let rx = self.session.mercury_sub(format!("hm://remote/user/{}/", self.username));
        let updates = self.delegate.updates();

        loop {
            select! {
                pkt = rx.recv() => {
                    let frame = protobuf::parse_from_bytes::<protocol::spirc::Frame>(
                        pkt.unwrap().payload.first().unwrap()).unwrap();

                    println!("{:?} {} {} {} {}",
                             frame.get_typ(),
                             frame.get_device_state().get_name(),
                             frame.get_ident(),
                             frame.get_seq_nr(),
                             frame.get_state_update_id());
                    if frame.get_ident() != self.ident &&
                        (frame.get_recipient().len() == 0 ||
                         frame.get_recipient().contains(&self.ident)) {
                            self.handle(frame);
                        }
                },
                update_time = updates.recv() => {
                    let end_of_track = self.delegate.state().end_of_track();
                    if end_of_track {
                        self.index = (self.index + 1) % self.tracks.len() as u32;
                        let track = self.tracks[self.index as usize];
                        self.delegate.load(track, true, 0);
                    } else {
                        self.state_update_id = update_time.unwrap();
                        self.notify(None);
                    }
                }
            }
        }
    }

    fn handle(&mut self, frame: protocol::spirc::Frame) {
        if frame.get_recipient().len() > 0 {
            self.last_command_ident = frame.get_ident().to_owned();
            self.last_command_msgid = frame.get_seq_nr();
        }
        match frame.get_typ() {
            protocol::spirc::MessageType::kMessageTypeHello => {
                self.notify(Some(frame.get_ident()));
            }
            protocol::spirc::MessageType::kMessageTypeLoad => {
                if !self.is_active {
                    self.is_active = true;
                    self.became_active_at = util::now_ms();
                }

                self.index = frame.get_state().get_playing_track_index();
                self.tracks = frame.get_state().get_track().iter()
                    .map(|track| SpotifyId::from_raw(track.get_gid()))
                    .collect();

                let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
                let track = self.tracks[self.index as usize];
                let position = frame.get_state().get_position_ms();
                self.delegate.load(track, play, position);
            }
            protocol::spirc::MessageType::kMessageTypePlay => {
                self.delegate.play();
            }
            protocol::spirc::MessageType::kMessageTypePause => {
                self.delegate.pause();
            }
            protocol::spirc::MessageType::kMessageTypeSeek => {
                self.delegate.seek(frame.get_position());
            }
            protocol::spirc::MessageType::kMessageTypeNotify => {
                if self.is_active && frame.get_device_state().get_is_active() {
                    self.is_active = false;
                    self.delegate.stop();
                }
            }
            _ => ()
        }
    }

    fn notify(&mut self, recipient: Option<&str>) {
        let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), {
            version: 1,
            ident: self.ident.clone(),
            protocol_version: "2.0.0".to_owned(),
            seq_nr: { self.seq_nr += 1; self.seq_nr  },
            typ: protocol::spirc::MessageType::kMessageTypeNotify,
            device_state: self.device_state(),
            recipient: protobuf::RepeatedField::from_vec(
                recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![])
            ),
            state_update_id: self.state_update_id as i64
        });

        if self.is_active {
            pkt.set_state(self.spirc_state());
        }

        self.session.mercury(MercuryRequest{
            method: MercuryMethod::SEND,
            uri: format!("hm://remote/user/{}", self.username),
            content_type: None,
            payload: vec![ pkt.write_to_bytes().unwrap() ]
        }).await().unwrap();
    }

    fn spirc_state(&self) -> protocol::spirc::State {
        let state = self.delegate.state();
        let (position_ms, position_measured_at) = state.position();

        protobuf_init!(protocol::spirc::State::new(), {
            status: state.status(),
            position_ms: position_ms,
            position_measured_at: position_measured_at as u64,

            playing_track_index: self.index,
            track: self.tracks.iter().map(|track| {
                protobuf_init!(protocol::spirc::TrackRef::new(), {
                    gid: track.to_raw().to_vec()
                })
            }).collect(),

            shuffle: self.shuffle,
            repeat: self.repeat,

            playing_from_fallback: true,

            last_command_ident: self.last_command_ident.clone(),
            last_command_msgid: self.last_command_msgid
        })
    }

    fn device_state(&self) -> protocol::spirc::DeviceState {
        protobuf_init!(protocol::spirc::DeviceState::new(), {
            sw_version: version_string(),
            is_active: self.is_active,
            can_play: self.can_play,
            volume: self.volume as u32,
            name: self.name.clone(),
            error_code: 0,
            became_active_at: if self.is_active { self.became_active_at as i64 } else { 0 },
            capabilities => [
                @{
                    typ: protocol::spirc::CapabilityType::kCanBePlayer,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kDeviceType,
                    intValue => [ self.device_type as i64 ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kGaiaEqConnectId,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportsLogout,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kIsObservable,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kVolumeSteps,
                    intValue => [10]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedContexts,
                    stringValue => [
                        "album".to_owned(),
                        "playlist".to_owned(),
                        "search".to_owned(),
                        "inbox".to_owned(),
                        "toplist".to_owned(),
                        "starred".to_owned(),
                        "publishedstarred".to_owned(),
                        "track".to_owned(),
                    ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedTypes,
                    stringValue => [
                        "audio/local".to_owned(),
                        "audio/track".to_owned(),
                        "local".to_owned(),
                        "track".to_owned(),
                    ]
                }
            ],
        })
    }
}
<|endoftext|>


<commit_before>use nom;
use nom::{Err, IResult};

use metadata;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};
use utility::{ErrorKind, ByteStream, ReadStream, StreamProducer};

use std::io;
use std::fs::File;

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

pub struct Stream {
  info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
  state: ParserState,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      let consumed = Move::Consume(0);

      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        consumer_state: ConsumerState::Continue(consumed),
      }
    }
  )
);

impl Stream {
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
    }
  }

  pub fn info(&self) -> StreamInfo {
    self.info
  }

  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut reader   = ReadStream::new(file);
      let mut is_error = false;
      let mut stream   = Stream {
        info: StreamInfo::new(),
        metadata: Vec::new(),
        frames: Vec::new(),
        state: ParserState::Marker,
      };

      loop {
        match stream.handle(&mut reader) {
          Ok(_)                         => break,
          Err(ErrorKind::EndOfInput)    => break,
          Err(ErrorKind::Consumed(_))   => continue,
          Err(ErrorKind::Incomplete(_)) => continue,
          Err(_)                        => {
            is_error = true;

            break;
          }
        }
      }

      if !is_error {
        Ok(stream)
      } else {
        let error_str = format!("parser: couldn't parse the given file {}",
                                filename);

        Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
      }
    })
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata_parser(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  pub fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                                   -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}
<commit_msg>Remove `consumer_state` from chain parser<commit_after>use nom;
use nom::{Err, IResult};

use metadata;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};
use utility::{ErrorKind, ByteStream, ReadStream, StreamProducer};

use std::io;
use std::fs::File;

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

pub struct Stream {
  info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
  state: ParserState,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
      }
    }
  )
);

impl Stream {
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
    }
  }

  pub fn info(&self) -> StreamInfo {
    self.info
  }

  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut reader   = ReadStream::new(file);
      let mut is_error = false;
      let mut stream   = Stream {
        info: StreamInfo::new(),
        metadata: Vec::new(),
        frames: Vec::new(),
        state: ParserState::Marker,
      };

      loop {
        match stream.handle(&mut reader) {
          Ok(_)                         => break,
          Err(ErrorKind::EndOfInput)    => break,
          Err(ErrorKind::Consumed(_))   => continue,
          Err(ErrorKind::Incomplete(_)) => continue,
          Err(_)                        => {
            is_error = true;

            break;
          }
        }
      }

      if !is_error {
        Ok(stream)
      } else {
        let error_str = format!("parser: couldn't parse the given file {}",
                                filename);

        Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
      }
    })
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata_parser(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  pub fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                                   -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}
<|endoftext|>


<commit_before>

use std::ops::Deref;
use std::fmt::{self, Display, Debug, Formatter};

use itertools::PutBack;

pub type CharType = u8;

#[derive(Debug, Copy, Clone)]
pub struct StreamPosition {
    idx: usize,
}

const SP_DEFAULT: StreamPosition = StreamPosition { idx: 0 };

impl From<usize> for StreamPosition {
    fn from(idx: usize) -> Self {
        StreamPosition { idx: idx }
    }
}

#[derive(Copy, Clone)]
pub struct Char(StreamPosition, CharType);

impl Debug for Char {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Char({}, {})", self.0.idx, self.1 as char)
    }
}

impl Deref for Char {
    type Target = CharType;

    fn deref(&self) -> &Self::Target {
        &self.1
    }
}

impl<I, P> From<(P, I)> for Char
    where P: Into<StreamPosition>,
          I: Into<CharType>
{
    fn from(src: (P, I)) -> Self {
        use std::ascii::AsciiExt;
        let c = src.1.into();
        assert!(c.is_ascii(), "'Char's must be ASCII: `{}`", c);
        Char(src.0.into(), c)
    }
}

impl From<char> for Char {
    fn from(c: char) -> Self {
        (SP_DEFAULT, c as CharType).into()
    }
}

impl From<CharType> for Char {
    fn from(c: CharType) -> Self {
        Char::from(c as char)
    }
}

impl Display for Char {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.1 as char)
    }
}

pub type CharStream<I> = PutBack<I>;
<commit_msg>Delete old stream module<commit_after><|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::grammar::{Elem, ElemTypes, Prod, ProdElement};
use std::collections::{BTreeMap, BTreeSet};

/// A state of a production within a parse state.
///
/// A production state keeps track of a particular production, the nonterminal
/// to which the production belongs, and an index into the production, which is
/// the current location of the parse state. For example:
///
/// ```text
/// A => a <b> . c
/// ```
///
/// This indicates that the head is A, the production is a <b> c, and the
/// current location is just before the final c.
#[derive(Derivative)]
#[derivative(
  Clone(bound = ""),
  PartialEq(bound = ""),
  Eq(bound = ""),
  PartialOrd(bound = ""),
  Ord(bound = ""),
  Debug(bound = "")
)]

pub struct ProdState<'a, E: ElemTypes> {
  /// The production this state is part of.
  prod: Prod<'a, E>,

  /// The index of this production state. Must be in the range [0,
  /// self.prod.prod_elements().len()].
  index: usize,
}

impl<'a, E: ElemTypes> ProdState<'a, E> {
  /// Create a ProdState from a given NonTerminal and Prod.
  ///
  /// This state's index will be at the start of the production.
  pub fn from_start(prod: Prod<'a, E>) -> Self {
    ProdState { prod, index: 0 }
  }

  pub fn prod(&self) -> Prod<'a, E> {
    self.prod
  }

  pub fn offset_prod_elem(&self, i: usize) -> Option<&'a ProdElement<E>> {
    self.prod.prod_elements().get(self.index + i)
  }

  pub fn offset_elem(&self, i: usize) -> Option<&'a Elem<E>> {
    self.offset_prod_elem(i).map(ProdElement::elem)
  }

  pub fn next_prod_elem(&self) -> Option<&'a ProdElement<E>> {
    self.offset_prod_elem(0)
  }

  pub fn next_elem(&self) -> Option<&'a Elem<E>> {
    self.offset_elem(0)
  }

  /// Returns the next element after the current index. If it is at the
  /// end, then it reuturns `None`.
  pub fn next_elem_state(
    &self,
  ) -> Option<(&'a ProdElement<E>, ProdState<'a, E>)> {
    self.next_prod_elem().map(|prod_elem| {
      (
        prod_elem,
        ProdState {
          prod: self.prod,
          index: self.index + 1,
        },
      )
    })
  }

  /// Return Some(state) which is this state advanced if
  /// the next element type is elem.
  pub fn advance_if(&self, elem: &Elem<E>) -> Option<ProdState<'a, E>> {
    self
      .next_elem_state()
      .filter(|(e, _)| e.elem() == elem)
      .map(|(_, next)| next)
  }

  pub fn is_complete(&self) -> bool {
    self.prod.len() == self.index
  }

  pub fn action_key(&self) -> &'a E::ActionKey {
    self.prod.action_key()
  }
}

/// A set of production states.
#[derive(Derivative)]
#[derivative(
  Clone(bound = ""),
  PartialEq(bound = ""),
  Eq(bound = ""),
  PartialOrd(bound = ""),
  Ord(bound = ""),
  Debug(bound = "")
)]
pub struct ProdStateSet<'a, E: ElemTypes> {
  states: BTreeSet<ProdState<'a, E>>,
}

impl<'a, E: ElemTypes> ProdStateSet<'a, E> {
  pub fn new_empty() -> Self {
    ProdStateSet {
      states: BTreeSet::new(),
    }
  }

  pub fn add(&mut self, state: ProdState<'a, E>) {
    self.states.insert(state);
  }

  pub fn from_iter<I>(iter: I) -> Self
  where
    I: Iterator<Item = ProdState<'a, E>>,
  {
    ProdStateSet {
      states: iter.collect(),
    }
  }

  /// Returns an iterator of pairs of production elements, and the states that are entered after
  /// that.
  pub fn nexts(
    &self,
  ) -> impl Iterator<Item = (&'a ProdElement<E>, ProdStateSet<'a, E>)> {
    let mut result = BTreeMap::new();

    for (k, v) in self.states.iter().filter_map(ProdState::next_elem_state) {
      result
        .entry(k)
        .or_insert_with(|| ProdStateSet::new_empty())
        .add(v);
    }

    result.into_iter()
  }

  /// Given a function that takes the closure of a given prod state, take the closure of all states in this set.
  pub fn take_closure<F, I>(&mut self, mut close_func: F)
  where
    F: FnMut(&ProdState<'a, E>) -> I,
    I: Iterator<Item = ProdState<'a, E>>,
  {
    let mut seen_states = self.states.clone();
    let mut curr_states = self.states.clone();
    let mut next_states = BTreeSet::new();
    loop {
      for state in curr_states.iter() {
        for new_state in close_func(&state) {
          if seen_states.insert(new_state.clone()) {
            next_states.insert(new_state);
          }
        }
      }

      if next_states.is_empty() {
        self.states = seen_states;
        return;
      }

      curr_states = next_states;
      next_states = BTreeSet::new();
    }
  }

  /// Returns an iterator over those states that are complete.
  pub fn complete(&self) -> impl Iterator<Item = ProdState<'a, E>> {
    self
      .states
      .iter()
      .filter(|st| st.is_complete())
      .cloned()
      .collect::<Vec<_>>()
      .into_iter()
  }
}
<commit_msg>Fix a bug after deleting a function<commit_after>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::grammar::{Elem, ElemTypes, Prod, ProdElement};
use std::collections::{BTreeMap, BTreeSet};

/// A state of a production within a parse state.
///
/// A production state keeps track of a particular production, the nonterminal
/// to which the production belongs, and an index into the production, which is
/// the current location of the parse state. For example:
///
/// ```text
/// A => a <b> . c
/// ```
///
/// This indicates that the head is A, the production is a <b> c, and the
/// current location is just before the final c.
#[derive(Derivative)]
#[derivative(
  Clone(bound = ""),
  PartialEq(bound = ""),
  Eq(bound = ""),
  PartialOrd(bound = ""),
  Ord(bound = ""),
  Debug(bound = "")
)]

pub struct ProdState<'a, E: ElemTypes> {
  /// The production this state is part of.
  prod: Prod<'a, E>,

  /// The index of this production state. Must be in the range [0,
  /// self.prod.prod_elements().len()].
  index: usize,
}

impl<'a, E: ElemTypes> ProdState<'a, E> {
  /// Create a ProdState from a given NonTerminal and Prod.
  ///
  /// This state's index will be at the start of the production.
  pub fn from_start(prod: Prod<'a, E>) -> Self {
    ProdState { prod, index: 0 }
  }

  pub fn prod(&self) -> Prod<'a, E> {
    self.prod
  }

  pub fn offset_prod_elem(&self, i: usize) -> Option<&'a ProdElement<E>> {
    self.prod.prod_elements().get(self.index + i)
  }

  pub fn offset_elem(&self, i: usize) -> Option<&'a Elem<E>> {
    self.offset_prod_elem(i).map(ProdElement::elem)
  }

  pub fn next_prod_elem(&self) -> Option<&'a ProdElement<E>> {
    self.offset_prod_elem(0)
  }

  pub fn next_elem(&self) -> Option<&'a Elem<E>> {
    self.offset_elem(0)
  }

  /// Returns the next element after the current index. If it is at the
  /// end, then it reuturns `None`.
  pub fn next_elem_state(
    &self,
  ) -> Option<(&'a ProdElement<E>, ProdState<'a, E>)> {
    self.next_prod_elem().map(|prod_elem| {
      (
        prod_elem,
        ProdState {
          prod: self.prod,
          index: self.index + 1,
        },
      )
    })
  }

  /// Return Some(state) which is this state advanced if
  /// the next element type is elem.
  pub fn advance_if(&self, elem: &Elem<E>) -> Option<ProdState<'a, E>> {
    self
      .next_elem_state()
      .filter(|(e, _)| e.elem() == elem)
      .map(|(_, next)| next)
  }

  pub fn is_complete(&self) -> bool {
    self.prod.num_elements() == self.index
  }

  pub fn action_key(&self) -> &'a E::ActionKey {
    self.prod.action_key()
  }
}

/// A set of production states.
#[derive(Derivative)]
#[derivative(
  Clone(bound = ""),
  PartialEq(bound = ""),
  Eq(bound = ""),
  PartialOrd(bound = ""),
  Ord(bound = ""),
  Debug(bound = "")
)]
pub struct ProdStateSet<'a, E: ElemTypes> {
  states: BTreeSet<ProdState<'a, E>>,
}

impl<'a, E: ElemTypes> ProdStateSet<'a, E> {
  pub fn new_empty() -> Self {
    ProdStateSet {
      states: BTreeSet::new(),
    }
  }

  pub fn add(&mut self, state: ProdState<'a, E>) {
    self.states.insert(state);
  }

  pub fn from_iter<I>(iter: I) -> Self
  where
    I: Iterator<Item = ProdState<'a, E>>,
  {
    ProdStateSet {
      states: iter.collect(),
    }
  }

  /// Returns an iterator of pairs of production elements, and the states that are entered after
  /// that.
  pub fn nexts(
    &self,
  ) -> impl Iterator<Item = (&'a ProdElement<E>, ProdStateSet<'a, E>)> {
    let mut result = BTreeMap::new();

    for (k, v) in self.states.iter().filter_map(ProdState::next_elem_state) {
      result
        .entry(k)
        .or_insert_with(|| ProdStateSet::new_empty())
        .add(v);
    }

    result.into_iter()
  }

  /// Given a function that takes the closure of a given prod state, take the closure of all states in this set.
  pub fn take_closure<F, I>(&mut self, mut close_func: F)
  where
    F: FnMut(&ProdState<'a, E>) -> I,
    I: Iterator<Item = ProdState<'a, E>>,
  {
    let mut seen_states = self.states.clone();
    let mut curr_states = self.states.clone();
    let mut next_states = BTreeSet::new();
    loop {
      for state in curr_states.iter() {
        for new_state in close_func(&state) {
          if seen_states.insert(new_state.clone()) {
            next_states.insert(new_state);
          }
        }
      }

      if next_states.is_empty() {
        self.states = seen_states;
        return;
      }

      curr_states = next_states;
      next_states = BTreeSet::new();
    }
  }

  /// Returns an iterator over those states that are complete.
  pub fn complete(&self) -> impl Iterator<Item = ProdState<'a, E>> {
    self
      .states
      .iter()
      .filter(|st| st.is_complete())
      .cloned()
      .collect::<Vec<_>>()
      .into_iter()
  }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![allow(dead_code)]
#![plugin(bitfield)]
#[cfg(test)]

extern crate core;
extern crate byteorder;
#[macro_use]
extern crate bitflags;

use std::net::UdpSocket;
use std::io::Cursor;
use std::io::Read;

use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian, BigEndian};

bitflags! {
    flags PacketType: u8 {
        const VersionNegotiation = 0x01,
        const ClientCleartext = 0x02,
        const NonFinalCleartext = 0x03,
        const FinalServerClearText = 0x04,
        const RTT0Encrypted = 0x05,
        const RTT1EncryptedPhase0 = 0x06,
        const RTT1EncryptedPhase1 = 0x07,
        const PublicReset = 0x08,
    }
}

bitflags! {
    flags ShortPacketType: u8 {
        const OneByte = 0x01,
        const TwoBytes = 0x02,
        const FourBytes = 0x03,
    }
}

//#[repr(u8)]
//#[derive(Debug, PartialEq)]
//pub enum PacketType {
//    VersionNegotiation = 0x01,
//    ClientCleartext = 0x02,
//    NonFinalCleartext = 0x03,
//    FinalServerClearText = 0x04,
//    RTT0Encrypted = 0x05,
//    RTT1EncryptedPhase0 = 0x06,
//    RTT1EncryptedPhase1 = 0x07,
//    PublicReset = 0x08,
//}

#[derive(Debug)]
pub enum PacketNumber {
    OneByte(u8),
    TwoBytes(u16),
    FourBytes(u32),
}

#[derive(Debug)]
pub struct ShortHeader {
    key_phase_bit: bool,
    connection_id: Option<u64>,
    packet_number: PacketNumber,
}

#[derive(Debug)]
pub struct LongHeader {
    packet_type: PacketType,
    connection_id: u64,
    packet_number: u32,
    version: u32,
}

enum QuicHeader {
    Short(ShortHeader),
    Long(LongHeader),
}

pub struct QuicPacket {
    header: QuicHeader,
    payload: Vec<u8>,
}

enum ErrorType {
    BadPacket
}

impl QuicPacket {
    fn from_bytes(buf: Vec<u8>) -> Result<QuicPacket, String> {
        let mut reader = Cursor::new(buf);
        let first_byte = reader.read_uint::<BigEndian>(1).expect("Packet is empty") as u8;

        if first_byte & 0x80 != 0 { // Long Header
            let packet_type = first_byte & 0x7f;
            let connection_id = reader.read_u64::<BigEndian>().expect("Connection ID not present");
            let packet_number = reader.read_u32::<BigEndian>().expect("Packet number not present");
            let version = reader.read_u32::<BigEndian>().expect("Version not present");

            let mut payload = Vec::new();
            let _ = reader.read_to_end(&mut payload);

            return Ok(QuicPacket {
                header: QuicHeader::Long(LongHeader {
                    packet_type: PacketType::from_bits(packet_type).expect("Invalid Packet Type"),
                    connection_id: connection_id,
                    packet_number: packet_number,
                    version: version,
                }),
                payload: payload
            })
        } else { // ShortHeader
            let conn_id_flag = first_byte & 0x40 != 0;
            let key_phase_bit = first_byte & 0x20 != 0;
            let packet_type = first_byte & 0x1f;

            let mut connection_id: Option<u64> = None;

            if conn_id_flag {
                connection_id = Some(reader.read_u64::<BigEndian>().expect("Connection ID not present"));
            }

            let packet_number_size = match ShortPacketType::from_bits(packet_type).expect("Invalid Packet Type") {
                OneByte => Some(1),
                TwoBytes => Some(2),
                FourBytes => Some(4),
                _ => return Err("Invalid Packet Type".to_string())
            };

            let mut packet_number: PacketNumber;

            packet_number = match packet_number_size {
                Some(1) => PacketNumber::OneByte(reader.read_uint::<BigEndian>(1).expect("Packet number is empty") as u8),
                Some(2) => PacketNumber::TwoBytes(reader.read_uint::<BigEndian>(2).expect("Packet number is empty") as u16),
                Some(4) => PacketNumber::FourBytes(reader.read_uint::<BigEndian>(4).expect("Packet number is empty") as u32),
                _ => return Err("Invalid Packet Type".to_string()),
            };

            let mut payload = Vec::new();
            let _ = reader.read_to_end(&mut payload);

            return Ok(QuicPacket {
                header: QuicHeader::Short(ShortHeader {
                    key_phase_bit: key_phase_bit,
                    connection_id: connection_id,
                    packet_number: packet_number
                }),
                payload: payload
            })
        }
    }

    fn as_bytes(&self) -> Vec<u8> {
        vec![0, 0]
    }
}

pub struct QuicClient {
    pub socket: std::net::UdpSocket,
    current_packet_number: u32,
    address: String
}

impl QuicClient {
    pub fn new(address: &str, port: u16) -> QuicClient {
        let address = format!("{}:{}", address, port);
        let udp_socket = UdpSocket::bind("0.0.0.0:0").expect("couldn't bind to address");

        let mut client = QuicClient {
            socket: udp_socket,
            current_packet_number: 0,
            address: address,
        };

        let init_header = LongHeader {
            packet_type: VersionNegotiation,
            connection_id: 1,
            packet_number: 1,
            version: 1,
        };

        let payload = String::from("The FitnessGram Pacer Test is a multistage aerobic capacity test that progressively gets more difficult as it continues. The 20 meter pacer test will begin in 30 seconds. Line up at the start. The running speed starts slowly but gets faster each minute after you hear this signal bodeboop. A sing lap should be completed every time you hear this sound. ding Remember to run in a straight line and run as long as possible. The second time you fail to complete a lap before the sound, your test is over. The test will begin on the word start. On your mark. Get ready!… Start.");

//        let packet_data = [&chlo_packet_header.as_bytes(), payload.as_bytes()].concat();

//        let _ = client.socket.send_to(packet_data.as_slice(), &client.address);

//        client.current_packet_number += 1;

        client
    }

    pub fn get<'a>(&self, url: &str) -> Vec<u8> {
        String::from(url).into_bytes()
    }
}

mod tests {
    #[test]
    fn creates_new_socket() {
        let _ = QuicClient::new("localhost", 443);
    }

    #[test]
    fn get_url() {
        let client = QuicClient::new("google.com", 443);
        assert_eq!(client.get("hello"), vec![0x01, 0x02]);
    }
}
<commit_msg>update tests<commit_after>#![feature(plugin)]
#![allow(dead_code)]
#![plugin(bitfield)]
#[cfg(test)]

extern crate core;
extern crate byteorder;
#[macro_use]
extern crate bitflags;

use std::net::UdpSocket;
use std::io::Cursor;
use std::io::Read;

use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian, BigEndian};

bitflags! {
    flags PacketType: u8 {
        const VersionNegotiation = 0x01,
        const ClientCleartext = 0x02,
        const NonFinalCleartext = 0x03,
        const FinalServerClearText = 0x04,
        const RTT0Encrypted = 0x05,
        const RTT1EncryptedPhase0 = 0x06,
        const RTT1EncryptedPhase1 = 0x07,
        const PublicReset = 0x08,
    }
}

bitflags! {
    flags ShortPacketType: u8 {
        const OneByte = 0x01,
        const TwoBytes = 0x02,
        const FourBytes = 0x03,
    }
}

//#[repr(u8)]
//#[derive(Debug, PartialEq)]
//pub enum PacketType {
//    VersionNegotiation = 0x01,
//    ClientCleartext = 0x02,
//    NonFinalCleartext = 0x03,
//    FinalServerClearText = 0x04,
//    RTT0Encrypted = 0x05,
//    RTT1EncryptedPhase0 = 0x06,
//    RTT1EncryptedPhase1 = 0x07,
//    PublicReset = 0x08,
//}

#[derive(Debug)]
pub enum PacketNumber {
    OneByte(u8),
    TwoBytes(u16),
    FourBytes(u32),
}

#[derive(Debug)]
pub struct ShortHeader {
    key_phase_bit: bool,
    connection_id: Option<u64>,
    packet_number: PacketNumber,
}

#[derive(Debug)]
pub struct LongHeader {
    packet_type: PacketType,
    connection_id: u64,
    packet_number: u32,
    version: u32,
}

enum QuicHeader {
    Short(ShortHeader),
    Long(LongHeader),
}

pub struct QuicPacket {
    header: QuicHeader,
    payload: Vec<u8>,
}

enum ErrorType {
    BadPacket
}

impl QuicPacket {
    fn from_bytes(buf: Vec<u8>) -> Result<QuicPacket, String> {
        let mut reader = Cursor::new(buf);
        let first_byte = reader.read_uint::<BigEndian>(1).expect("Packet is empty") as u8;

        if first_byte & 0x80 != 0 { // Long Header
            let packet_type = first_byte & 0x7f;
            let connection_id = reader.read_u64::<BigEndian>().expect("Connection ID not present");
            let packet_number = reader.read_u32::<BigEndian>().expect("Packet number not present");
            let version = reader.read_u32::<BigEndian>().expect("Version not present");

            let mut payload = Vec::new();
            let _ = reader.read_to_end(&mut payload);

            return Ok(QuicPacket {
                header: QuicHeader::Long(LongHeader {
                    packet_type: PacketType::from_bits(packet_type).expect("Invalid Packet Type"),
                    connection_id: connection_id,
                    packet_number: packet_number,
                    version: version,
                }),
                payload: payload
            })
        } else { // ShortHeader
            let conn_id_flag = first_byte & 0x40 != 0;
            let key_phase_bit = first_byte & 0x20 != 0;
            let packet_type = first_byte & 0x1f;

            let mut connection_id: Option<u64> = None;

            if conn_id_flag {
                connection_id = Some(reader.read_u64::<BigEndian>().expect("Connection ID not present"));
            }

            let packet_number_size = match ShortPacketType::from_bits(packet_type).expect("Invalid Packet Type") {
                OneByte => Some(1),
                TwoBytes => Some(2),
                FourBytes => Some(4),
                _ => return Err("Invalid Packet Type".to_string())
            };

            let mut packet_number: PacketNumber;

            packet_number = match packet_number_size {
                Some(1) => PacketNumber::OneByte(reader.read_uint::<BigEndian>(1).expect("Packet number is empty") as u8),
                Some(2) => PacketNumber::TwoBytes(reader.read_uint::<BigEndian>(2).expect("Packet number is empty") as u16),
                Some(4) => PacketNumber::FourBytes(reader.read_uint::<BigEndian>(4).expect("Packet number is empty") as u32),
                _ => return Err("Invalid Packet Type".to_string()),
            };

            let mut payload = Vec::new();
            let _ = reader.read_to_end(&mut payload);

            return Ok(QuicPacket {
                header: QuicHeader::Short(ShortHeader {
                    key_phase_bit: key_phase_bit,
                    connection_id: connection_id,
                    packet_number: packet_number
                }),
                payload: payload
            })
        }
    }

    fn as_bytes(&self) -> Vec<u8> {
        vec![0, 0]
    }
}

pub struct QuicClient {
    pub socket: std::net::UdpSocket,
    current_packet_number: u32,
    address: String
}

impl QuicClient {
    pub fn new(address: &str, port: u16) -> QuicClient {
        let address = format!("{}:{}", address, port);
        let udp_socket = UdpSocket::bind("0.0.0.0:0").expect("couldn't bind to address");

        let mut client = QuicClient {
            socket: udp_socket,
            current_packet_number: 0,
            address: address,
        };

        let init_header = LongHeader {
            packet_type: VersionNegotiation,
            connection_id: 1,
            packet_number: 1,
            version: 1,
        };

        let payload = String::from("The FitnessGram Pacer Test is a multistage aerobic capacity test that progressively gets more difficult as it continues. The 20 meter pacer test will begin in 30 seconds. Line up at the start. The running speed starts slowly but gets faster each minute after you hear this signal bodeboop. A sing lap should be completed every time you hear this sound. ding Remember to run in a straight line and run as long as possible. The second time you fail to complete a lap before the sound, your test is over. The test will begin on the word start. On your mark. Get ready!… Start.");

//        let packet_data = [&chlo_packet_header.as_bytes(), payload.as_bytes()].concat();

//        let _ = client.socket.send_to(packet_data.as_slice(), &client.address);

//        client.current_packet_number += 1;

        client
    }

    pub fn get<'a>(&self, url: &str) -> Vec<u8> {
        String::from(url).into_bytes()
    }
}

mod tests {
    #[test]
    fn creates_new_socket() {
        let _ = super::QuicClient::new("localhost", 443);
    }

    #[test]
    fn get_url() {
        let client = super::QuicClient::new("google.com", 443);
        assert_eq!(client.get("hello"), String::from("hello").into_bytes());
    }
}
<|endoftext|>


<commit_before>//! Helpers for writing Alfred XML output
//!
//! # Example
//!
//! ```
//! extern crate alfred;
//!
//! use std::io;
//!
//! fn write_items() -> io::IoResult<()> {
//!     let mut xmlw = try!(alfred::XMLWriter::new(io::stdout()));
//!
//!     let item1 = alfred::Item::new("Item 1");
//!     let item2 = alfred::Item {
//!         subtitle: Some("Subtitle".into_maybe_owned()),
//!         ..alfred::Item::new("Item 2")
//!     };
//!     let item3 = alfred::Item {
//!         arg: Some("Argument".into_maybe_owned()),
//!         subtitle: Some("Subtitle".into_maybe_owned()),
//!         icon: Some(alfred::FileType("public.folder".into_maybe_owned())),
//!         ..alfred::Item::new("Item 3")
//!     };
//!
//!     try!(xmlw.write_item(&item1));
//!     try!(xmlw.write_item(&item2));
//!     try!(xmlw.write_item(&item3));
//!
//!     xmlw.close()
//! }
//!
//! fn main() {
//!     match write_items() {
//!         Ok(()) => {},
//!         Err(err) => {
//!             let _ = writeln!(io::stderr(), "Error writing items: {}", err);
//!         }
//!     }
//! }
//! ```

#![feature(if_let)]
#![warn(missing_doc)]

use std::io;
use std::io::BufferedWriter;
use std::str;

/// Representation of an `<item>`
#[deriving(PartialEq,Eq,Clone)]
pub struct Item<'a> {
    /// Identifier for the results. If given, must be unique among items, and is used for
    /// prioritizing feedback results based on usage. If blank, Alfred uses a UUID and does
    /// not learn from the results.
    pub uid: Option<str::MaybeOwned<'a>>,
    /// The value that is passed to the next portion of the workflow when this item
    /// is selected.
    pub arg: Option<str::MaybeOwned<'a>>,
    /// What type of result this is, if any.
    pub type_: Option<ItemType>,
    /// Whether or not the result item is 'valid'. If `false`, `autocomplete` may be used.
    pub valid: bool,
    /// Autocomplete data for valid=false items. When this item is selected, the autocomplete
    /// value is inserted into the Alfred window.
    pub autocomplete: Option<str::MaybeOwned<'a>>,

    /// Title for the item
    pub title: str::MaybeOwned<'a>,
    /// Subtitle for the item
    pub subtitle: Option<str::MaybeOwned<'a>>,
    /// Icon for the item
    pub icon: Option<Icon<'a>>
}

impl<'a> Item<'a> {
    /// Returns a new Item with the given title
    pub fn new<S: str::IntoMaybeOwned<'a>>(title: S) -> Item<'a> {
        Item {
            uid: None,
            arg: None,
            type_: None,
            valid: true,
            autocomplete: None,
            title: title.into_maybe_owned(),
            subtitle: None,
            icon: None
        }
    }
}

/// Item icons
#[deriving(PartialEq,Eq,Clone)]
pub enum Icon<'a> {
    /// Path to an image file on disk relative to the workflow directory
    PathIcon(str::MaybeOwned<'a>),
    /// Path to a file whose icon will be used
    FileIcon(str::MaybeOwned<'a>),
    /// UTI for a file type to use (e.g. public.folder)
    FileType(str::MaybeOwned<'a>)
}

/// Item types
#[deriving(PartialEq,Eq,Clone)]
pub enum ItemType {
    /// Type representing a file
    FileItemType
}

/// Helper struct used to manage the XML serialization of `Item`s
///
/// When the `XMLWriter` is first created, the XML header is immediately
/// written. When the `XMLWriter` is dropped, the XML footer is written.
///
/// Any errors produced by writing the footer are silently ignored. The
/// `close()` method can be used to return any such error.
pub struct XMLWriter<'a, W: Writer + 'a> {
    w: W,
    last_err: Option<io::IoError>
}

impl<'a, W: Writer + 'a> XMLWriter<'a, W> {
    /// Returns a new `XMLWriter` that writes to the given `Writer`
    ///
    /// The XML header is written immediately.
    pub fn new(mut w: W) -> io::IoResult<XMLWriter<'a, W>> {
        match w.write_str("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<items>\n") {
            Ok(()) => {
                Ok(XMLWriter {
                    w: w,
                    last_err: None
                })
            }
            Err(err) => Err(err)
        }
    }

    /// Writes an `Item` to the underlying `Writer`
    ///
    /// If a previous write produced an error, any subsequent write will do
    /// nothing and return the same error. This is because the previous write
    /// may have partially completed, and attempting to write any more data
    /// will be unlikely to work properly.
    pub fn write_item(&mut self, item: &Item) -> io::IoResult<()> {
        if let Some(ref err) = self.last_err {
            return Err(err.clone());
        }
        let result = item.write_xml(&mut self.w, 1);
        if let Err(ref err) = result {
            self.last_err = Some(err.clone());
        }
        result
    }

    /// Consumes the `XMLWriter` and writes the XML footer
    ///
    /// This method can be used to get any error resulting from writing the
    /// footer. If this method is not used, the footer will be written when the
    /// `XMLWriter` is dropped and any error will be silently ignored.
    ///
    /// As with `write_item()`, if a previous invocation of `write_item()`
    /// returned an error, `close()` will return the same error without
    /// attempting to write the XML footer.
    pub fn close(mut self) -> io::IoResult<()> {
        if let Some(err) = self.last_err {
            return Err(err);
        }
        self.w.write_str("</items>\n")
    }
}

/// Writes a complete XML document representing the `Item`s to the `Writer`
pub fn write_items<W: Writer>(w: W, items: &[Item]) -> io::IoResult<()> {
    let mut xmlw = try!(XMLWriter::new(w));
    for item in items.iter() {
        try!(xmlw.write_item(item));
    }
    xmlw.close()
}

impl<'a> Item<'a> {
    /// Writes the XML fragment representing the `Item` to the `Writer`
    ///
    /// `XMLWriter` should be used instead if at all possible, in order to
    /// write the XML header/footer and maintain proper error discipline.
    pub fn write_xml(&self, w: &mut io::Writer, indent: uint) -> io::IoResult<()> {
        fn write_indent(w: &mut io::Writer, indent: uint) -> io::IoResult<()> {
            for _ in range(0, indent) {
                try!(w.write_str("    "));
            }
            Ok(())
        }

        let mut w = BufferedWriter::with_capacity(512, w);

        try!(write_indent(&mut w, indent));
        try!(w.write_str("<item"));
        match self.uid {
            None => (),
            Some(ref uid) => {
                try!(write!(&mut w, r#" uid="{}""#, encode_entities(uid.as_slice())));
            }
        }
        match self.arg {
            None => (),
            Some(ref arg) => {
                try!(write!(&mut w, r#" arg="{}""#, encode_entities(arg.as_slice())));
            }
        }
        match self.type_ {
            None => (),
            Some(FileItemType) => {
                try!(w.write_str(r#" type="file""#));
            }
        }
        try!(write!(&mut w, r#" valid="{}""#, if self.valid { "yes" } else { "no" }));
        match self.autocomplete {
            None => (),
            Some(ref auto) => {
                try!(write!(&mut w, r#" autocomplete="{}""#, encode_entities(auto.as_slice())));
            }
        }
        try!(w.write_str(">\n"));

        try!(write_indent(&mut w, indent+1));
        try!(write!(&mut w, "<title>{}</title>\n", encode_entities(self.title.as_slice())));

        match self.subtitle {
            None => (),
            Some(ref s) => {
                try!(write_indent(&mut w, indent+1));
                try!(write!(&mut w, "<subtitle>{}</subtitle>\n", encode_entities(s.as_slice())));
            }
        }

        match self.icon {
            None => (),
            Some(ref icon) => {
                try!(write_indent(&mut w, indent+1));
                match *icon {
                    PathIcon(ref s) => {
                        try!(write!(&mut w, "<icon>{}</icon>\n", encode_entities(s.as_slice())));
                    }
                    FileIcon(ref s) => {
                        try!(write!(&mut w, "<icon type=\"fileicon\">{}</icon>\n",
                                      encode_entities(s.as_slice())));
                    }
                    FileType(ref s) => {
                        try!(write!(&mut w, "<icon type=\"filetype\">{}</icon>\n",
                                      encode_entities(s.as_slice())));
                    }
                }
            }
        }

        try!(write_indent(&mut w, indent));
        try!(w.write_str("</item>\n"));

        try!(w.flush());
        Ok(())
    }
}

fn encode_entities<'a>(s: &'a str) -> str::MaybeOwned<'a> {
    fn encode_entity(c: char) -> Option<&'static str> {
        Some(match c {
            '<' => "<",
            '>' => ">",
            '"' => """,
            '&' => "&",
            '\0'...'\x08' |
            '\x0B'...'\x0C' |
            '\x0E'...'\x1F' |
            '\uFFFE' | '\uFFFF' => {
                // these are all invalid characters in XML
                "\uFFFD"
            }
            _ => return None
        })
    }

    if s.chars().any(|c| encode_entity(c).is_some()) {
        let mut res = String::with_capacity(s.len());
        for c in s.chars() {
            match encode_entity(c) {
                Some(ent) => res.push_str(ent),
                None => res.push(c)
            }
        }
        str::Owned(res)
    } else {
        str::Slice(s)
    }
}
<commit_msg>Implement Drop on XMLWriter<commit_after>//! Helpers for writing Alfred XML output
//!
//! # Example
//!
//! ```
//! extern crate alfred;
//!
//! use std::io;
//!
//! fn write_items() -> io::IoResult<()> {
//!     let mut xmlw = try!(alfred::XMLWriter::new(io::stdout()));
//!
//!     let item1 = alfred::Item::new("Item 1");
//!     let item2 = alfred::Item {
//!         subtitle: Some("Subtitle".into_maybe_owned()),
//!         ..alfred::Item::new("Item 2")
//!     };
//!     let item3 = alfred::Item {
//!         arg: Some("Argument".into_maybe_owned()),
//!         subtitle: Some("Subtitle".into_maybe_owned()),
//!         icon: Some(alfred::FileType("public.folder".into_maybe_owned())),
//!         ..alfred::Item::new("Item 3")
//!     };
//!
//!     try!(xmlw.write_item(&item1));
//!     try!(xmlw.write_item(&item2));
//!     try!(xmlw.write_item(&item3));
//!
//!     let mut stdout = try!(xmlw.close());
//!     stdout.flush()
//! }
//!
//! fn main() {
//!     match write_items() {
//!         Ok(()) => {},
//!         Err(err) => {
//!             let _ = writeln!(io::stderr(), "Error writing items: {}", err);
//!         }
//!     }
//! }
//! ```

#![feature(if_let, unsafe_destructor)]
#![warn(missing_doc)]

use std::io;
use std::io::BufferedWriter;
use std::mem;
use std::str;

/// Representation of an `<item>`
#[deriving(PartialEq,Eq,Clone)]
pub struct Item<'a> {
    /// Identifier for the results. If given, must be unique among items, and is used for
    /// prioritizing feedback results based on usage. If blank, Alfred uses a UUID and does
    /// not learn from the results.
    pub uid: Option<str::MaybeOwned<'a>>,
    /// The value that is passed to the next portion of the workflow when this item
    /// is selected.
    pub arg: Option<str::MaybeOwned<'a>>,
    /// What type of result this is, if any.
    pub type_: Option<ItemType>,
    /// Whether or not the result item is 'valid'. If `false`, `autocomplete` may be used.
    pub valid: bool,
    /// Autocomplete data for valid=false items. When this item is selected, the autocomplete
    /// value is inserted into the Alfred window.
    pub autocomplete: Option<str::MaybeOwned<'a>>,

    /// Title for the item
    pub title: str::MaybeOwned<'a>,
    /// Subtitle for the item
    pub subtitle: Option<str::MaybeOwned<'a>>,
    /// Icon for the item
    pub icon: Option<Icon<'a>>
}

impl<'a> Item<'a> {
    /// Returns a new Item with the given title
    pub fn new<S: str::IntoMaybeOwned<'a>>(title: S) -> Item<'a> {
        Item {
            uid: None,
            arg: None,
            type_: None,
            valid: true,
            autocomplete: None,
            title: title.into_maybe_owned(),
            subtitle: None,
            icon: None
        }
    }
}

/// Item icons
#[deriving(PartialEq,Eq,Clone)]
pub enum Icon<'a> {
    /// Path to an image file on disk relative to the workflow directory
    PathIcon(str::MaybeOwned<'a>),
    /// Path to a file whose icon will be used
    FileIcon(str::MaybeOwned<'a>),
    /// UTI for a file type to use (e.g. public.folder)
    FileType(str::MaybeOwned<'a>)
}

/// Item types
#[deriving(PartialEq,Eq,Clone)]
pub enum ItemType {
    /// Type representing a file
    FileItemType
}

/// Helper struct used to manage the XML serialization of `Item`s
///
/// When the `XMLWriter` is first created, the XML header is immediately
/// written. When the `XMLWriter` is dropped, the XML footer is written
/// and the `Writer` is flushed.
///
/// Any errors produced by writing the footer are silently ignored. The
/// `close()` method can be used to return any such error.
pub struct XMLWriter<'a, W: Writer + 'a> {
    // Option so close() can remove it
    // Otherwise this must alwyas be Some()
    w: Option<W>,
    last_err: Option<io::IoError>
}

impl<'a, W: Writer + 'a> XMLWriter<'a, W> {
    /// Returns a new `XMLWriter` that writes to the given `Writer`
    ///
    /// The XML header is written immediately.
    pub fn new(mut w: W) -> io::IoResult<XMLWriter<'a, W>> {
        match w.write_str("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<items>\n") {
            Ok(()) => {
                Ok(XMLWriter {
                    w: Some(w),
                    last_err: None
                })
            }
            Err(err) => Err(err)
        }
    }

    /// Writes an `Item` to the underlying `Writer`
    ///
    /// If a previous write produced an error, any subsequent write will do
    /// nothing and return the same error. This is because the previous write
    /// may have partially completed, and attempting to write any more data
    /// will be unlikely to work properly.
    pub fn write_item(&mut self, item: &Item) -> io::IoResult<()> {
        if let Some(ref err) = self.last_err {
            return Err(err.clone());
        }
        let result = item.write_xml(self.w.as_mut().unwrap(), 1);
        if let Err(ref err) = result {
            self.last_err = Some(err.clone());
        }
        result
    }

    /// Consumes the `XMLWriter` and writes the XML footer
    ///
    /// This method can be used to get any error resulting from writing the
    /// footer. If this method is not used, the footer will be written when the
    /// `XMLWriter` is dropped and any error will be silently ignored.
    ///
    /// As with `write_item()`, if a previous invocation of `write_item()`
    /// returned an error, `close()` will return the same error without
    /// attempting to write the XML footer.
    ///
    /// When this method is used, the XML footer is written, but the `Writer`
    /// is not flushed. When the `XMLWriter` is dropped without calling
    /// `close()`, the `Writer` is flushed after the footer is written.
    pub fn close(mut self) -> io::IoResult<W> {
        let last_err = self.last_err.take();
        let mut w = self.w.take().unwrap();
        unsafe { mem::forget(self); }
        if let Some(err) = last_err {
            return Err(err);
        }
        try!(write_footer(&mut w));
        Ok(w)
    }
}

fn write_footer<'a, W: Writer + 'a>(w: &'a mut W) -> io::IoResult<()> {
    w.write_str("</items>\n")
}

#[unsafe_destructor]
impl<'a, W: Writer + 'a> Drop for XMLWriter<'a, W> {
    fn drop(&mut self) {
        if self.last_err.is_some() {
            return;
        }
        let mut w = self.w.take().unwrap();
        if write_footer(&mut w).is_ok() {
            let _ = w.flush();
        }
    }
}

/// Writes a complete XML document representing the `Item`s to the `Writer`
///
/// The `Writer` is flushed after the XML document is written.
pub fn write_items<W: Writer>(w: W, items: &[Item]) -> io::IoResult<()> {
    let mut xmlw = try!(XMLWriter::new(w));
    for item in items.iter() {
        try!(xmlw.write_item(item));
    }
    let mut w = try!(xmlw.close());
    w.flush()
}

impl<'a> Item<'a> {
    /// Writes the XML fragment representing the `Item` to the `Writer`
    ///
    /// `XMLWriter` should be used instead if at all possible, in order to
    /// write the XML header/footer and maintain proper error discipline.
    pub fn write_xml(&self, w: &mut io::Writer, indent: uint) -> io::IoResult<()> {
        fn write_indent(w: &mut io::Writer, indent: uint) -> io::IoResult<()> {
            for _ in range(0, indent) {
                try!(w.write_str("    "));
            }
            Ok(())
        }

        let mut w = BufferedWriter::with_capacity(512, w);

        try!(write_indent(&mut w, indent));
        try!(w.write_str("<item"));
        match self.uid {
            None => (),
            Some(ref uid) => {
                try!(write!(&mut w, r#" uid="{}""#, encode_entities(uid.as_slice())));
            }
        }
        match self.arg {
            None => (),
            Some(ref arg) => {
                try!(write!(&mut w, r#" arg="{}""#, encode_entities(arg.as_slice())));
            }
        }
        match self.type_ {
            None => (),
            Some(FileItemType) => {
                try!(w.write_str(r#" type="file""#));
            }
        }
        try!(write!(&mut w, r#" valid="{}""#, if self.valid { "yes" } else { "no" }));
        match self.autocomplete {
            None => (),
            Some(ref auto) => {
                try!(write!(&mut w, r#" autocomplete="{}""#, encode_entities(auto.as_slice())));
            }
        }
        try!(w.write_str(">\n"));

        try!(write_indent(&mut w, indent+1));
        try!(write!(&mut w, "<title>{}</title>\n", encode_entities(self.title.as_slice())));

        match self.subtitle {
            None => (),
            Some(ref s) => {
                try!(write_indent(&mut w, indent+1));
                try!(write!(&mut w, "<subtitle>{}</subtitle>\n", encode_entities(s.as_slice())));
            }
        }

        match self.icon {
            None => (),
            Some(ref icon) => {
                try!(write_indent(&mut w, indent+1));
                match *icon {
                    PathIcon(ref s) => {
                        try!(write!(&mut w, "<icon>{}</icon>\n", encode_entities(s.as_slice())));
                    }
                    FileIcon(ref s) => {
                        try!(write!(&mut w, "<icon type=\"fileicon\">{}</icon>\n",
                                      encode_entities(s.as_slice())));
                    }
                    FileType(ref s) => {
                        try!(write!(&mut w, "<icon type=\"filetype\">{}</icon>\n",
                                      encode_entities(s.as_slice())));
                    }
                }
            }
        }

        try!(write_indent(&mut w, indent));
        try!(w.write_str("</item>\n"));

        try!(w.flush());
        Ok(())
    }
}

fn encode_entities<'a>(s: &'a str) -> str::MaybeOwned<'a> {
    fn encode_entity(c: char) -> Option<&'static str> {
        Some(match c {
            '<' => "<",
            '>' => ">",
            '"' => """,
            '&' => "&",
            '\0'...'\x08' |
            '\x0B'...'\x0C' |
            '\x0E'...'\x1F' |
            '\uFFFE' | '\uFFFF' => {
                // these are all invalid characters in XML
                "\uFFFD"
            }
            _ => return None
        })
    }

    if s.chars().any(|c| encode_entity(c).is_some()) {
        let mut res = String::with_capacity(s.len());
        for c in s.chars() {
            match encode_entity(c) {
                Some(ent) => res.push_str(ent),
                None => res.push(c)
            }
        }
        str::Owned(res)
    } else {
        str::Slice(s)
    }
}
<|endoftext|>