<commit_before>//! Contains implementations of FBX parsers.

use std::io::Read;
use crate::reader::error::{Result, Error, ErrorKind};
use crate::reader::{FbxEvent, ParserConfig};
use crate::common::FbxFormatType;
use self::binary::BinaryParser;
use self::ascii::AsciiParser;

mod macros;
mod ascii;
mod binary;

/// Parser state, with sub parser if necessary.
#[derive(Debug, Clone)]
enum ParserState {
    /// Reading magic binary (i.e. the first line).
    Magic,
    /// Reading binary FBX.
    Binary(BinaryParser),
    /// Reading ASCII FBX.
    Ascii(AsciiParser),
}

/// Common state among all sub parsers.
#[derive(Debug, Clone)]
pub(crate) struct CommonState {
    /// Position of last successfully read byte.
    pos: u64,
    final_result: Option<Result<FbxEvent>>,
}

/// A simple wrapper around magic, binary and ascii FBX parser.
pub struct Parser {
    config: ParserConfig,
    common: CommonState,
    state: ParserState,
}

impl Parser {
    /// Constructs a parser.
    pub fn new(config: ParserConfig) -> Self {
        Parser {
            config: config,
            common: CommonState {
                pos: 0,
                final_result: None,
            },
            state: ParserState::Magic,
        }
    }

    /// Get next `FbxEvent`.
    pub fn next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        // If parsing has been finished, return the last result.
        if let Some(ref result) = self.common.final_result {
            return result.clone();
        }
        let result;
        loop {
            // Parsing is not finished, call sub parser.
            let r = match self.state {
                ParserState::Magic => self.magic_next(reader),
                ParserState::Binary(ref mut parser) => parser.next(reader, &mut self.common),
                ParserState::Ascii(ref mut parser) => parser.next(reader, &mut self.common),
            };
            // Break only when `ignore_comments` option is disabled or got non-comment event.
            if self.config.ignore_comments {
                match r {
                    Ok(FbxEvent::Comment(_)) => {},
                    r => {
                        result = r;
                        break;
                    }
                }
            } else {
                result = r;
                break;
            }
        }
        // If parsing is finished, set `final_result`.
        match result {
            Ok(FbxEvent::EndFbx) | Err(_) => {
                self.common.final_result = Some(result.clone());
            },
            _ => {}
        }
        result
    }

    /// Read magic binary and update parser state if success.
    fn magic_next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        // 20 is the length of `b"Kaydara FBX Binary  "`.
        let mut first_line_bytes = Vec::with_capacity(20);
        // First, read the first line.
        // Read the first line manually.
        let magic_end_byte;
        loop {
            let c = try_read_le_u8!(self.common.pos, reader);
            if (c == 0) || (c == ('\n' as u8)) {
                magic_end_byte = c;
                break;
            }
            first_line_bytes.push(c);
        }
        // In Binary FBX, magic binary is `"Kaydara FBX Binary  "`,
        // and in ASCII FBX, there is no magic and it should be treated as normal line.
        if magic_end_byte == 0 {
            // Binary FBX?
            if first_line_bytes == b"Kaydara FBX Binary  " {
                // Binary FBX!
                // "unknown but all observed files show these bytes",
                // see https://code.blender.org/2013/08/fbx-binary-file-format-specification/ .
                {
                    let bytes = try_read_exact!(self.common.pos, reader, 2);
                    if bytes != vec![0x1A, 0x00] {
                        warn!("expected [0x1A, 0x00] right after magic, but got {:?}", bytes);
                    }
                }
                // Read FBX version.
                let version = try_read_le_u32!(self.common.pos, reader);
                debug!("magic binary read, Binary FBX (version={})", version);
                self.state = ParserState::Binary(BinaryParser::new(version));
                Ok(FbxEvent::StartFbx(FbxFormatType::Binary(version)))
            } else {
                Err(Error::new(self.common.pos, ErrorKind::InvalidMagic))
            }
        } else {
            assert_eq!(magic_end_byte, ('\n' as u8));
            // Maybe ASCII FBX
            let mut buffer;
            if first_line_bytes[0] != (';' as u8) {
                // The line is not comment, so the parser should remember it to use next time.
                buffer = try_with_pos!(self.common.pos, String::from_utf8(first_line_bytes));
                buffer.push('\n');
            } else {
                buffer = String::new();
            }
            self.state = ParserState::Ascii(AsciiParser::new(buffer));
            Ok(FbxEvent::StartFbx(FbxFormatType::Ascii))
        }
    }
}
<commit_msg>Prevent `mod macros` to be reordered<commit_after>//! Contains implementations of FBX parsers.

use std::io::Read;
use crate::reader::error::{Result, Error, ErrorKind};
use crate::reader::{FbxEvent, ParserConfig};
use crate::common::FbxFormatType;
use self::binary::BinaryParser;
use self::ascii::AsciiParser;

mod macros;

mod ascii;
mod binary;

/// Parser state, with sub parser if necessary.
#[derive(Debug, Clone)]
enum ParserState {
    /// Reading magic binary (i.e. the first line).
    Magic,
    /// Reading binary FBX.
    Binary(BinaryParser),
    /// Reading ASCII FBX.
    Ascii(AsciiParser),
}

/// Common state among all sub parsers.
#[derive(Debug, Clone)]
pub(crate) struct CommonState {
    /// Position of last successfully read byte.
    pos: u64,
    final_result: Option<Result<FbxEvent>>,
}

/// A simple wrapper around magic, binary and ascii FBX parser.
pub struct Parser {
    config: ParserConfig,
    common: CommonState,
    state: ParserState,
}

impl Parser {
    /// Constructs a parser.
    pub fn new(config: ParserConfig) -> Self {
        Parser {
            config: config,
            common: CommonState {
                pos: 0,
                final_result: None,
            },
            state: ParserState::Magic,
        }
    }

    /// Get next `FbxEvent`.
    pub fn next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        // If parsing has been finished, return the last result.
        if let Some(ref result) = self.common.final_result {
            return result.clone();
        }
        let result;
        loop {
            // Parsing is not finished, call sub parser.
            let r = match self.state {
                ParserState::Magic => self.magic_next(reader),
                ParserState::Binary(ref mut parser) => parser.next(reader, &mut self.common),
                ParserState::Ascii(ref mut parser) => parser.next(reader, &mut self.common),
            };
            // Break only when `ignore_comments` option is disabled or got non-comment event.
            if self.config.ignore_comments {
                match r {
                    Ok(FbxEvent::Comment(_)) => {},
                    r => {
                        result = r;
                        break;
                    }
                }
            } else {
                result = r;
                break;
            }
        }
        // If parsing is finished, set `final_result`.
        match result {
            Ok(FbxEvent::EndFbx) | Err(_) => {
                self.common.final_result = Some(result.clone());
            },
            _ => {}
        }
        result
    }

    /// Read magic binary and update parser state if success.
    fn magic_next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        // 20 is the length of `b"Kaydara FBX Binary  "`.
        let mut first_line_bytes = Vec::with_capacity(20);
        // First, read the first line.
        // Read the first line manually.
        let magic_end_byte;
        loop {
            let c = try_read_le_u8!(self.common.pos, reader);
            if (c == 0) || (c == ('\n' as u8)) {
                magic_end_byte = c;
                break;
            }
            first_line_bytes.push(c);
        }
        // In Binary FBX, magic binary is `"Kaydara FBX Binary  "`,
        // and in ASCII FBX, there is no magic and it should be treated as normal line.
        if magic_end_byte == 0 {
            // Binary FBX?
            if first_line_bytes == b"Kaydara FBX Binary  " {
                // Binary FBX!
                // "unknown but all observed files show these bytes",
                // see https://code.blender.org/2013/08/fbx-binary-file-format-specification/ .
                {
                    let bytes = try_read_exact!(self.common.pos, reader, 2);
                    if bytes != vec![0x1A, 0x00] {
                        warn!("expected [0x1A, 0x00] right after magic, but got {:?}", bytes);
                    }
                }
                // Read FBX version.
                let version = try_read_le_u32!(self.common.pos, reader);
                debug!("magic binary read, Binary FBX (version={})", version);
                self.state = ParserState::Binary(BinaryParser::new(version));
                Ok(FbxEvent::StartFbx(FbxFormatType::Binary(version)))
            } else {
                Err(Error::new(self.common.pos, ErrorKind::InvalidMagic))
            }
        } else {
            assert_eq!(magic_end_byte, ('\n' as u8));
            // Maybe ASCII FBX
            let mut buffer;
            if first_line_bytes[0] != (';' as u8) {
                // The line is not comment, so the parser should remember it to use next time.
                buffer = try_with_pos!(self.common.pos, String::from_utf8(first_line_bytes));
                buffer.push('\n');
            } else {
                buffer = String::new();
            }
            self.state = ParserState::Ascii(AsciiParser::new(buffer));
            Ok(FbxEvent::StartFbx(FbxFormatType::Ascii))
        }
    }
}
<|endoftext|>


<commit_before>#[doc = "
A graphics sink that renders to PNG format buffers

Each time the renderer renders a frame the bufsink will output a
`[u8]` containing the frame in PNG format.
"];

export msg, pngsink;

import azure::cairo;
import azure_bg = azure::bindgen;
import azure::AzDrawTargetRef;
import cairo_bg = cairo::bindgen;

enum msg {
    begin_drawing(chan<AzDrawTargetRef>),
    draw(chan<AzDrawTargetRef>, AzDrawTargetRef),
    exit
}

impl pngsink of renderer::sink for chan<msg> {
    fn begin_drawing(next_dt: chan<AzDrawTargetRef>) {
        self.send(begin_drawing(next_dt))
    }
    fn draw(next_dt: chan<AzDrawTargetRef>, draw_me: AzDrawTargetRef) {
        self.send(draw(next_dt, draw_me))
    }
}

fn pngsink(output: chan<[u8]>) -> chan<msg> {
    task::spawn_listener::<msg> { |po|

        let cairo_surf = cairo_bg::cairo_image_surface_create(
            cairo::CAIRO_FORMAT_ARGB32, 800 as libc::c_int, 600 as libc::c_int
            );
        assert cairo_surf.is_not_null();

        let draw_target = azure_bg::AzCreateDrawTargetForCairoSurface(cairo_surf);
        assert draw_target.is_not_null();

        loop {
            alt po.recv() {
              begin_drawing(sender) {
                #debug("pngsink: begin_drawing");
                sender.send(draw_target);
              }
              draw(sender, dt) {
                #debug("pngsink: draw");
                do_draw(sender, dt, output, cairo_surf);
              }
              exit { break }
            }
        }

        azure_bg::AzReleaseDrawTarget(draw_target);
        cairo_bg::cairo_surface_destroy(cairo_surf);
    }
}

fn do_draw(sender: chan<AzDrawTargetRef>,
           dt: AzDrawTargetRef,
           output: comm::chan<[u8]>,
           cairo_surf: *cairo::cairo_surface_t) {

    import libc::*;

    listen {|data_ch|

        crust fn write_fn(closure: *c_void,
                          data: *c_uchar,
                          len: c_uint)

            -> cairo::cairo_status_t unsafe {

            let p: *chan<[u8]> = unsafe::reinterpret_cast(closure);
            let data_ch = *p;

            // Convert from *c_uchar to *u8
            let data = unsafe::reinterpret_cast(data);
            let len = len as uint;
            // Copy to a vector
            let data = vec::unsafe::from_buf(data, len);
            data_ch.send(data);

            ret cairo::CAIRO_STATUS_SUCCESS;
        }

        let closure = ptr::addr_of(data_ch);

        unsafe {
            cairo_bg::cairo_surface_write_to_png_stream(
                cairo_surf, write_fn, unsafe::reinterpret_cast(closure));
        }

        // Collect the entire image into a single vector
        let mut result = [];
        while data_ch.peek() {
            result += data_ch.recv();
        }

        // Send the PNG image away
        output.send(result);
    }
    // Send the next draw target to the renderer
    sender.send(dt);
}

#[test]
fn sanity_check() {

    listen {|ch|

        let sink = pngsink(ch);
        let renderer = renderer::renderer(sink);

        let dlist = [];
        renderer.send(renderer::RenderMsg(dlist));
        listen {|resp|
            renderer.send(renderer::ExitMsg(resp));
            resp.recv();
        }
        sink.send(exit)
    }
}
<commit_msg>"resp" -> "from_renderer"<commit_after>#[doc = "
A graphics sink that renders to PNG format buffers

Each time the renderer renders a frame the bufsink will output a
`[u8]` containing the frame in PNG format.
"];

export msg, pngsink;

import azure::cairo;
import azure_bg = azure::bindgen;
import azure::AzDrawTargetRef;
import cairo_bg = cairo::bindgen;

enum msg {
    begin_drawing(chan<AzDrawTargetRef>),
    draw(chan<AzDrawTargetRef>, AzDrawTargetRef),
    exit
}

impl pngsink of renderer::sink for chan<msg> {
    fn begin_drawing(next_dt: chan<AzDrawTargetRef>) {
        self.send(begin_drawing(next_dt))
    }
    fn draw(next_dt: chan<AzDrawTargetRef>, draw_me: AzDrawTargetRef) {
        self.send(draw(next_dt, draw_me))
    }
}

fn pngsink(output: chan<[u8]>) -> chan<msg> {
    task::spawn_listener::<msg> { |po|

        let cairo_surf = cairo_bg::cairo_image_surface_create(
            cairo::CAIRO_FORMAT_ARGB32, 800 as libc::c_int, 600 as libc::c_int
            );
        assert cairo_surf.is_not_null();

        let draw_target = azure_bg::AzCreateDrawTargetForCairoSurface(cairo_surf);
        assert draw_target.is_not_null();

        loop {
            alt po.recv() {
              begin_drawing(sender) {
                #debug("pngsink: begin_drawing");
                sender.send(draw_target);
              }
              draw(sender, dt) {
                #debug("pngsink: draw");
                do_draw(sender, dt, output, cairo_surf);
              }
              exit { break }
            }
        }

        azure_bg::AzReleaseDrawTarget(draw_target);
        cairo_bg::cairo_surface_destroy(cairo_surf);
    }
}

fn do_draw(sender: chan<AzDrawTargetRef>,
           dt: AzDrawTargetRef,
           output: comm::chan<[u8]>,
           cairo_surf: *cairo::cairo_surface_t) {

    import libc::*;

    listen {|data_ch|

        crust fn write_fn(closure: *c_void,
                          data: *c_uchar,
                          len: c_uint)

            -> cairo::cairo_status_t unsafe {

            let p: *chan<[u8]> = unsafe::reinterpret_cast(closure);
            let data_ch = *p;

            // Convert from *c_uchar to *u8
            let data = unsafe::reinterpret_cast(data);
            let len = len as uint;
            // Copy to a vector
            let data = vec::unsafe::from_buf(data, len);
            data_ch.send(data);

            ret cairo::CAIRO_STATUS_SUCCESS;
        }

        let closure = ptr::addr_of(data_ch);

        unsafe {
            cairo_bg::cairo_surface_write_to_png_stream(
                cairo_surf, write_fn, unsafe::reinterpret_cast(closure));
        }

        // Collect the entire image into a single vector
        let mut result = [];
        while data_ch.peek() {
            result += data_ch.recv();
        }

        // Send the PNG image away
        output.send(result);
    }
    // Send the next draw target to the renderer
    sender.send(dt);
}

#[test]
fn sanity_check() {
    listen {|ch|
        let sink = pngsink(ch);
        let renderer = renderer::renderer(sink);

        let dlist = [];
        renderer.send(renderer::RenderMsg(dlist));
        listen {
            |from_renderer|
            renderer.send(renderer::ExitMsg(from_renderer));
            from_renderer.recv();
        }

        sink.send(exit)
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::u32;
use std::fs::File;

use utility::{ErrorKind, ReadStream, many_metadata};

use metadata::{
  Metadata, Data,
  StreamInfo, CueSheet, VorbisComment, Picture,
  PictureType,
};

// Will return true when the unwrapped value of `option` and `other` match
// or `option` is `Option::None`, otherwise false.
#[inline]
pub fn optional_eq<T: Eq>(option: Option<T>, other: T) -> bool {
  option.map_or(true, |value| value == other)
}

// With the given filename, return all metadata blocks available.
//
// This function expects a flac file, but will return a proper `Result::Err`
// when things go wrong.
//
// # Failures
//
// * `ErrorKind::NotFound` is returned when the given filename isn't found.
// * `ErrorKind::InvalidData` is returned when the data within the file
//   isn't valid FLAC data.
pub fn get_metadata(filename: &str) -> Result<Vec<Metadata>, ErrorKind> {
  File::open(filename).map_err(|e| ErrorKind::IO(e.kind()))
                      .and_then(|file| {
    let mut stream   = ReadStream::new(file);
    let mut metadata = Vec::new();

    let result = many_metadata(&mut stream, |block| metadata.push(block));

    if let Err(kind) = result {
      match kind {
        ErrorKind::HeaderParser |
        ErrorKind::Unknown      => Err(ErrorKind::IO(
                                     io::ErrorKind::InvalidData)),
        _                       => Err(kind),
      }
    } else {
      Ok(metadata)
    }
  })
}

/// Reads and returns the `StreamInfo` metadata block of the given FLAC
/// file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `StreamInfo` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_stream_info("path/to/file.flac") {
///   Ok(stream_info) => {
///     // Use the stream_info variable...
///   }
///   Err(error)      => println!("{:?}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
///
/// let stream_info = metadata::get_stream_info("path/to/file.flac").unwrap();
/// ```
pub fn get_stream_info(filename: &str) -> Result<StreamInfo, ErrorKind> {
  get_metadata(filename).and_then(|blocks| {
    let mut result = Err(ErrorKind::NotFound);

    for block in blocks {
      if let Data::StreamInfo(stream_info) = block.data {
        result = Ok(stream_info);
        break;
      }
    }

    result
  })
}

/// Reads and returns the `VorbisComment` metadata block of the given FLAC
/// file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `VorbisComment` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_vorbis_comment("path/to/file.flac") {
///   Ok(vorbis_comment) => {
///     // Use the vorbis_comment variable...
///   }
///   Err(error)         => println!("{:?}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
///
/// let vorbis_comment =
///   metadata::get_vorbis_comment("path/to/file.flac").unwrap();
/// ```
pub fn get_vorbis_comment(filename: &str)
                          -> Result<VorbisComment, ErrorKind> {
  get_metadata(filename).and_then(|blocks| {
    let mut result = Err(ErrorKind::NotFound);

    for block in blocks {
      if let Data::VorbisComment(vorbis_comment) = block.data {
        result = Ok(vorbis_comment);
        break;
      }
    }

    result
  })
}

/// Reads and returns the `CueSheet` metadata block of the given FLAC file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `CueSheet` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_cue_sheet("path/to/file.flac") {
///   Ok(cue_sheet) => {
///     // Use the cue_sheet variable...
///   }
///   Err(error)    => println!("{:?}", error),
/// }
/// ```
///
/// Or just ignore the errors
///
/// ```no_run
/// use flac::metadata;
///
/// let cue_sheet = metadata::get_cue_sheet("path/to/file.flac").unwrap();
/// ```
pub fn get_cue_sheet(filename: &str) -> Result<CueSheet, ErrorKind> {
  get_metadata(filename).and_then(|blocks| {
    let mut result = Err(ErrorKind::NotFound);

    for block in blocks {
      if let Data::CueSheet(cue_sheet) = block.data {
        result = Ok(cue_sheet);
        break;
      }
    }

    result
  })
}

/// Reads and returns a `Picture` metadata block of the given FLAC file.
///
/// There can be more than one `Picture` block in a file and this function
/// takes optional, that being `Option<T>`, parameters that act as
/// constraints to search within. The `Picture` with the largest area
/// matching all constraints will be returned.
///
/// Putting `None` into any of the optional constraints conveys that you
/// want any of that parameter. Otherwise it will try to look for the image
/// that matches within the given constraints.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found,
///   there is no `Picture` within the file, or no `Picture` that fits the
///   given constraints.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
/// use flac::metadata::PictureType;
///
/// let result = metadata::get_picture("path/to/file.flac",
///                                    Some(PictureType::FileIcon),
///                                    Some("image/gif"),
///                                    None, None, None,
///                                    None, None);
///
/// match result {
///   Ok(picture) => {
///     // Use the picture variable...
///   }
///   Err(error)  => println!("{:?}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
/// use flac::metadata::PictureType;
///
/// let picture = metadata::get_picture("path/to/file.flac",
///                                     Some(PictureType::FileIcon),
///                                     Some("image/gif"),
///                                     None, None, None,
///                                     None, None).unwrap();
/// ```
pub fn get_picture(filename: &str,
                   picture_type: Option<PictureType>,
                   mime_type: Option<&str>,
                   description: Option<&str>,
                   max_width: Option<u32>,
                   max_height: Option<u32>,
                   max_depth: Option<u32>,
                   max_colors: Option<u32>)
                   -> Result<Picture, ErrorKind> {
  get_metadata(filename).and_then(|blocks| {
    let mut result = Err(ErrorKind::NotFound);

    let mut max_area_seen  = 0;
    let mut max_depth_seen = 0;

    let max_value      = u32::max_value();
    let max_width_num  = max_width.unwrap_or(max_value);
    let max_height_num = max_height.unwrap_or(max_value);
    let max_depth_num  = max_depth.unwrap_or(max_value);
    let max_colors_num = max_colors.unwrap_or(max_value);

    for block in blocks {
      if let Data::Picture(picture) = block.data {
        let area = (picture.width as u64) * (picture.height as u64);

        if optional_eq(picture_type, picture.picture_type) &&
           optional_eq(mime_type, &picture.mime_type) &&
           optional_eq(description, &picture.description) &&
           picture.width <= max_width_num &&
           picture.height <= max_height_num &&
           picture.depth <= max_depth_num &&
           picture.colors <= max_colors_num &&
           (area > max_area_seen || (area == max_area_seen &&
                                     picture.depth > max_depth_seen)) {
          max_area_seen  = area;
          max_depth_seen = picture.depth;
          result         = Ok(picture);
        }
      }
    }

    result
  })
}

#[cfg(test)]
mod tests {
  use super::*;
  use std::io::ErrorKind;

  #[test]
  #[should_panic]
  fn test_panic_optional_eq() {
    assert!(optional_eq(Some(1), 0));
  }

  #[test]
  fn test_optional_eq() {
    assert!(optional_eq(None, 0), "Should always return true when None");
    assert!(optional_eq(Some(0), 0), "Should return true (Some(0) == 0)");
  }

  #[test]
  fn test_get_metadata() {
    let not_found    = get_metadata("non-existent/file.txt");
    let invalid_data = get_metadata("README.md");
    let result       = get_metadata("tests/assets/input-SVAUP.flac");

    assert_eq!(not_found.unwrap_err().kind(), ErrorKind::NotFound);
    assert_eq!(invalid_data.unwrap_err().kind(), ErrorKind::InvalidData);
    assert!(result.is_ok());
  }
}
<commit_msg>Fix tests for `get_metadata`<commit_after>use std::io;
use std::u32;
use std::fs::File;

use utility::{ErrorKind, ReadStream, many_metadata};

use metadata::{
  Metadata, Data,
  StreamInfo, CueSheet, VorbisComment, Picture,
  PictureType,
};

// Will return true when the unwrapped value of `option` and `other` match
// or `option` is `Option::None`, otherwise false.
#[inline]
pub fn optional_eq<T: Eq>(option: Option<T>, other: T) -> bool {
  option.map_or(true, |value| value == other)
}

// With the given filename, return all metadata blocks available.
//
// This function expects a flac file, but will return a proper `Result::Err`
// when things go wrong.
//
// # Failures
//
// * `ErrorKind::NotFound` is returned when the given filename isn't found.
// * `ErrorKind::InvalidData` is returned when the data within the file
//   isn't valid FLAC data.
pub fn get_metadata(filename: &str) -> Result<Vec<Metadata>, ErrorKind> {
  File::open(filename).map_err(|e| ErrorKind::IO(e.kind()))
                      .and_then(|file| {
    let mut stream   = ReadStream::new(file);
    let mut metadata = Vec::new();

    let result = many_metadata(&mut stream, |block| metadata.push(block));

    if let Err(kind) = result {
      match kind {
        ErrorKind::HeaderParser |
        ErrorKind::Unknown      => Err(ErrorKind::IO(
                                     io::ErrorKind::InvalidData)),
        _                       => Err(kind),
      }
    } else {
      Ok(metadata)
    }
  })
}

/// Reads and returns the `StreamInfo` metadata block of the given FLAC
/// file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `StreamInfo` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_stream_info("path/to/file.flac") {
///   Ok(stream_info) => {
///     // Use the stream_info variable...
///   }
///   Err(error)      => println!("{:?}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
///
/// let stream_info = metadata::get_stream_info("path/to/file.flac").unwrap();
/// ```
pub fn get_stream_info(filename: &str) -> Result<StreamInfo, ErrorKind> {
  get_metadata(filename).and_then(|blocks| {
    let mut result = Err(ErrorKind::NotFound);

    for block in blocks {
      if let Data::StreamInfo(stream_info) = block.data {
        result = Ok(stream_info);
        break;
      }
    }

    result
  })
}

/// Reads and returns the `VorbisComment` metadata block of the given FLAC
/// file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `VorbisComment` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_vorbis_comment("path/to/file.flac") {
///   Ok(vorbis_comment) => {
///     // Use the vorbis_comment variable...
///   }
///   Err(error)         => println!("{:?}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
///
/// let vorbis_comment =
///   metadata::get_vorbis_comment("path/to/file.flac").unwrap();
/// ```
pub fn get_vorbis_comment(filename: &str)
                          -> Result<VorbisComment, ErrorKind> {
  get_metadata(filename).and_then(|blocks| {
    let mut result = Err(ErrorKind::NotFound);

    for block in blocks {
      if let Data::VorbisComment(vorbis_comment) = block.data {
        result = Ok(vorbis_comment);
        break;
      }
    }

    result
  })
}

/// Reads and returns the `CueSheet` metadata block of the given FLAC file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `CueSheet` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_cue_sheet("path/to/file.flac") {
///   Ok(cue_sheet) => {
///     // Use the cue_sheet variable...
///   }
///   Err(error)    => println!("{:?}", error),
/// }
/// ```
///
/// Or just ignore the errors
///
/// ```no_run
/// use flac::metadata;
///
/// let cue_sheet = metadata::get_cue_sheet("path/to/file.flac").unwrap();
/// ```
pub fn get_cue_sheet(filename: &str) -> Result<CueSheet, ErrorKind> {
  get_metadata(filename).and_then(|blocks| {
    let mut result = Err(ErrorKind::NotFound);

    for block in blocks {
      if let Data::CueSheet(cue_sheet) = block.data {
        result = Ok(cue_sheet);
        break;
      }
    }

    result
  })
}

/// Reads and returns a `Picture` metadata block of the given FLAC file.
///
/// There can be more than one `Picture` block in a file and this function
/// takes optional, that being `Option<T>`, parameters that act as
/// constraints to search within. The `Picture` with the largest area
/// matching all constraints will be returned.
///
/// Putting `None` into any of the optional constraints conveys that you
/// want any of that parameter. Otherwise it will try to look for the image
/// that matches within the given constraints.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found,
///   there is no `Picture` within the file, or no `Picture` that fits the
///   given constraints.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
/// use flac::metadata::PictureType;
///
/// let result = metadata::get_picture("path/to/file.flac",
///                                    Some(PictureType::FileIcon),
///                                    Some("image/gif"),
///                                    None, None, None,
///                                    None, None);
///
/// match result {
///   Ok(picture) => {
///     // Use the picture variable...
///   }
///   Err(error)  => println!("{:?}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
/// use flac::metadata::PictureType;
///
/// let picture = metadata::get_picture("path/to/file.flac",
///                                     Some(PictureType::FileIcon),
///                                     Some("image/gif"),
///                                     None, None, None,
///                                     None, None).unwrap();
/// ```
pub fn get_picture(filename: &str,
                   picture_type: Option<PictureType>,
                   mime_type: Option<&str>,
                   description: Option<&str>,
                   max_width: Option<u32>,
                   max_height: Option<u32>,
                   max_depth: Option<u32>,
                   max_colors: Option<u32>)
                   -> Result<Picture, ErrorKind> {
  get_metadata(filename).and_then(|blocks| {
    let mut result = Err(ErrorKind::NotFound);

    let mut max_area_seen  = 0;
    let mut max_depth_seen = 0;

    let max_value      = u32::max_value();
    let max_width_num  = max_width.unwrap_or(max_value);
    let max_height_num = max_height.unwrap_or(max_value);
    let max_depth_num  = max_depth.unwrap_or(max_value);
    let max_colors_num = max_colors.unwrap_or(max_value);

    for block in blocks {
      if let Data::Picture(picture) = block.data {
        let area = (picture.width as u64) * (picture.height as u64);

        if optional_eq(picture_type, picture.picture_type) &&
           optional_eq(mime_type, &picture.mime_type) &&
           optional_eq(description, &picture.description) &&
           picture.width <= max_width_num &&
           picture.height <= max_height_num &&
           picture.depth <= max_depth_num &&
           picture.colors <= max_colors_num &&
           (area > max_area_seen || (area == max_area_seen &&
                                     picture.depth > max_depth_seen)) {
          max_area_seen  = area;
          max_depth_seen = picture.depth;
          result         = Ok(picture);
        }
      }
    }

    result
  })
}

#[cfg(test)]
mod tests {
  use super::*;
  use std::io;

  use utility::ErrorKind;

  #[test]
  #[should_panic]
  fn test_panic_optional_eq() {
    assert!(optional_eq(Some(1), 0));
  }

  #[test]
  fn test_optional_eq() {
    assert!(optional_eq(None, 0), "Should always return true when None");
    assert!(optional_eq(Some(0), 0), "Should return true (Some(0) == 0)");
  }

  #[test]
  fn test_get_metadata() {
    let not_found    = get_metadata("non-existent/file.txt");
    let invalid_data = get_metadata("README.md");
    let result       = get_metadata("tests/assets/input-SVAUP.flac");

    assert_eq!(not_found.unwrap_err(), ErrorKind::IO(
                                         io::ErrorKind::NotFound));
    assert_eq!(invalid_data.unwrap_err(), ErrorKind::IO(
                                            io::ErrorKind::InvalidData));
    assert!(result.is_ok());
  }
}
<|endoftext|>


<commit_before>use std::sync::atomic::{compiler_fence, fence, AtomicBool, AtomicIsize, AtomicU64, Ordering::*};

fn main() {
    atomic_bool();
    atomic_isize();
    atomic_u64();
    atomic_fences();
}

fn atomic_bool() {
    static mut ATOMIC: AtomicBool = AtomicBool::new(false);

    unsafe {
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.store(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_or(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_and(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.fetch_nand(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_xor(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
    }
}
// There isn't a trait to use to make this generic, so just use a macro
macro_rules! compare_exchange_weak_loop {
    ($atom:expr, $from:expr, $to:expr, $succ_order:expr, $fail_order:expr) => {
        loop {
            match $atom.compare_exchange_weak($from, $to, $succ_order, $fail_order) {
                Ok(n) => {
                    assert_eq!(n, $from);
                    break;
                }
                Err(n) => assert_eq!(n, $from),
            }
        }
    };
}
fn atomic_isize() {
    static ATOMIC: AtomicIsize = AtomicIsize::new(0);

    // Make sure trans can emit all the intrinsics correctly
    assert_eq!(ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed), Ok(0));
    assert_eq!(ATOMIC.compare_exchange(0, 2, Acquire, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange(0, 1, Release, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange(1, 0, AcqRel, Relaxed), Ok(1));
    ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst).ok();

    ATOMIC.store(0, SeqCst);
    compare_exchange_weak_loop!(ATOMIC, 0, 1, Relaxed, Relaxed);
    assert_eq!(ATOMIC.compare_exchange_weak(0, 2, Acquire, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed), Err(1));
    compare_exchange_weak_loop!(ATOMIC, 1, 0, AcqRel, Relaxed);
    assert_eq!(ATOMIC.load(Relaxed), 0);
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok();
}

fn atomic_u64() {
    static ATOMIC: AtomicU64 = AtomicU64::new(0);

    ATOMIC.store(1, SeqCst);
    assert_eq!(ATOMIC.compare_exchange(0, 0x100, AcqRel, Acquire), Err(1));
    compare_exchange_weak_loop!(ATOMIC, 1, 0x100, AcqRel, Acquire);
    assert_eq!(ATOMIC.load(Relaxed), 0x100);
}

fn atomic_fences() {
    fence(SeqCst);
    fence(Release);
    fence(Acquire);
    fence(AcqRel);
    compiler_fence(SeqCst);
    compiler_fence(Release);
    compiler_fence(Acquire);
    compiler_fence(AcqRel);
}
<commit_msg>Test that _weak atomics sometimes fail<commit_after>use std::sync::atomic::{compiler_fence, fence, AtomicBool, AtomicIsize, AtomicU64, Ordering::*};

fn main() {
    atomic_bool();
    atomic_isize();
    atomic_u64();
    atomic_fences();
    weak_sometimes_fails();
}

fn atomic_bool() {
    static mut ATOMIC: AtomicBool = AtomicBool::new(false);

    unsafe {
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.store(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_or(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_and(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.fetch_nand(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_xor(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
    }
}
// There isn't a trait to use to make this generic, so just use a macro
macro_rules! compare_exchange_weak_loop {
    ($atom:expr, $from:expr, $to:expr, $succ_order:expr, $fail_order:expr) => {
        loop {
            match $atom.compare_exchange_weak($from, $to, $succ_order, $fail_order) {
                Ok(n) => {
                    assert_eq!(n, $from);
                    break;
                }
                Err(n) => assert_eq!(n, $from),
            }
        }
    };
}
fn atomic_isize() {
    static ATOMIC: AtomicIsize = AtomicIsize::new(0);

    // Make sure trans can emit all the intrinsics correctly
    assert_eq!(ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed), Ok(0));
    assert_eq!(ATOMIC.compare_exchange(0, 2, Acquire, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange(0, 1, Release, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange(1, 0, AcqRel, Relaxed), Ok(1));
    ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst).ok();

    ATOMIC.store(0, SeqCst);
    compare_exchange_weak_loop!(ATOMIC, 0, 1, Relaxed, Relaxed);
    assert_eq!(ATOMIC.compare_exchange_weak(0, 2, Acquire, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed), Err(1));
    compare_exchange_weak_loop!(ATOMIC, 1, 0, AcqRel, Relaxed);
    assert_eq!(ATOMIC.load(Relaxed), 0);
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok();
}

fn atomic_u64() {
    static ATOMIC: AtomicU64 = AtomicU64::new(0);

    ATOMIC.store(1, SeqCst);
    assert_eq!(ATOMIC.compare_exchange(0, 0x100, AcqRel, Acquire), Err(1));
    compare_exchange_weak_loop!(ATOMIC, 1, 0x100, AcqRel, Acquire);
    assert_eq!(ATOMIC.load(Relaxed), 0x100);
}

fn atomic_fences() {
    fence(SeqCst);
    fence(Release);
    fence(Acquire);
    fence(AcqRel);
    compiler_fence(SeqCst);
    compiler_fence(Release);
    compiler_fence(Acquire);
    compiler_fence(AcqRel);
}

fn weak_sometimes_fails() {
    static ATOMIC: AtomicBool = AtomicBool::new(false);
    let tries = 20;
    for _ in 0..tries {
        let cur = ATOMIC.load(Relaxed);
        // Try (weakly) to flip the flag.
        if ATOMIC.compare_exchange_weak(cur, !cur, Relaxed, Relaxed).is_err() {
            // We succeeded, so return and skip the panic.
            return;
        }
    }
    panic!("compare_exchange_weak succeeded {} tries in a row", tries);
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::sync::{
    Arc,
    Mutex,
};
use std::thread;
use std::time::Duration;

use winapi::winsock2::{
    fd_set,
    FD_SETSIZE,
    SOCKET_ERROR,
    timeval,
    WSADATA,
};
use ws2_32::{
    select,
    WSACleanup,
    WSAStartup,
};

use c_ares;
use mio;

use error::ResolverError;
use eventloop::EventLoopHandle;

// The EventLoop will use select() to check on the status of file descriptors
// that c-ares cares about.
//
// It also waits for a message telling it to shut down.  We use a mio channel
// here only for consistency with the unix interface.
pub struct EventLoop {
    tx_msg_channel: mio::channel::Sender<Message>,
    rx_msg_channel: mio::channel::Receiver<Message>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: bool,
}

// Messages for the event loop.
#[derive(Debug)]
pub enum Message {
    // 'Shut down'.
    ShutDown,
}

impl EventLoop {
    // Create a new event loop.
    pub fn new(options: c_ares::Options) -> Result<EventLoop, ResolverError> {
        // Initialize sockets.
        unsafe {
            let mut wsadata: WSADATA = mem::uninitialized();
            WSAStartup(0x101, &mut wsadata);
        }

        // Create the message channel.
        let (tx, rx) = mio::channel::channel();

        // Create the c-ares channel.
        let ares_channel = try!(c_ares::Channel::new(options));
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            tx_msg_channel: tx,
            rx_msg_channel: rx,
            ares_channel: locked_channel,
            quit: false,
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopHandle {
        let tx_clone = self.tx_msg_channel.clone();
        let join_handle = thread::spawn(|| self.event_loop_thread());
        EventLoopHandle::new(join_handle, tx_clone)
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let timeout = timeval {
            tv_sec: 0,
            tv_usec: 200000,
        };
        let duration = Duration::from_millis(200);

        // Loop round, asking c-ares what it cares about and doing as asked.
        loop {
            let mut read_fds = fd_set {
                fd_count: 0,
                fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
            };
            let mut write_fds = fd_set {
                fd_count: 0,
                fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
            };
            let count = self.ares_channel.lock().unwrap().fds(&mut read_fds, &mut write_fds);

            // Wait for something to happen.
            let results = unsafe {
                if count == 0 {
                    thread::sleep(duration);
                    0
                } else {
                    select(0, &mut read_fds, &mut write_fds, ptr::null_mut(), &timeout)
                }
            };

            // Process whatever happened.
            match results {
                SOCKET_ERROR => panic!("Socket error"),
                _ => self.ares_channel.lock().unwrap().process(&mut read_fds, &mut write_fds),
            }

            // Check whether we're asked to quit.
            self.handle_messages();
            if self.quit { break }
        }
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        loop {
            match self.rx_msg_channel.try_recv() {
                Ok(Message::ShutDown) => {
                    // Instruction to shut down.
                    self.quit = true;
                    break
                },

                // No more instructions.
                Err(_) => break,
            }
        }
    }
}

impl Drop for EventLoop {
    fn drop(&mut self) {
        unsafe { WSACleanup(); }
    }
}
<commit_msg>clippy<commit_after>use std::mem;
use std::ptr;
use std::sync::{
    Arc,
    Mutex,
};
use std::thread;
use std::time::Duration;

use winapi::winsock2::{
    fd_set,
    FD_SETSIZE,
    SOCKET_ERROR,
    timeval,
    WSADATA,
};
use ws2_32::{
    select,
    WSACleanup,
    WSAStartup,
};

use c_ares;
use mio;

use error::ResolverError;
use eventloop::EventLoopHandle;

// The EventLoop will use select() to check on the status of file descriptors
// that c-ares cares about.
//
// It also waits for a message telling it to shut down.  We use a mio channel
// here only for consistency with the unix interface.
pub struct EventLoop {
    tx_msg_channel: mio::channel::Sender<Message>,
    rx_msg_channel: mio::channel::Receiver<Message>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: bool,
}

// Messages for the event loop.
#[derive(Debug)]
pub enum Message {
    // 'Shut down'.
    ShutDown,
}

impl EventLoop {
    // Create a new event loop.
    pub fn new(options: c_ares::Options) -> Result<EventLoop, ResolverError> {
        // Initialize sockets.
        unsafe {
            let mut wsadata: WSADATA = mem::uninitialized();
            WSAStartup(0x101, &mut wsadata);
        }

        // Create the message channel.
        let (tx, rx) = mio::channel::channel();

        // Create the c-ares channel.
        let ares_channel = try!(c_ares::Channel::new(options));
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            tx_msg_channel: tx,
            rx_msg_channel: rx,
            ares_channel: locked_channel,
            quit: false,
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopHandle {
        let tx_clone = self.tx_msg_channel.clone();
        let join_handle = thread::spawn(|| self.event_loop_thread());
        EventLoopHandle::new(join_handle, tx_clone)
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let timeout = timeval {
            tv_sec: 0,
            tv_usec: 200000,
        };
        let duration = Duration::from_millis(200);

        // Loop round, asking c-ares what it cares about and doing as asked.
        loop {
            let mut read_fds = fd_set {
                fd_count: 0,
                fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
            };
            let mut write_fds = fd_set {
                fd_count: 0,
                fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
            };
            let count = self.ares_channel.lock().unwrap().fds(&mut read_fds, &mut write_fds);

            // Wait for something to happen.
            let results = unsafe {
                if count == 0 {
                    thread::sleep(duration);
                    0
                } else {
                    select(0, &mut read_fds, &mut write_fds, ptr::null_mut(), &timeout)
                }
            };

            // Process whatever happened.
            match results {
                SOCKET_ERROR => panic!("Socket error"),
                _ => self.ares_channel.lock().unwrap().process(&mut read_fds, &mut write_fds),
            }

            // Check whether we're asked to quit.
            self.handle_messages();
            if self.quit { break }
        }
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        // The only possible message is an instruction to shut down.
        if let Ok(Message::ShutDown) = self.rx_msg_channel.try_recv() {
            self.quit = true;
        }
    }
}

impl Drop for EventLoop {
    fn drop(&mut self) {
        unsafe { WSACleanup(); }
    }
}
<|endoftext|>


<commit_before>use mail::Mail;

use std::borrow::Cow;
use std::io::Read;

use hyper::Client;
use hyper::header::{Authorization, Bearer, ContentType, Headers};
use hyper::mime::{Mime, TopLevel, SubLevel};

static API_URL: &'static str = "https://api.sendgrid.com/api/mail.send.json?";

pub struct SGClient {
    api_key: String,
}

impl SGClient {
    fn make_post_body<'a>(self, mut mail_info: Mail) -> Cow<'a, str> {
        let mut body = String::new();

        // The leading POST data should not start with an ampersand.
        let first_to = mail_info.to.remove(0);
        body.push_str("to[]=");
        body.push_str(&first_to[..]);

        // Now, add anymore if need be.
        for to in mail_info.to.iter() {
            body.push_str("&to[]=");
            body.push_str(&to[..]);
        }

        for cc in mail_info.cc.iter() {
            body.push_str("&cc[]=");
            body.push_str(&cc[..]);
        }

        body.push_str("&from=");
        body.push_str(mail_info.from);

        body.push_str("&subject=");
        body.push_str(mail_info.subject);

        body.push_str("&html=");
        body.push_str(mail_info.html);

        body.into()
    }

    pub fn new(key: String) -> SGClient {
        SGClient {api_key: key}
    }

    pub fn send(self, mail_info: Mail) {
        let client = Client::new();
        let mut headers = Headers::new();
        headers.set(
            Authorization(
                Bearer { token: self.api_key.to_owned() }
                )
        );
        headers.set(
            ContentType(
                Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, vec![])
                )
        );

        let post_body = self.make_post_body(mail_info).into_owned();
        let mut res = client.post(API_URL)
            .headers(headers)
            .body(&post_body[..])
            .send()
            .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        println!("Response: {}", body);
    }
}
<commit_msg>add UserAgent header<commit_after>use mail::Mail;

use std::borrow::Cow;
use std::io::Read;

use hyper::Client;
use hyper::header::{Authorization, Bearer, ContentType, Headers, UserAgent};
use hyper::mime::{Mime, TopLevel, SubLevel};

static API_URL: &'static str = "https://api.sendgrid.com/api/mail.send.json?";

pub struct SGClient {
    api_key: String,
}

impl SGClient {
    fn make_post_body<'a>(self, mut mail_info: Mail) -> Cow<'a, str> {
        let mut body = String::new();

        // The leading POST data should not start with an ampersand.
        let first_to = mail_info.to.remove(0);
        body.push_str("to[]=");
        body.push_str(&first_to[..]);

        // Now, add anymore if need be.
        for to in mail_info.to.iter() {
            body.push_str("&to[]=");
            body.push_str(&to[..]);
        }

        for cc in mail_info.cc.iter() {
            body.push_str("&cc[]=");
            body.push_str(&cc[..]);
        }

        body.push_str("&from=");
        body.push_str(mail_info.from);

        body.push_str("&subject=");
        body.push_str(mail_info.subject);

        body.push_str("&html=");
        body.push_str(mail_info.html);

        body.into()
    }

    pub fn new(key: String) -> SGClient {
        SGClient {api_key: key}
    }

    pub fn send(self, mail_info: Mail) {
        let client = Client::new();
        let mut headers = Headers::new();
        headers.set(
            Authorization(
                Bearer { token: self.api_key.to_owned() }
                )
        );
        headers.set(
            ContentType(
                Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, vec![])
                )
        );
        headers.set(
            UserAgent("sendgrid-rs".to_owned())
        );

        let post_body = self.make_post_body(mail_info).into_owned();
        let mut res = client.post(API_URL)
            .headers(headers)
            .body(&post_body[..])
            .send()
            .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        println!("Response: {}", body);
    }
}
<|endoftext|>


<commit_before>//! Logic for state machine.

use state::State;
use state::UpdateDelta;

pub type UpdateFunction<T, D> = fn (obj: &mut T, delta: &D);

/// A unique identifier for object.
pub struct ObjectId(uint);

/// A unique identifier for state.
pub struct StateId(uint);

/// Keeps track of the current state of objects.
/// Also keeps an update function per state.
/// This is because otherwise all states require same logic.
pub struct StateMachine<Object, Delta> {
    current: State<StateId>,
    states: State<State<Object>>,
    update_functions: State<UpdateFunction<Object, Delta>>
}

impl<T, D> StateMachine<T, D> {
    /// Adds a new state.
    pub fn add_state(
            &mut self,
            StateId(state_id): StateId,
            state: State<T>,
            update: Option<UpdateFunction<T, D>>
    ) {
        self.states.objects.insert(state_id, state);
        match update {
            None => {},
            Some(fun) => { self.update_functions.objects.insert(state_id, fun); }
        }
    }

    /// Adds a new object.
    pub fn add_object(
            &mut self,
            StateId(state_id): StateId,
            ObjectId(obj_id): ObjectId,
            obj: T) {
        self.current.objects.insert(obj_id, StateId(state_id));
        self.states.objects.get_mut(&state_id).objects.insert(obj_id, obj);
    }

    /// Returns the current value of object by looking up in correct state.
    #[inline(always)]
    pub fn val<'a>(&'a self, ObjectId(obj): ObjectId) -> &'a T {
        let &StateId(state) = self.current.objects.get(&obj);
        self.states.objects.get(&state).objects.get(&obj)
    }

    /// Returns the current `state_id` of an object.
    pub fn state_id(&self, ObjectId(obj): ObjectId) -> StateId {
        *self.current.objects.get(&obj)
    }

    /// Returns the current state of an object.
    pub fn state<'a>(&'a self, ObjectId(obj): ObjectId) -> &'a State<T> {
        let &StateId(state) = self.current.objects.get(&obj);
        self.states.objects.get(&state)
    }

    /// Moves an object to a new state.
    pub fn move_to(&mut self, StateId(to): StateId, ObjectId(obj): ObjectId) {
        let &StateId(state) = self.current.objects.get(&obj);
        let pop = self.states.objects.get_mut(&state).objects.pop(&obj);
        match pop {
            None => {},
            Some(val) => { self.states.objects.get_mut(&to).objects.insert(obj, val); }
        }
    }
}

impl<T: UpdateDelta<D>, D>
UpdateDelta<D> for StateMachine<T, D> {
    fn update(&mut self, delta: &D) {
        for (id_state, state) in self.states.objects.mut_iter() {
            match self.update_functions.objects.find(id_state) {
                    None => {},
                    Some(fun) => {
                        for (_, obj) in state.objects.mut_iter() {
                            (*fun)(obj, delta);
                        }
                    }
            }
        }
    }
}

<commit_msg>Added pop<commit_after>//! Logic for state machine.

use state::State;
use state::UpdateDelta;

pub type UpdateFunction<T, D> = fn (obj: &mut T, delta: &D);

/// A unique identifier for object.
pub struct ObjectId(uint);

/// A unique identifier for state.
pub struct StateId(uint);

/// Keeps track of the current state of objects.
/// Also keeps an update function per state.
/// This is because otherwise all states require same logic.
pub struct StateMachine<Object, Delta> {
    current: State<StateId>,
    states: State<State<Object>>,
    update_functions: State<UpdateFunction<Object, Delta>>
}

impl<T, D> StateMachine<T, D> {
    /// Adds a new state.
    pub fn add_state(
            &mut self,
            StateId(state_id): StateId,
            state: State<T>,
            update: Option<UpdateFunction<T, D>>
    ) {
        self.states.objects.insert(state_id, state);
        match update {
            None => {},
            Some(fun) => { self.update_functions.objects.insert(state_id, fun); }
        }
    }

    /// Adds a new object.
    pub fn add_object(
            &mut self,
            StateId(state_id): StateId,
            ObjectId(obj_id): ObjectId,
            obj: T) {
        self.current.objects.insert(obj_id, StateId(state_id));
        self.states.objects.get_mut(&state_id).objects.insert(obj_id, obj);
    }

    /// Returns the current value of object by looking up in correct state.
    #[inline(always)]
    pub fn val<'a>(&'a self, ObjectId(obj): ObjectId) -> &'a T {
        let &StateId(state) = self.current.objects.get(&obj);
        self.states.objects.get(&state).objects.get(&obj)
    }

    /// Returns the current `state_id` of an object.
    pub fn state_id(&self, ObjectId(obj): ObjectId) -> StateId {
        *self.current.objects.get(&obj)
    }

    /// Returns the current state of an object.
    pub fn state<'a>(&'a self, ObjectId(obj): ObjectId) -> &'a State<T> {
        let &StateId(state) = self.current.objects.get(&obj);
        self.states.objects.get(&state)
    }

    /// Moves an object to a new state.
    pub fn move_to(&mut self, StateId(to): StateId, ObjectId(obj): ObjectId) {
        let &StateId(state) = self.current.objects.get(&obj);
        let pop = self.states.objects.get_mut(&state).objects.pop(&obj);
        match pop {
            None => {},
            Some(val) => { self.states.objects.get_mut(&to).objects.insert(obj, val); }
        }
    }

    /// Removes an object from state machine.
    pub fn pop(&mut self, ObjectId(obj): ObjectId) -> Option<T> {
        let &StateId(state) = self.current.objects.get(&obj);
        self.states.objects.get_mut(&state).objects.pop(&obj)
    }
}

impl<T: UpdateDelta<D>, D>
UpdateDelta<D> for StateMachine<T, D> {
    fn update(&mut self, delta: &D) {
        for (id_state, state) in self.states.objects.mut_iter() {
            match self.update_functions.objects.find(id_state) {
                    None => {},
                    Some(fun) => {
                        for (_, obj) in state.objects.mut_iter() {
                            (*fun)(obj, delta);
                        }
                    }
            }
        }
    }
}

<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   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
//
//       http://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.
//

//!
//! A symbol reader reads one symbol at a time from a source
//!

use std::slice::Iter;
use std::io::Read;
use std::io::Bytes;
use std::str::Chars;
use std::marker::PhantomData;

///
/// A symbol reader reads one symbol at a time from a source
///
pub trait SymbolReader<Symbol> {
    ///
    /// Reads the next symbol from this reader
    ///
    fn next_symbol(&mut self) -> Option<Symbol>;
}

///
/// Trait that can be implemented by things that can construct a symbol reader
///
pub trait SymbolSource<'a, Symbol> {
    /// The type of symbol reader that will be generated by this call
    type SymbolReader: SymbolReader<Symbol>+'a;

    /// Returns a new object that can read the symbols from this one
    fn read_symbols(self) -> Self::SymbolReader;
}

impl<'a, Symbol: Clone+'a> SymbolSource<'a, Symbol> for &'a Vec<Symbol> {
    type SymbolReader = Iter<'a, Symbol>;

    fn read_symbols(self) -> Self::SymbolReader {
        self.iter()
    }
}

impl<'a, Symbol: Clone+'a> SymbolReader<Symbol> for Iter<'a, Symbol> {
    fn next_symbol(&mut self) -> Option<Symbol> {
        if let Some(sym) = self.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

// Can read from streams

//
// TODO: implementing SymbolSource for Read would be nice
// It's just a matter of calling bytes() on the appropriate type, but Rust's type system is simultaneously too clever and not clever enough
// to allow that in any sensible way. You can't do it an an arbitrary Read because the Bytes object is not sized without knowing its real
// type; I couldn't figure out a trick using the Self type to get around that, though those do work sometimes.
// `impl<X: Read> SymbolReader for X` sounds like a nice idea but Rust thinks X can be anything and won't allow any other implementations
// of the interface, which makes that useless too.
// Screwing around with lifetimes and references like below seems like it should work, but Rust doesn't seem to see the implementations on
// actual streams.
//

/*
impl<'a> SymbolSource<'a, u8> for &'a mut Read {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}

impl<'a> SymbolSource<'a, u8> for &'a mut BufRead {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}
*/

///
/// The ByteSymbolReader turns a `std::io::Bytes` object into a symbol reader
///
pub struct ByteSymbolReader<Reader: Read> {
    bytes: Bytes<Reader>
}

impl<Reader: Read> ByteSymbolReader<Reader> {
    pub fn new(bytes: Bytes<Reader>) -> ByteSymbolReader<Reader> {
        ByteSymbolReader { bytes: bytes }
    }

    pub fn from(reader: Reader) -> ByteSymbolReader<Reader> {
        Self::new(reader.bytes())
    }
}

impl<Reader: Read> SymbolReader<u8> for ByteSymbolReader<Reader> {
    fn next_symbol(&mut self) -> Option<u8> {
        if let Some(Ok(sym)) = self.bytes.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

//
// Can read from strings
//
impl<'a> SymbolSource<'a, char> for &'a str {
    type SymbolReader = Chars<'a>;

    fn read_symbols(self) -> Self::SymbolReader {
        self.chars()
    }
}

impl<'a> SymbolReader<char> for Chars<'a> {
    fn next_symbol(&mut self) -> Option<char> {
        self.next()
    }
}

///
/// Converts symbol streams to vectors
///
pub trait ReaderToVector<Symbol> {
    /// Reads every symbol in this object and returns a vector
    fn to_vec(&mut self) -> Vec<Symbol>;
}

impl<Symbol, Reader: SymbolReader<Symbol>> ReaderToVector<Symbol> for Reader {
    #[inline]
    fn to_vec(&mut self) -> Vec<Symbol> {
        let mut result = vec![];

        while let Some(symbol) = self.next_symbol() {
            result.push(symbol);
        }

        result
    }
}

///
/// A symbol stream that performs mapping of symbols from a source stream
///
pub struct MappedStream<'a, InputSymbol, MapFunction, Reader>
where Reader: SymbolReader<InputSymbol>+'a {
    /// The source stream
    source_stream: &'a mut Reader,

    /// A function used to map a symbol from the source stream to a symbol in the output stream
    mapping_function: MapFunction,

    // Can't see how to eliminate the input symbol reference due to rust's type system. This is used by source_stream, but rust can't see that
    #[allow(dead_code)]
    phantom: PhantomData<InputSymbol>
}

///
/// Provides a way to map symbol streams to streams of other types
///
pub trait MapSymbolReader<Symbol> : SymbolReader<Symbol>+Sized {
    /// Maps symbols in this stream to symbols in a new stream
    fn map_symbols<'a, OutputSymbol, MapFunction>(&'a mut self, mapping_function: MapFunction) -> MappedStream<'a, Symbol, MapFunction, Self>
    where MapFunction: FnMut(Symbol) -> OutputSymbol;
}

impl<Symbol, Reader: SymbolReader<Symbol>> MapSymbolReader<Symbol> for Reader {
    fn map_symbols<'a, OutputSymbol, MapFunction>(&'a mut self, mapping_function: MapFunction) -> MappedStream<'a, Symbol, MapFunction, Self>
    where MapFunction: FnMut(Symbol) -> OutputSymbol {
        MappedStream {
            source_stream:    self,
            mapping_function: mapping_function,
            phantom:          PhantomData
        }
    }
}

impl<'a, InputSymbol, OutputSymbol, MapFunction, Reader: SymbolReader<InputSymbol>+'a> SymbolReader<OutputSymbol> for MappedStream<'a, InputSymbol, MapFunction, Reader>
where MapFunction: FnMut(InputSymbol) -> OutputSymbol {
    fn next_symbol(&mut self) -> Option<OutputSymbol> {
        if let Some(input_symbol) = self.source_stream.next_symbol() {
            Some((self.mapping_function)(input_symbol))
        } else {
            None
        }
    }
}

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

    #[test]
    fn can_read_from_vec() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }

    #[test]
    fn can_convert_to_vec() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();
        let result      = reader.to_vec();

        assert!(result == vec![1, 2, 3]);
    }

    #[test]
    fn can_map_stream() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();
        let result      = reader.map_symbols(|sym| sym+1).to_vec();

        assert!(result == vec![2, 3, 4]);
    }

    #[test]
    fn can_read_from_bytes_reader() {
        let array: [u8; 3] = [1, 2, 3];
        let slice = &array[..];
        let mut reader = ByteSymbolReader::from(slice);

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }

    #[test]
    fn can_read_from_string_reader() {
        let mut reader = "abc".read_symbols();

        assert!(reader.next_symbol() == Some('a'));
        assert!(reader.next_symbol() == Some('b'));
        assert!(reader.next_symbol() == Some('c'));
        assert!(reader.next_symbol() == None);
    }
}
<commit_msg>Clarify comment<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   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
//
//       http://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.
//

//!
//! A symbol reader reads one symbol at a time from a source
//!

use std::slice::Iter;
use std::io::Read;
use std::io::Bytes;
use std::str::Chars;
use std::marker::PhantomData;

///
/// A symbol reader reads one symbol at a time from a source
///
pub trait SymbolReader<Symbol> {
    ///
    /// Reads the next symbol from this reader
    ///
    fn next_symbol(&mut self) -> Option<Symbol>;
}

///
/// Trait that can be implemented by things that can construct a symbol reader
///
pub trait SymbolSource<'a, Symbol> {
    /// The type of symbol reader that will be generated by this call
    type SymbolReader: SymbolReader<Symbol>+'a;

    /// Returns a new object that can read the symbols from this one
    fn read_symbols(self) -> Self::SymbolReader;
}

impl<'a, Symbol: Clone+'a> SymbolSource<'a, Symbol> for &'a Vec<Symbol> {
    type SymbolReader = Iter<'a, Symbol>;

    fn read_symbols(self) -> Self::SymbolReader {
        self.iter()
    }
}

impl<'a, Symbol: Clone+'a> SymbolReader<Symbol> for Iter<'a, Symbol> {
    fn next_symbol(&mut self) -> Option<Symbol> {
        if let Some(sym) = self.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

// Can read from streams

//
// TODO: implementing SymbolSource for Read would be nice
// It's just a matter of calling bytes() on the appropriate type, but Rust's type system is simultaneously too clever and not clever enough
// to allow that in any sensible way. You can't do it an an arbitrary Read because the Bytes object is not sized without knowing its real
// type; I couldn't figure out a trick using the Self type to get around that, though those do work sometimes.
// `impl<X: Read> SymbolReader for X` sounds like a nice idea but Rust thinks X can be anything and won't allow any other implementations
// of the interface, which makes that useless too.
// Screwing around with lifetimes and references like below seems like it should work, but Rust doesn't seem to see the implementations on
// actual streams.
//

/*
impl<'a> SymbolSource<'a, u8> for &'a mut Read {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}

impl<'a> SymbolSource<'a, u8> for &'a mut BufRead {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}
*/

///
/// The ByteSymbolReader turns a `std::io::Bytes` object into a symbol reader
///
pub struct ByteSymbolReader<Reader: Read> {
    bytes: Bytes<Reader>
}

impl<Reader: Read> ByteSymbolReader<Reader> {
    pub fn new(bytes: Bytes<Reader>) -> ByteSymbolReader<Reader> {
        ByteSymbolReader { bytes: bytes }
    }

    pub fn from(reader: Reader) -> ByteSymbolReader<Reader> {
        Self::new(reader.bytes())
    }
}

impl<Reader: Read> SymbolReader<u8> for ByteSymbolReader<Reader> {
    fn next_symbol(&mut self) -> Option<u8> {
        if let Some(Ok(sym)) = self.bytes.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

//
// Can read from strings
//
impl<'a> SymbolSource<'a, char> for &'a str {
    type SymbolReader = Chars<'a>;

    fn read_symbols(self) -> Self::SymbolReader {
        self.chars()
    }
}

impl<'a> SymbolReader<char> for Chars<'a> {
    fn next_symbol(&mut self) -> Option<char> {
        self.next()
    }
}

///
/// Converts symbol streams to vectors
///
pub trait ReaderToVector<Symbol> {
    /// Reads every symbol in this object and returns a vector
    fn to_vec(&mut self) -> Vec<Symbol>;
}

impl<Symbol, Reader: SymbolReader<Symbol>> ReaderToVector<Symbol> for Reader {
    #[inline]
    fn to_vec(&mut self) -> Vec<Symbol> {
        let mut result = vec![];

        while let Some(symbol) = self.next_symbol() {
            result.push(symbol);
        }

        result
    }
}

///
/// A symbol stream that performs mapping of symbols from a source stream
///
pub struct MappedStream<'a, InputSymbol, MapFunction, Reader>
where Reader: SymbolReader<InputSymbol>+'a {
    /// The source stream
    source_stream: &'a mut Reader,

    /// A function used to map a symbol from the source stream to a symbol in the output stream
    mapping_function: MapFunction,

    // Can't see how to eliminate the input symbol reference due to rust's type system. InputSymbol is used by source_stream, but rust can't see that
    #[allow(dead_code)]
    phantom: PhantomData<InputSymbol>
}

///
/// Provides a way to map symbol streams to streams of other types
///
pub trait MapSymbolReader<Symbol> : SymbolReader<Symbol>+Sized {
    /// Maps symbols in this stream to symbols in a new stream
    fn map_symbols<'a, OutputSymbol, MapFunction>(&'a mut self, mapping_function: MapFunction) -> MappedStream<'a, Symbol, MapFunction, Self>
    where MapFunction: FnMut(Symbol) -> OutputSymbol;
}

impl<Symbol, Reader: SymbolReader<Symbol>> MapSymbolReader<Symbol> for Reader {
    fn map_symbols<'a, OutputSymbol, MapFunction>(&'a mut self, mapping_function: MapFunction) -> MappedStream<'a, Symbol, MapFunction, Self>
    where MapFunction: FnMut(Symbol) -> OutputSymbol {
        MappedStream {
            source_stream:    self,
            mapping_function: mapping_function,
            phantom:          PhantomData
        }
    }
}

impl<'a, InputSymbol, OutputSymbol, MapFunction, Reader: SymbolReader<InputSymbol>+'a> SymbolReader<OutputSymbol> for MappedStream<'a, InputSymbol, MapFunction, Reader>
where MapFunction: FnMut(InputSymbol) -> OutputSymbol {
    fn next_symbol(&mut self) -> Option<OutputSymbol> {
        if let Some(input_symbol) = self.source_stream.next_symbol() {
            Some((self.mapping_function)(input_symbol))
        } else {
            None
        }
    }
}

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

    #[test]
    fn can_read_from_vec() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }

    #[test]
    fn can_convert_to_vec() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();
        let result      = reader.to_vec();

        assert!(result == vec![1, 2, 3]);
    }

    #[test]
    fn can_map_stream() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();
        let result      = reader.map_symbols(|sym| sym+1).to_vec();

        assert!(result == vec![2, 3, 4]);
    }

    #[test]
    fn can_read_from_bytes_reader() {
        let array: [u8; 3] = [1, 2, 3];
        let slice = &array[..];
        let mut reader = ByteSymbolReader::from(slice);

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }

    #[test]
    fn can_read_from_string_reader() {
        let mut reader = "abc".read_symbols();

        assert!(reader.next_symbol() == Some('a'));
        assert!(reader.next_symbol() == Some('b'));
        assert!(reader.next_symbol() == Some('c'));
        assert!(reader.next_symbol() == None);
    }
}
<|endoftext|>


<commit_before>//! Helper functions to parse values of specific attributes

use values::*;
use str::{pop_char, from_chars};
use float::from_str;
use option::map;

export parse_font_size;
export parse_size;
export parse_box_sizing;
export parse_display_type;

fn parse_length(str : &str) -> Option<Length> {
    // TODO: use these once we stop lexing below
    const PTS_PER_INCH: float = 72.0;
    const CM_PER_INCH: float = 2.54;
    const PX_PER_PT: float = 1.0 / 0.75;

    match str {
      s if s.ends_with("in") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * 72.0 * *f)),
      s if s.ends_with("cm") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(*f / 2.54 * 72.0 * 1.0/0.75)),
      s if s.ends_with("mm") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(*f * 0.1 / 2.54 * 72.0 * 1.0/0.75)),
      s if s.ends_with("pt") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * *f)),
      s if s.ends_with("pc") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * 12.0 * *f)),
      s if s.ends_with("px") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(*f)),
      s if s.ends_with("em") => from_str(str.substr(0, str.len() - 2)).map(|f| Em(*f)),
      s if s.ends_with("ex") => from_str(str.substr(0, str.len() - 2)).map(|f| Em(0.5 * *f)),
      _ => None,
    }
}

fn parse_absolute_size(str : &str) -> ParseResult<AbsoluteSize> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"xx-small" => Value(XXSmall),
      ~"x-small" => Value(XSmall),
      ~"small" => Value(Small),
      ~"medium" => Value(Medium),
      ~"large" => Value(Large),
      ~"x-large" => Value(XLarge),
      ~"xx-large" => Value(XXLarge),
      _  => Fail
    }
}

fn parse_position(str: &str) -> ParseResult<CSSPosition> {
    // FIXME: Bad copy
    match str.to_str() {
        ~"static" => Value(PosStatic),
        ~"relative" => Value(PosRelative),
        ~"absolute" => Value(PosAbsolute),
        ~"fixed" => Value(PosFixed),
        _ => Fail
    }
}

fn parse_relative_size(str: &str) -> ParseResult<RelativeSize> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"smaller" => Value(Smaller),
      ~"larger" => Value(Larger),
      _ => Fail
    }
}

fn parse_font_size(_str: &str) -> ParseResult<CSSFontSize> {
    // TODO: complete me
    Value(LengthSize(Px(14.0)))
}

// For width / height, and anything else with the same attribute values
fn parse_box_sizing(str : &str) -> ParseResult<BoxSizing> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"auto" => Value(BoxAuto),
      ~"inherit" => CSSInherit,
        _ => Fail
    }
}

fn parse_display_type(str : &str) -> ParseResult<CSSDisplay> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"inline" => Value(DisplayInline),
      ~"block" => Value(DisplayBlock),
      ~"none" => Value(DisplayNone),
      _ => { #debug["Recieved unknown display value '%s'", str]; Fail }
    }
}

#[cfg(test)]
mod test {
    use css::lexer::spawn_css_lexer_from_string;
    use css::parser::build_stylesheet;
    use newcss::values::{Stylesheet, Element, FontSize, Width, Height};

    // TODO: use helper methods to create test values

    #[test]
    fn should_match_font_sizes() {
        let input = ~"* {font-size:12px; font-size:inherit; font-size:200%; font-size:x-small}";
        let token_port = spawn_css_lexer_from_string(move input);
        let _actual_rule = build_stylesheet(move token_port);
        let _expected_rule : Stylesheet = ~[~(~[~Element(~"*", ~[])],
                                             ~[FontSize(Specified(LengthSize(Px(12.0)))),
                                               FontSize(Specified(PercentSize(100.0))),
                                               FontSize(Specified(PercentSize(200.0))),
                                               FontSize(Specified(LengthSize(Px(12.0))))])];

        // TODO: fix me once StyleDeclaration is a trait, not an enum
        //assert actual_rule == expected_rule;
    }

    #[test]
    fn should_match_width_height() {
        let input = ~"* {width:20%; height:auto; width:20px; width:3in; height:70px; height:30px}";
        let token_port = spawn_css_lexer_from_string(move input);
        let _actual_rule = build_stylesheet(move token_port);
        let _expected_rule : Stylesheet = ~[~(~[~Element(~"*", ~[])],
                                             ~[Width(Specified(BoxPercent(20.0))),
                                               Height(Specified(BoxAuto)),
                                               Width(Specified(BoxLength(Px(20.0)))),
                                               Width(Specified(BoxLength(Px(216.0)))),
                                               Height(Specified(BoxLength(Px(70.0)))),
                                               Height(Specified(BoxLength(Px(30.0))))])];

        // TODO: fix me once StyleDeclaration is a trait, not an enum
        //assert actual_rule == expected_rule;
    }
}
<commit_msg>Fix tests<commit_after>//! Helper functions to parse values of specific attributes

use values::*;
use str::{pop_char, from_chars};
use float::from_str;
use option::map;

export parse_font_size;
export parse_size;
export parse_box_sizing;
export parse_display_type;

fn parse_length(str : &str) -> Option<Length> {
    // TODO: use these once we stop lexing below
    const PTS_PER_INCH: float = 72.0;
    const CM_PER_INCH: float = 2.54;
    const PX_PER_PT: float = 1.0 / 0.75;

    match str {
      s if s.ends_with("in") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * 72.0 * *f)),
      s if s.ends_with("cm") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(*f / 2.54 * 72.0 * 1.0/0.75)),
      s if s.ends_with("mm") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(*f * 0.1 / 2.54 * 72.0 * 1.0/0.75)),
      s if s.ends_with("pt") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * *f)),
      s if s.ends_with("pc") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * 12.0 * *f)),
      s if s.ends_with("px") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(*f)),
      s if s.ends_with("em") => from_str(str.substr(0, str.len() - 2)).map(|f| Em(*f)),
      s if s.ends_with("ex") => from_str(str.substr(0, str.len() - 2)).map(|f| Em(0.5 * *f)),
      _ => None,
    }
}

fn parse_absolute_size(str : &str) -> ParseResult<AbsoluteSize> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"xx-small" => Value(XXSmall),
      ~"x-small" => Value(XSmall),
      ~"small" => Value(Small),
      ~"medium" => Value(Medium),
      ~"large" => Value(Large),
      ~"x-large" => Value(XLarge),
      ~"xx-large" => Value(XXLarge),
      _  => Fail
    }
}

fn parse_position(str: &str) -> ParseResult<CSSPosition> {
    // FIXME: Bad copy
    match str.to_str() {
        ~"static" => Value(PosStatic),
        ~"relative" => Value(PosRelative),
        ~"absolute" => Value(PosAbsolute),
        ~"fixed" => Value(PosFixed),
        _ => Fail
    }
}

fn parse_relative_size(str: &str) -> ParseResult<RelativeSize> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"smaller" => Value(Smaller),
      ~"larger" => Value(Larger),
      _ => Fail
    }
}

fn parse_font_size(_str: &str) -> ParseResult<CSSFontSize> {
    // TODO: complete me
    Value(LengthSize(Px(14.0)))
}

// For width / height, and anything else with the same attribute values
fn parse_box_sizing(str : &str) -> ParseResult<BoxSizing> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"auto" => Value(BoxAuto),
      ~"inherit" => CSSInherit,
        _ => Fail
    }
}

fn parse_display_type(str : &str) -> ParseResult<CSSDisplay> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"inline" => Value(DisplayInline),
      ~"block" => Value(DisplayBlock),
      ~"none" => Value(DisplayNone),
      _ => { #debug["Recieved unknown display value '%s'", str]; Fail }
    }
}

#[cfg(test)]
mod test {
    use lexer::spawn_css_lexer_from_string;
    use parser::build_stylesheet;
    use values::{Stylesheet, Element, FontSize, Width, Height};

    // TODO: use helper methods to create test values

    #[test]
    fn should_match_font_sizes() {
        let input = ~"* {font-size:12px; font-size:inherit; font-size:200%; font-size:x-small}";
        let token_port = spawn_css_lexer_from_string(move input);
        let _actual_rule = build_stylesheet(move token_port);
        let _expected_rule : Stylesheet = ~[~(~[~Element(~"*", ~[])],
                                             ~[FontSize(Specified(LengthSize(Px(12.0)))),
                                               FontSize(Specified(PercentSize(100.0))),
                                               FontSize(Specified(PercentSize(200.0))),
                                               FontSize(Specified(LengthSize(Px(12.0))))])];

        // TODO: fix me once StyleDeclaration is a trait, not an enum
        //assert actual_rule == expected_rule;
    }

    #[test]
    fn should_match_width_height() {
        let input = ~"* {width:20%; height:auto; width:20px; width:3in; height:70px; height:30px}";
        let token_port = spawn_css_lexer_from_string(move input);
        let _actual_rule = build_stylesheet(move token_port);
        let _expected_rule : Stylesheet = ~[~(~[~Element(~"*", ~[])],
                                             ~[Width(Specified(BoxPercent(20.0))),
                                               Height(Specified(BoxAuto)),
                                               Width(Specified(BoxLength(Px(20.0)))),
                                               Width(Specified(BoxLength(Px(216.0)))),
                                               Height(Specified(BoxLength(Px(70.0)))),
                                               Height(Specified(BoxLength(Px(30.0))))])];

        // TODO: fix me once StyleDeclaration is a trait, not an enum
        //assert actual_rule == expected_rule;
    }
}
<|endoftext|>


<commit_before>//! Reading proc-macro rustc version information from binary data

use std::{
    fs::File,
    io::{self, Read},
};

use memmap2::Mmap;
use object::read::{File as BinaryFile, Object, ObjectSection};
use paths::AbsPath;
use snap::read::FrameDecoder as SnapDecoder;

#[derive(Debug)]
pub struct RustCInfo {
    pub version: (usize, usize, usize),
    pub channel: String,
    pub commit: Option<String>,
    pub date: Option<String>,
}

/// Read rustc dylib information
pub fn read_dylib_info(dylib_path: &AbsPath) -> io::Result<RustCInfo> {
    macro_rules! err {
        ($e:literal) => {
            io::Error::new(io::ErrorKind::InvalidData, $e)
        };
    }

    let ver_str = read_version(dylib_path)?;
    let mut items = ver_str.split_whitespace();
    let tag = items.next().ok_or_else(|| err!("version format error"))?;
    if tag != "rustc" {
        return Err(err!("version format error (No rustc tag)"));
    }

    let version_part = items.next().ok_or_else(|| err!("no version string"))?;
    let mut version_parts = version_part.split('-');
    let version = version_parts.next().ok_or_else(|| err!("no version"))?;
    let channel = version_parts.next().unwrap_or_default().to_string();

    let commit = match items.next() {
        Some(commit) => {
            match commit.len() {
                0 => None,
                _ => Some(commit[1..].to_string() /* remove ( */),
            }
        }
        None => None,
    };
    let date = match items.next() {
        Some(date) => {
            match date.len() {
                0 => None,
                _ => Some(date[0..date.len() - 2].to_string() /* remove ) */),
            }
        }
        None => None,
    };

    let version_numbers = version
        .split('.')
        .map(|it| it.parse::<usize>())
        .collect::<Result<Vec<_>, _>>()
        .map_err(|_| err!("version number error"))?;

    if version_numbers.len() != 3 {
        return Err(err!("version number format error"));
    }
    let version = (version_numbers[0], version_numbers[1], version_numbers[2]);

    Ok(RustCInfo { version, channel, commit, date })
}

/// This is used inside read_version() to locate the ".rustc" section
/// from a proc macro crate's binary file.
fn read_section<'a>(dylib_binary: &'a [u8], section_name: &str) -> io::Result<&'a [u8]> {
    BinaryFile::parse(dylib_binary)
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?
        .section_by_name(section_name)
        .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "section read error"))?
        .data()
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}

/// Check the version of rustc that was used to compile a proc macro crate's
///
/// binary file.
/// A proc macro crate binary's ".rustc" section has following byte layout:
/// * [b'r',b'u',b's',b't',0,0,0,5] is the first 8 bytes
/// * ff060000 734e6150 is followed, it's the snappy format magic bytes,
///   means bytes from here(including this sequence) are compressed in
///   snappy compression format. Version info is inside here, so decompress
///   this.
/// The bytes you get after decompressing the snappy format portion has
/// following layout:
/// * [b'r',b'u',b's',b't',0,0,0,5] is the first 8 bytes(again)
/// * [crate root bytes] next 4 bytes is to store crate root position,
///   according to rustc's source code comment
/// * [length byte] next 1 byte tells us how many bytes we should read next
///   for the version string's utf8 bytes
/// * [version string bytes encoded in utf8] <- GET THIS BOI
/// * [some more bytes that we don really care but still there] :-)
/// Check this issue for more about the bytes layout:
/// <https://github.com/rust-analyzer/rust-analyzer/issues/6174>
fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
    let dylib_file = File::open(dylib_path)?;
    let dylib_mmaped = unsafe { Mmap::map(&dylib_file) }?;

    let dot_rustc = read_section(&dylib_mmaped, ".rustc")?;

    let header = &dot_rustc[..8];
    const EXPECTED_HEADER: [u8; 8] = [b'r', b'u', b's', b't', 0, 0, 0, 5];
    // check if header is valid
    if header != EXPECTED_HEADER {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!("only metadata version 5 is supported, section header was: {:?}", header),
        ));
    }

    let snappy_portion = &dot_rustc[8..];

    let mut snappy_decoder = SnapDecoder::new(snappy_portion);

    // the bytes before version string bytes, so this basically is:
    // 8 bytes for [b'r',b'u',b's',b't',0,0,0,5]
    // 4 bytes for [crate root bytes]
    // 1 byte for length of version string
    // so 13 bytes in total, and we should check the 13th byte
    // to know the length
    let mut bytes_before_version = [0u8; 13];
    snappy_decoder.read_exact(&mut bytes_before_version)?;
    let length = bytes_before_version[12]; // what? can't use -1 indexing?

    let mut version_string_utf8 = vec![0u8; length as usize];
    snappy_decoder.read_exact(&mut version_string_utf8)?;
    let version_string = String::from_utf8(version_string_utf8);
    version_string.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}
<commit_msg>Add support for v6 macro metadata format<commit_after>//! Reading proc-macro rustc version information from binary data

use std::{
    fs::File,
    io::{self, Read},
};

use memmap2::Mmap;
use object::read::{File as BinaryFile, Object, ObjectSection};
use paths::AbsPath;
use snap::read::FrameDecoder as SnapDecoder;

#[derive(Debug)]
pub struct RustCInfo {
    pub version: (usize, usize, usize),
    pub channel: String,
    pub commit: Option<String>,
    pub date: Option<String>,
}

/// Read rustc dylib information
pub fn read_dylib_info(dylib_path: &AbsPath) -> io::Result<RustCInfo> {
    macro_rules! err {
        ($e:literal) => {
            io::Error::new(io::ErrorKind::InvalidData, $e)
        };
    }

    let ver_str = read_version(dylib_path)?;
    let mut items = ver_str.split_whitespace();
    let tag = items.next().ok_or_else(|| err!("version format error"))?;
    if tag != "rustc" {
        return Err(err!("version format error (No rustc tag)"));
    }

    let version_part = items.next().ok_or_else(|| err!("no version string"))?;
    let mut version_parts = version_part.split('-');
    let version = version_parts.next().ok_or_else(|| err!("no version"))?;
    let channel = version_parts.next().unwrap_or_default().to_string();

    let commit = match items.next() {
        Some(commit) => {
            match commit.len() {
                0 => None,
                _ => Some(commit[1..].to_string() /* remove ( */),
            }
        }
        None => None,
    };
    let date = match items.next() {
        Some(date) => {
            match date.len() {
                0 => None,
                _ => Some(date[0..date.len() - 2].to_string() /* remove ) */),
            }
        }
        None => None,
    };

    let version_numbers = version
        .split('.')
        .map(|it| it.parse::<usize>())
        .collect::<Result<Vec<_>, _>>()
        .map_err(|_| err!("version number error"))?;

    if version_numbers.len() != 3 {
        return Err(err!("version number format error"));
    }
    let version = (version_numbers[0], version_numbers[1], version_numbers[2]);

    Ok(RustCInfo { version, channel, commit, date })
}

/// This is used inside read_version() to locate the ".rustc" section
/// from a proc macro crate's binary file.
fn read_section<'a>(dylib_binary: &'a [u8], section_name: &str) -> io::Result<&'a [u8]> {
    BinaryFile::parse(dylib_binary)
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?
        .section_by_name(section_name)
        .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "section read error"))?
        .data()
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}

/// Check the version of rustc that was used to compile a proc macro crate's
///
/// binary file.
/// A proc macro crate binary's ".rustc" section has following byte layout:
/// * [b'r',b'u',b's',b't',0,0,0,5] is the first 8 bytes
/// * ff060000 734e6150 is followed, it's the snappy format magic bytes,
///   means bytes from here(including this sequence) are compressed in
///   snappy compression format. Version info is inside here, so decompress
///   this.
/// The bytes you get after decompressing the snappy format portion has
/// following layout:
/// * [b'r',b'u',b's',b't',0,0,0,5] is the first 8 bytes(again)
/// * [crate root bytes] next 4 bytes is to store crate root position,
///   according to rustc's source code comment
/// * [length byte] next 1 byte tells us how many bytes we should read next
///   for the version string's utf8 bytes
/// * [version string bytes encoded in utf8] <- GET THIS BOI
/// * [some more bytes that we don't really care but about still there] :-)
/// Check this issue for more about the bytes layout:
/// <https://github.com/rust-analyzer/rust-analyzer/issues/6174>
fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
    let dylib_file = File::open(dylib_path)?;
    let dylib_mmaped = unsafe { Mmap::map(&dylib_file) }?;

    let dot_rustc = read_section(&dylib_mmaped, ".rustc")?;

    // check if magic is valid
    if &dot_rustc[0..4] != b"rust" {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!("unknown metadata magic, expected `rust`, found `{:?}`", &dot_rustc[0..4]),
        ));
    }
    let version = u32::from_be_bytes([dot_rustc[4], dot_rustc[5], dot_rustc[6], dot_rustc[7]]);
    // Last supported version is:
    // https://github.com/rust-lang/rust/commit/0696e79f2740ad89309269b460579e548a5cd632
    match version {
        5 | 6 => {}
        _ => {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!("unsupported metadata version {}", version),
            ));
        }
    }

    let snappy_portion = &dot_rustc[8..];

    let mut snappy_decoder = SnapDecoder::new(snappy_portion);

    // the bytes before version string bytes, so this basically is:
    // 8 bytes for [b'r',b'u',b's',b't',0,0,0,5]
    // 4 bytes for [crate root bytes]
    // 1 byte for length of version string
    // so 13 bytes in total, and we should check the 13th byte
    // to know the length
    let mut bytes_before_version = [0u8; 13];
    snappy_decoder.read_exact(&mut bytes_before_version)?;
    let length = bytes_before_version[12];

    let mut version_string_utf8 = vec![0u8; length as usize];
    snappy_decoder.read_exact(&mut version_string_utf8)?;
    let version_string = String::from_utf8(version_string_utf8);
    version_string.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}
<|endoftext|>