<commit_before>use crate::io::ErrorKind;
use std::io::{self, BufWriter, Write};
use std::process::exit;
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
use std::thread::{self, JoinHandle};

use crate::{constants::*, refiner};
use regex::Regex;

const HUNK_HEADER: &str = "\x1b[36m"; // Cyan

lazy_static! {
    static ref STATIC_HEADER_PREFIXES: Vec<(&'static str, &'static str)> = vec![
        ("diff ", BOLD),
        ("index ", BOLD),
        ("--- ", BOLD),
        ("+++ ", BOLD),
        ("@@ ", HUNK_HEADER),
    ];
    static ref ANSI_COLOR_REGEX: Regex = Regex::new("\x1b[^m]*m").unwrap();
}

#[must_use]
fn get_fixed_highlight(line: &str) -> &str {
    for static_header_prefix in STATIC_HEADER_PREFIXES.iter() {
        let prefix = static_header_prefix.0;
        if line.starts_with(prefix) {
            return static_header_prefix.1;
        }
    }

    return "";
}

fn print<W: io::Write + Send>(stream: &mut BufWriter<W>, text: &str) {
    if let Err(error) = stream.write_all(text.as_bytes()) {
        if error.kind() == ErrorKind::BrokenPipe {
            // This is fine, somebody probably just quit their pager before it
            // was done reading our output.
            exit(0);
        }

        panic!("Error writing diff to pager: {:?}", error);
    }
}

pub struct LineCollector {
    old_text: String,
    new_text: String,
    plain_text: String,
    consumer_thread: Option<JoinHandle<()>>,
    queue_putter: SyncSender<String>,
}

impl Drop for LineCollector {
    fn drop(&mut self) {
        // Flush any outstanding lines. This can be done in any order, at most
        // one of them is going to do anything anyway.
        self.drain_oldnew();
        self.drain_plain();

        // Tell the consumer thread to drain and quit. Sending an empty string
        // like this is the secret handshake for requesting a shutdown.
        self.queue_putter.send("".to_string()).unwrap();

        // Wait for the consumer thread to finish
        // https://stackoverflow.com/q/57670145/473672
        self.consumer_thread.take().map(JoinHandle::join);
    }
}

impl LineCollector {
    pub fn new<W: io::Write + Send + 'static>(output: W) -> LineCollector {
        // Allocate a queue where we can push our futures to the consumer thread
        //
        // FIXME: The queue should be bounded to 2x the number of logical CPUs.
        // 1x for the entries that need CPU time for diffing, and another 1x
        // that just contain text to print and won't need any processing time.
        let (queue_putter, queue_getter): (SyncSender<String>, Receiver<String>) = sync_channel(16);

        // This thread takes futures and prints their results
        let consumer = thread::spawn(move || {
            let mut output = BufWriter::new(output);

            loop {
                if let Ok(print_me) = queue_getter.recv() {
                    if print_me.is_empty() {
                        // Secret handshake received, done!
                        break;
                    }
                    print(&mut output, &print_me);
                }
            }
        });

        return LineCollector {
            old_text: String::from(""),
            new_text: String::from(""),
            plain_text: String::from(""),
            consumer_thread: Some(consumer),
            queue_putter,
        };
    }

    fn drain_oldnew(&mut self) {
        if self.old_text.is_empty() && self.new_text.is_empty() {
            return;
        }

        // FIXME: This should be enqueued as a future containing the refiner::format() call
        let mut output = String::new();
        for line in refiner::format(&self.old_text, &self.new_text) {
            output.push_str(&line);
            output.push('\n');
        }
        self.queue_putter.send(output).unwrap();

        self.old_text.clear();
        self.new_text.clear();
    }

    fn drain_plain(&mut self) {
        if self.plain_text.is_empty() {
            return;
        }

        // FIXME: Create an already-resolved future returning this text, then
        // store that future in our queue.
        self.queue_putter
            .send(String::from(&self.plain_text))
            .unwrap();

        self.plain_text.clear();
    }

    fn consume_plain_line(&mut self, line: &str) {
        self.drain_oldnew();
        self.plain_text.push_str(line);
        self.plain_text.push('\n');
    }

    fn consume_old_line(&mut self, line: &str) {
        self.drain_plain();
        self.old_text.push_str(&line[1..]);
        self.old_text.push('\n');
    }

    fn consume_new_line(&mut self, line: &str) {
        self.drain_plain();
        self.new_text.push_str(&line[1..]);
        self.new_text.push('\n');
    }

    fn consume_no_eof_newline_marker(&mut self) {
        if !self.new_text.is_empty() {
            // New section comes after old, so if we get in here it's a new
            // section that doesn't end in a newline. Remove its trailing
            // newline.
            assert!(self.new_text.pop().unwrap() == '\n');
            return;
        }

        if !self.old_text.is_empty() {
            // Old text doesn't end in a newline, remove its trailing newline
            assert!(self.old_text.pop().unwrap() == '\n');
            return;
        }

        // It's a piece of unchanged text that doesn't end in a newline, just
        // consume the colorized marker as plain text
        self.consume_plain_line(&format!(
            "{}{}{}",
            NO_EOF_NEWLINE_COLOR, &NO_EOF_NEWLINE_MARKER, NORMAL
        ))
    }

    pub fn consume_line(&mut self, line: String) {
        // Strip out incoming ANSI formatting. This enables us to highlight
        // already-colored input.
        let line = ANSI_COLOR_REGEX.replace_all(&line, "");

        let fixed_highlight = get_fixed_highlight(&line);
        if !fixed_highlight.is_empty() {
            self.consume_plain_line(&format!("{}{}{}", fixed_highlight, line, NORMAL));
            return;
        }

        if line.is_empty() {
            self.consume_plain_line("");
            return;
        }

        if line.starts_with('-') {
            self.consume_old_line(&line);
            return;
        }

        if line.starts_with('+') {
            self.consume_new_line(&line);
            return;
        }

        if line == NO_EOF_NEWLINE_MARKER {
            self.consume_no_eof_newline_marker();
            return;
        }

        self.consume_plain_line(&line);
    }
}
<commit_msg>Pass string containers around, not just strings<commit_after>use crate::io::ErrorKind;
use std::io::{self, BufWriter, Write};
use std::process::exit;
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
use std::thread::{self, JoinHandle};

use crate::{constants::*, refiner};
use regex::Regex;

const HUNK_HEADER: &str = "\x1b[36m"; // Cyan

lazy_static! {
    static ref STATIC_HEADER_PREFIXES: Vec<(&'static str, &'static str)> = vec![
        ("diff ", BOLD),
        ("index ", BOLD),
        ("--- ", BOLD),
        ("+++ ", BOLD),
        ("@@ ", HUNK_HEADER),
    ];
    static ref ANSI_COLOR_REGEX: Regex = Regex::new("\x1b[^m]*m").unwrap();
}

#[must_use]
fn get_fixed_highlight(line: &str) -> &str {
    for static_header_prefix in STATIC_HEADER_PREFIXES.iter() {
        let prefix = static_header_prefix.0;
        if line.starts_with(prefix) {
            return static_header_prefix.1;
        }
    }

    return "";
}

fn print<W: io::Write + Send>(stream: &mut BufWriter<W>, text: &str) {
    if let Err(error) = stream.write_all(text.as_bytes()) {
        if error.kind() == ErrorKind::BrokenPipe {
            // This is fine, somebody probably just quit their pager before it
            // was done reading our output.
            exit(0);
        }

        panic!("Error writing diff to pager: {:?}", error);
    }
}

// FIXME: Don't call this "Stringinator"!!
struct Stringinator {
    // FIXME: This should be an Option<String>, which only contains the result
    // if the computation is done
    result: String,
}

impl Stringinator {
    pub fn from_string(result: String) -> Stringinator {
        return Stringinator { result };
    }

    pub fn is_empty(&self) -> bool {
        return self.result.is_empty();
    }
}

pub struct LineCollector {
    old_text: String,
    new_text: String,
    plain_text: String,
    consumer_thread: Option<JoinHandle<()>>,

    // FIXME: I'd rather have had a SyncSender of some trait here. That would
    // enable us to have two separate result implementations, one which just
    // returns a string and another that does a background computation first.
    // But I failed to figure out how when I tried, more Googling needed!
    queue_putter: SyncSender<Stringinator>,
}

impl Drop for LineCollector {
    fn drop(&mut self) {
        // Flush any outstanding lines. This can be done in any order, at most
        // one of them is going to do anything anyway.
        self.drain_oldnew();
        self.drain_plain();

        // Tell the consumer thread to drain and quit. Sending an empty string
        // like this is the secret handshake for requesting a shutdown.
        self.queue_putter
            .send(Stringinator::from_string("".to_string()))
            .unwrap();

        // Wait for the consumer thread to finish
        // https://stackoverflow.com/q/57670145/473672
        self.consumer_thread.take().map(JoinHandle::join);
    }
}

impl LineCollector {
    pub fn new<W: io::Write + Send + 'static>(output: W) -> LineCollector {
        // Allocate a queue where we can push our futures to the consumer thread
        //
        // FIXME: The queue should be bounded to 2x the number of logical CPUs.
        // 1x for the entries that need CPU time for diffing, and another 1x
        // that just contain text to print and won't need any processing time.
        let (queue_putter, queue_getter): (SyncSender<Stringinator>, Receiver<Stringinator>) =
            sync_channel(16);

        // This thread takes futures and prints their results
        let consumer = thread::spawn(move || {
            let mut output = BufWriter::new(output);

            loop {
                if let Ok(print_me) = queue_getter.recv() {
                    if print_me.is_empty() {
                        // Secret handshake received, done!
                        break;
                    }
                    print(&mut output, &print_me.result);
                }
            }
        });

        return LineCollector {
            old_text: String::from(""),
            new_text: String::from(""),
            plain_text: String::from(""),
            consumer_thread: Some(consumer),
            queue_putter,
        };
    }

    fn drain_oldnew(&mut self) {
        if self.old_text.is_empty() && self.new_text.is_empty() {
            return;
        }

        // FIXME: This should be enqueued as a future containing the refiner::format() call
        let mut output = String::new();
        for line in refiner::format(&self.old_text, &self.new_text) {
            output.push_str(&line);
            output.push('\n');
        }
        self.queue_putter
            .send(Stringinator::from_string(output))
            .unwrap();

        self.old_text.clear();
        self.new_text.clear();
    }

    fn drain_plain(&mut self) {
        if self.plain_text.is_empty() {
            return;
        }

        // FIXME: Create an already-resolved future returning this text, then
        // store that future in our queue.
        self.queue_putter
            .send(Stringinator::from_string(String::from(&self.plain_text)))
            .unwrap();

        self.plain_text.clear();
    }

    fn consume_plain_line(&mut self, line: &str) {
        self.drain_oldnew();
        self.plain_text.push_str(line);
        self.plain_text.push('\n');
    }

    fn consume_old_line(&mut self, line: &str) {
        self.drain_plain();
        self.old_text.push_str(&line[1..]);
        self.old_text.push('\n');
    }

    fn consume_new_line(&mut self, line: &str) {
        self.drain_plain();
        self.new_text.push_str(&line[1..]);
        self.new_text.push('\n');
    }

    fn consume_no_eof_newline_marker(&mut self) {
        if !self.new_text.is_empty() {
            // New section comes after old, so if we get in here it's a new
            // section that doesn't end in a newline. Remove its trailing
            // newline.
            assert!(self.new_text.pop().unwrap() == '\n');
            return;
        }

        if !self.old_text.is_empty() {
            // Old text doesn't end in a newline, remove its trailing newline
            assert!(self.old_text.pop().unwrap() == '\n');
            return;
        }

        // It's a piece of unchanged text that doesn't end in a newline, just
        // consume the colorized marker as plain text
        self.consume_plain_line(&format!(
            "{}{}{}",
            NO_EOF_NEWLINE_COLOR, &NO_EOF_NEWLINE_MARKER, NORMAL
        ))
    }

    pub fn consume_line(&mut self, line: String) {
        // Strip out incoming ANSI formatting. This enables us to highlight
        // already-colored input.
        let line = ANSI_COLOR_REGEX.replace_all(&line, "");

        let fixed_highlight = get_fixed_highlight(&line);
        if !fixed_highlight.is_empty() {
            self.consume_plain_line(&format!("{}{}{}", fixed_highlight, line, NORMAL));
            return;
        }

        if line.is_empty() {
            self.consume_plain_line("");
            return;
        }

        if line.starts_with('-') {
            self.consume_old_line(&line);
            return;
        }

        if line.starts_with('+') {
            self.consume_new_line(&line);
            return;
        }

        if line == NO_EOF_NEWLINE_MARKER {
            self.consume_no_eof_newline_marker();
            return;
        }

        self.consume_plain_line(&line);
    }
}
<|endoftext|>


<commit_before>use std::fmt::Write as fmt_Write;
use std::fmt;

use Message;
use reflect::ReflectFieldRef;
use reflect::ReflectValueRef;
use reflect::ReflectRepeatedRef;
use json::float;
use std::f32;
use std::f64;
use reflect::ReflectMapRef;

struct Printer {
    buf: String,
}

trait JsonFloat : fmt::Display {
    fn is_nan(&self) -> bool;
    fn is_pos_infinity(&self) -> bool;
    fn is_neg_infinity(&self) -> bool;

    fn write_to_json(&self, w: &mut String) -> fmt::Result {
        if self.is_nan() {
            write!(w, "{}", float::PROTOBUF_JSON_NAN)
        } else if self.is_pos_infinity() {
            write!(w, "{}", float::PROTOBUF_JSON_INF)
        } else if self.is_neg_infinity() {
            write!(w, "{}", float::PROTOBUF_JSON_MINUS_INF)
        } else {
            write!(w, "{}", self)
        }
    }
}

impl JsonFloat for f32 {
    fn is_nan(&self) -> bool {
        f32::is_nan(*self)
    }

    fn is_pos_infinity(&self) -> bool {
        f32::is_infinite(*self) && self > &0.0
    }

    fn is_neg_infinity(&self) -> bool {
        f32::is_infinite(*self) && self < &0.0
    }
}

impl JsonFloat for f64 {
    fn is_nan(&self) -> bool {
        f64::is_nan(*self)
    }

    fn is_pos_infinity(&self) -> bool {
        f64::is_infinite(*self) && self > &0.0
    }

    fn is_neg_infinity(&self) -> bool {
        f64::is_infinite(*self) && self < &0.0
    }
}

impl Printer {
    fn print_comma_but_first(&mut self, first: &mut bool) -> fmt::Result {
        if *first {
            *first = false;
            Ok(())
        } else {
            write!(self.buf, ", ")
        }
    }

    fn print_value(&mut self, value: &ReflectValueRef) -> fmt::Result {
        match value {
            ReflectValueRef::U32(v) => write!(self.buf, "{}", v),
            ReflectValueRef::U64(v) => write!(self.buf, "{}", v),
            ReflectValueRef::I32(v) => write!(self.buf, "{}", v),
            ReflectValueRef::I64(v) => write!(self.buf, "{}", v),
            ReflectValueRef::F32(v) => v.write_to_json(&mut self.buf),
            ReflectValueRef::F64(v) => v.write_to_json(&mut self.buf),
            ReflectValueRef::Bool(v) => write!(self.buf, "{}", v),
            ReflectValueRef::String(_v) => unimplemented!(),
            ReflectValueRef::Bytes(_v) => unimplemented!(),
            // TODO: option to output JSON as number
            ReflectValueRef::Enum(v) => write!(self.buf, "\"{}\"", v.name()),
            ReflectValueRef::Message(v) => self.print_message(*v),
        }
    }

    fn print_repeated(&mut self, _repeated: &ReflectRepeatedRef) -> fmt::Result {
        unimplemented!()
    }

    fn print_map(&mut self, _map: &ReflectMapRef) -> fmt::Result {
        unimplemented!()
    }

    fn print_message(&mut self, message: &Message) -> fmt::Result {
        let descriptor = message.descriptor();

        write!(self.buf, "{{")?;

        let mut first = true;

        for field in descriptor.fields() {
            match field.get_reflect(message) {
                ReflectFieldRef::Optional(None) => {}
                ReflectFieldRef::Optional(Some(v)) => {
                    self.print_comma_but_first(&mut first)?;
                    write!(self.buf, "{}: ", field.json_name())?;
                    self.print_value(&v)?;
                }
                ReflectFieldRef::Repeated(v) => {
                    write!(self.buf, "{}: ", field.json_name())?;
                    self.print_repeated(&v)?;
                }
                ReflectFieldRef::Map(v) => {
                    write!(self.buf, "{}: ", field.json_name())?;
                    self.print_map(&v)?;
                }
            }
        }

        write!(self.buf, "}}")?;
        Ok(())
    }
}

pub fn print_to_string(message: &Message) -> String {
    let mut printer = Printer {
        buf: String::new()
    };
    printer.print_message(message).unwrap();
    printer.buf
}
<commit_msg>Working on JSON<commit_after>use std::fmt::Write as fmt_Write;
use std::fmt;

use Message;
use reflect::ReflectFieldRef;
use reflect::ReflectValueRef;
use reflect::ReflectRepeatedRef;
use json::float;
use std::f32;
use std::f64;
use reflect::ReflectMapRef;

struct Printer {
    buf: String,
}

trait JsonFloat : fmt::Display {
    fn is_nan(&self) -> bool;
    fn is_pos_infinity(&self) -> bool;
    fn is_neg_infinity(&self) -> bool;

    fn write_to_json(&self, w: &mut String) -> fmt::Result {
        if self.is_nan() {
            write!(w, "{}", float::PROTOBUF_JSON_NAN)
        } else if self.is_pos_infinity() {
            write!(w, "{}", float::PROTOBUF_JSON_INF)
        } else if self.is_neg_infinity() {
            write!(w, "{}", float::PROTOBUF_JSON_MINUS_INF)
        } else {
            write!(w, "{}", self)
        }
    }
}

impl JsonFloat for f32 {
    fn is_nan(&self) -> bool {
        f32::is_nan(*self)
    }

    fn is_pos_infinity(&self) -> bool {
        f32::is_infinite(*self) && self > &0.0
    }

    fn is_neg_infinity(&self) -> bool {
        f32::is_infinite(*self) && self < &0.0
    }
}

impl JsonFloat for f64 {
    fn is_nan(&self) -> bool {
        f64::is_nan(*self)
    }

    fn is_pos_infinity(&self) -> bool {
        f64::is_infinite(*self) && self > &0.0
    }

    fn is_neg_infinity(&self) -> bool {
        f64::is_infinite(*self) && self < &0.0
    }
}

impl Printer {
    fn print_comma_but_first(&mut self, first: &mut bool) -> fmt::Result {
        if *first {
            *first = false;
            Ok(())
        } else {
            write!(self.buf, ", ")
        }
    }

    fn print_value(&mut self, value: &ReflectValueRef) -> fmt::Result {
        match value {
            ReflectValueRef::U32(v) => write!(self.buf, "{}", v),
            ReflectValueRef::U64(v) => write!(self.buf, "{}", v),
            ReflectValueRef::I32(v) => write!(self.buf, "{}", v),
            ReflectValueRef::I64(v) => write!(self.buf, "{}", v),
            ReflectValueRef::F32(v) => v.write_to_json(&mut self.buf),
            ReflectValueRef::F64(v) => v.write_to_json(&mut self.buf),
            ReflectValueRef::Bool(v) => write!(self.buf, "{}", v),
            ReflectValueRef::String(_v) => unimplemented!(),
            ReflectValueRef::Bytes(_v) => unimplemented!(),
            // TODO: option to output JSON as number
            ReflectValueRef::Enum(v) => write!(self.buf, "\"{}\"", v.name()),
            ReflectValueRef::Message(v) => self.print_message(*v),
        }
    }

    fn print_repeated(&mut self, repeated: &ReflectRepeatedRef) -> fmt::Result {
        write!(self.buf, "[")?;
        for (i, item) in repeated.into_iter().enumerate() {
            if i != 0 {
                write!(self.buf, ", ")?;
            }
            self.print_value(&item)?;
        }
        write!(self.buf, "]")?;
        Ok(())
    }

    fn print_map(&mut self, map: &ReflectMapRef) -> fmt::Result {
        write!(self.buf, "{{")?;
        for (i, (_k, _v)) in map.into_iter().enumerate() {
            if i != 0 {
                write!(self.buf, ", ")?;
            }
            unimplemented!();
        }
        write!(self.buf, "}}")?;
        Ok(())
    }

    fn print_message(&mut self, message: &Message) -> fmt::Result {
        let descriptor = message.descriptor();

        write!(self.buf, "{{")?;

        let mut first = true;

        for field in descriptor.fields() {
            match field.get_reflect(message) {
                ReflectFieldRef::Optional(None) => {}
                ReflectFieldRef::Optional(Some(v)) => {
                    self.print_comma_but_first(&mut first)?;
                    write!(self.buf, "{}: ", field.json_name())?;
                    self.print_value(&v)?;
                }
                ReflectFieldRef::Repeated(v) => {
                    write!(self.buf, "{}: ", field.json_name())?;
                    self.print_repeated(&v)?;
                }
                ReflectFieldRef::Map(v) => {
                    write!(self.buf, "{}: ", field.json_name())?;
                    self.print_map(&v)?;
                }
            }
        }

        write!(self.buf, "}}")?;
        Ok(())
    }
}

pub fn print_to_string(message: &Message) -> String {
    let mut printer = Printer {
        buf: String::new()
    };
    printer.print_message(message).unwrap();
    printer.buf
}
<|endoftext|>


<commit_before>use nom::{IResult, Consumer, ConsumerState};
use metadata::parser::{header, block_data};

use std::collections::HashMap;

/// Data associated with a single metadata block.
#[derive(Debug)]
pub struct Block {
  /// Marks whether the current metadata block is the last.
  pub is_last: bool,
  /// The length, in bytes, of the block being parsed. This does not include
  /// the metadata block header.
  pub length: u32,
  /// Block data containing on of the eight different types of metadata.
  pub data: BlockData,
}

/// General enum that hold all the different metadata block data.
#[derive(Debug, PartialEq, Eq)]
pub enum BlockData {
  /// Information regarding the entire audio stream.
  StreamInfo(StreamInfo),
  /// Block that represents a number of padded bytes.
  Padding(u32),
  /// Data used by third-party applications.
  Application(Application),
  /// Table of multiple points to seek, or skip, to within the FLAC file.
  SeekTable(Vec<SeekPoint>),
  /// Stores human-readable name/value pairs.
  VorbisComment(VorbisComment),
  /// Stores cue information
  CueSheet(CueSheet),
  /// Stores pictures associated with the FLAC file.
  Picture(Picture),
  /// A type of block data that isn't know or doesn't match the type above.
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream
#[derive(Debug, PartialEq, Eq)]
pub struct StreamInfo {
  pub min_block_size: u16,
  pub max_block_size: u16,
  pub min_frame_size: u32,
  pub max_frame_size: u32,
  pub sample_rate: u32,
  pub channels: u8,
  pub bits_per_sample: u8,
  pub total_samples: u64,
  pub md5_sum: [u8; 16],
}

/// Data used by third-party applications.
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  pub id: String,
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file.
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  pub sample_number: u64,
  pub stream_offset: u64,
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs.
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  pub vendor_string: String,
  pub comments: HashMap<String, String>,
}

/// Stores cue information.
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  pub media_catalog_number: String,
  pub lead_in: u64,
  pub is_cd: bool,
  pub tracks: Vec<CueSheetTrack>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  pub offset: u64,
  pub number: u8,
  pub isrc: String,
  pub is_audio: bool,
  pub is_pre_emphasis: bool,
  pub indices: Vec<CueSheetTrackIndex>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  pub offset: u64,
  pub number: u8,
}

/// Stores pictures associated with the FLAC file.
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  pub picture_type: PictureType,
  pub mime_type: String,
  pub description: String,
  pub width: u32,
  pub height: u32,
  pub depth: u32,
  pub colors: u32,
  pub data: Vec<u8>,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  Other,
  FileIconStandard,
  FileIcon,
  FrontCover,
  BackCover,
  LeafletPage,
  Media,
  LeadArtist,
  Artist,
  Conductor,
  Band,
  Composer,
  Lyricist,
  RecordingLocation,
  DuringRecording,
  DuringPerformace,
  VideoScreenCapture,
  Fish,
  Illustration,
  BandLogo,
  PublisherLogo,
}

enum ParserState {
  FLAC,
  Header,
  MetaData,
}

pub struct MetaDataConsumer {
  state: ParserState,
  is_last: bool,
  block_type: u8,
  length: u32,
  pub data: Vec<Block>
}

impl MetaDataConsumer {
  pub fn new() -> MetaDataConsumer {
    MetaDataConsumer {
      state: ParserState::FLAC,
      is_last: false,
      block_type: 127,
      length: 0,
      data: Vec::new(),
    }
  }
}

impl Consumer for MetaDataConsumer {
  fn consume(&mut self, input: &[u8]) -> ConsumerState {
    match self.state {
      ParserState::FLAC     => {
        match tag!(input, "fLaC") {
          IResult::Done(_, _) => {
            self.state = ParserState::Header;
            ConsumerState::Await(4, 4)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      }
      ParserState::Header   => {
        match header(input) {
          IResult::Done(_, data) => {
            let (is_last, block_type, length) = data;

            self.state      = ParserState::MetaData;
            self.is_last    = is_last;
            self.block_type = block_type;
            self.length     = length;

            ConsumerState::Await(4, length as usize)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      },
      ParserState::MetaData => {
        let length = self.length as usize;

        match block_data(input, self.block_type, self.length) {
          IResult::Done(_, data) => {
            self.data.push(Block {
              is_last: self.is_last,
              length: self.length,
              data: data,
            });

            if self.is_last {
              ConsumerState::ConsumerDone
            } else {
              self.state = ParserState::Header;

              ConsumerState::Await(length, 4)
            }
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, length),
        }
      }
    }
  }

  fn failed(&mut self, error_code: u32) {
    println!("Failed with error code: {}", error_code);
  }

  fn end(&mut self) {}
}
<commit_msg>Add documentation for the `StreamInfo` struct<commit_after>use nom::{IResult, Consumer, ConsumerState};
use metadata::parser::{header, block_data};

use std::collections::HashMap;

/// Data associated with a single metadata block.
#[derive(Debug)]
pub struct Block {
  /// Marks whether the current metadata block is the last.
  pub is_last: bool,
  /// The length, in bytes, of the block being parsed. This does not include
  /// the metadata block header.
  pub length: u32,
  /// Block data containing on of the eight different types of metadata.
  pub data: BlockData,
}

/// General enum that hold all the different metadata block data.
#[derive(Debug, PartialEq, Eq)]
pub enum BlockData {
  /// Information regarding the entire audio stream.
  StreamInfo(StreamInfo),
  /// Block that represents a number of padded bytes.
  Padding(u32),
  /// Data used by third-party applications.
  Application(Application),
  /// Table of multiple points to seek, or skip, to within the FLAC file.
  SeekTable(Vec<SeekPoint>),
  /// Stores human-readable name/value pairs.
  VorbisComment(VorbisComment),
  /// Stores cue information
  CueSheet(CueSheet),
  /// Stores pictures associated with the FLAC file.
  Picture(Picture),
  /// A type of block data that isn't know or doesn't match the type above.
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream
#[derive(Debug, PartialEq, Eq)]
pub struct StreamInfo {
  /// Minimum block size, in samples, used in the stream.
  pub min_block_size: u16,
  /// Maximum block size, in samples, used in the stream.
  pub max_block_size: u16,
  /// Minimum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub min_frame_size: u32,
  /// Maximum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub max_frame_size: u32,
  /// Sample rate in hertz (Hz).
  pub sample_rate: u32,
  /// Number of channels. FLAC supports one to eight channel.
  pub channels: u8,
  /// Bits per sample. FLAC supports four to thirty-two bits per sample.
  pub bits_per_sample: u8,
  /// Total samples in the stream. A value of zero means the number is
  /// unknown.
  pub total_samples: u64,
  /// MD5 signature of the unencoded audio data.
  pub md5_sum: [u8; 16],
}

/// Data used by third-party applications.
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  pub id: String,
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file.
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  pub sample_number: u64,
  pub stream_offset: u64,
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs.
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  pub vendor_string: String,
  pub comments: HashMap<String, String>,
}

/// Stores cue information.
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  pub media_catalog_number: String,
  pub lead_in: u64,
  pub is_cd: bool,
  pub tracks: Vec<CueSheetTrack>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  pub offset: u64,
  pub number: u8,
  pub isrc: String,
  pub is_audio: bool,
  pub is_pre_emphasis: bool,
  pub indices: Vec<CueSheetTrackIndex>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  pub offset: u64,
  pub number: u8,
}

/// Stores pictures associated with the FLAC file.
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  pub picture_type: PictureType,
  pub mime_type: String,
  pub description: String,
  pub width: u32,
  pub height: u32,
  pub depth: u32,
  pub colors: u32,
  pub data: Vec<u8>,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  Other,
  FileIconStandard,
  FileIcon,
  FrontCover,
  BackCover,
  LeafletPage,
  Media,
  LeadArtist,
  Artist,
  Conductor,
  Band,
  Composer,
  Lyricist,
  RecordingLocation,
  DuringRecording,
  DuringPerformace,
  VideoScreenCapture,
  Fish,
  Illustration,
  BandLogo,
  PublisherLogo,
}

enum ParserState {
  FLAC,
  Header,
  MetaData,
}

pub struct MetaDataConsumer {
  state: ParserState,
  is_last: bool,
  block_type: u8,
  length: u32,
  pub data: Vec<Block>
}

impl MetaDataConsumer {
  pub fn new() -> MetaDataConsumer {
    MetaDataConsumer {
      state: ParserState::FLAC,
      is_last: false,
      block_type: 127,
      length: 0,
      data: Vec::new(),
    }
  }
}

impl Consumer for MetaDataConsumer {
  fn consume(&mut self, input: &[u8]) -> ConsumerState {
    match self.state {
      ParserState::FLAC     => {
        match tag!(input, "fLaC") {
          IResult::Done(_, _) => {
            self.state = ParserState::Header;
            ConsumerState::Await(4, 4)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      }
      ParserState::Header   => {
        match header(input) {
          IResult::Done(_, data) => {
            let (is_last, block_type, length) = data;

            self.state      = ParserState::MetaData;
            self.is_last    = is_last;
            self.block_type = block_type;
            self.length     = length;

            ConsumerState::Await(4, length as usize)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      },
      ParserState::MetaData => {
        let length = self.length as usize;

        match block_data(input, self.block_type, self.length) {
          IResult::Done(_, data) => {
            self.data.push(Block {
              is_last: self.is_last,
              length: self.length,
              data: data,
            });

            if self.is_last {
              ConsumerState::ConsumerDone
            } else {
              self.state = ParserState::Header;

              ConsumerState::Await(length, 4)
            }
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, length),
        }
      }
    }
  }

  fn failed(&mut self, error_code: u32) {
    println!("Failed with error code: {}", error_code);
  }

  fn end(&mut self) {}
}
<|endoftext|>


<commit_before>use diffgeom::coordinates::{CoordinateSystem, Point};
use diffgeom::metric::MetricSystem;
use diffgeom::tensors::Vector;
use generic_array::{ArrayLength, GenericArray};
use numeric::StateVector;
use numeric_algs::State;
use std::ops::Mul;
use typenum::consts::{U1, U2, U3};
use typenum::{Exp, Pow, Prod, Unsigned};

pub struct Particle<C: CoordinateSystem>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    x: Point<C>,
    v: Vector<C>,
}

impl<C: CoordinateSystem> Clone for Particle<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    fn clone(&self) -> Self {
        Particle {
            x: self.x.clone(),
            v: self.v.clone(),
        }
    }
}

impl<C: CoordinateSystem> Particle<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    pub fn new(x: Point<C>, v: Vector<C>) -> Self {
        Particle { x: x, v: v }
    }

    pub fn get_pos(&self) -> &Point<C> {
        &self.x
    }

    pub fn get_vel(&self) -> &Vector<C> {
        &self.v
    }
}

impl<C: CoordinateSystem> State for Particle<C>
where
    C::Dimension: Pow<U1> + Mul<U2> + Unsigned,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
    Prod<C::Dimension, U2>: ArrayLength<f64>,
    <Prod<C::Dimension, U2> as ArrayLength<f64>>::ArrayType: Copy,
{
    type Derivative = StateVector<Prod<C::Dimension, U2>>;

    fn shift_in_place(&mut self, dir: &Self::Derivative, amount: f64) {
        let d = C::Dimension::to_usize();
        for i in 0..d {
            self.x[i] += dir.0[i] * amount;
            self.v[i] += dir.0[i + d] * amount;
            self.v.set_point(self.x.clone());
        }
    }
}

impl<C: CoordinateSystem> Particle<C>
where
    C::Dimension: Pow<U1> + Mul<U2> + Unsigned + Pow<U2> + Pow<U3>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
    Prod<C::Dimension, U2>: ArrayLength<f64>,
    <Prod<C::Dimension, U2> as ArrayLength<f64>>::ArrayType: Copy,
    C: MetricSystem,
    Exp<C::Dimension, U2>: ArrayLength<f64>,
    Exp<C::Dimension, U3>: ArrayLength<f64>,
{
    pub fn derivative(&self) -> StateVector<Prod<C::Dimension, U2>> {
        let christoffel = C::christoffel(&self.x);
        let temp = inner!(_, Vector<C>; U1, U3; christoffel, self.v.clone());
        let cov_der = inner!(_, Vector<C>; U1, U2; temp, self.v.clone());
        let mut result = GenericArray::default();
        let d = C::Dimension::to_usize();
        for i in 0..d {
            result[i] = self.v[i];
            result[i + d] = -cov_der[i];
        }
        StateVector(result)
    }
}
<commit_msg>particle: implement coord system conversions for particles<commit_after>use diffgeom::coordinates::{ConversionTo, CoordinateSystem, Point};
use diffgeom::metric::MetricSystem;
use diffgeom::tensors::Vector;
use generic_array::{ArrayLength, GenericArray};
use numeric::StateVector;
use numeric_algs::State;
use std::ops::Mul;
use typenum::consts::{U1, U2, U3};
use typenum::{Exp, Pow, Prod, Same, Unsigned};

pub struct Particle<C: CoordinateSystem>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    x: Point<C>,
    v: Vector<C>,
}

impl<C: CoordinateSystem> Clone for Particle<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    fn clone(&self) -> Self {
        Particle {
            x: self.x.clone(),
            v: self.v.clone(),
        }
    }
}

impl<C: CoordinateSystem> Particle<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    pub fn new(x: Point<C>, v: Vector<C>) -> Self {
        Particle { x: x, v: v }
    }

    pub fn get_pos(&self) -> &Point<C> {
        &self.x
    }

    pub fn get_vel(&self) -> &Vector<C> {
        &self.v
    }
}

impl<C: CoordinateSystem> State for Particle<C>
where
    C::Dimension: Pow<U1> + Mul<U2> + Unsigned,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
    Prod<C::Dimension, U2>: ArrayLength<f64>,
    <Prod<C::Dimension, U2> as ArrayLength<f64>>::ArrayType: Copy,
{
    type Derivative = StateVector<Prod<C::Dimension, U2>>;

    fn shift_in_place(&mut self, dir: &Self::Derivative, amount: f64) {
        let d = C::Dimension::to_usize();
        for i in 0..d {
            self.x[i] += dir.0[i] * amount;
            self.v[i] += dir.0[i + d] * amount;
            self.v.set_point(self.x.clone());
        }
    }
}

impl<C: CoordinateSystem> Particle<C>
where
    C::Dimension: Pow<U1> + Mul<U2> + Unsigned + Pow<U2> + Pow<U3>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
    Prod<C::Dimension, U2>: ArrayLength<f64>,
    <Prod<C::Dimension, U2> as ArrayLength<f64>>::ArrayType: Copy,
    C: MetricSystem,
    Exp<C::Dimension, U2>: ArrayLength<f64>,
    Exp<C::Dimension, U3>: ArrayLength<f64>,
{
    pub fn derivative(&self) -> StateVector<Prod<C::Dimension, U2>> {
        let christoffel = C::christoffel(&self.x);
        let temp = inner!(_, Vector<C>; U1, U3; christoffel, self.v.clone());
        let cov_der = inner!(_, Vector<C>; U1, U2; temp, self.v.clone());
        let mut result = GenericArray::default();
        let d = C::Dimension::to_usize();
        for i in 0..d {
            result[i] = self.v[i];
            result[i + d] = -cov_der[i];
        }
        StateVector(result)
    }
}

impl<C: CoordinateSystem> Particle<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    pub fn convert<C2: CoordinateSystem + 'static>(&self) -> Particle<C2>
    where
        C: ConversionTo<C2>,
        C2::Dimension: Pow<U1> + Pow<U2>,
        Exp<C2::Dimension, U1>: ArrayLength<f64>,
        Exp<C2::Dimension, U2>: ArrayLength<f64>,
        C2::Dimension: Same<C::Dimension>,
    {
        let new_x: Point<C2> = C::convert_point(&self.x);
        let new_v: Vector<C2> = self.v.convert();
        Particle { x: new_x, v: new_v }
    }
}
<|endoftext|>


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

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

#[cfg(any(unix, windows))]
mod inner_unix_or_windows {
    extern crate time;

    /**
    Gets the current system time, in milliseconds since the UNIX epoch.
    */
    pub fn current_time() -> u64 {
        /*
        This is kinda dicey, since *ideally* both this function and `file_last_modified` would be using the same underlying APIs.  They are not, insofar as I know.

        At least, not when targetting Windows.

        That said, so long as everything is in the same units and uses the same epoch, it should be fine.
        */
        let now_1970_utc = time::now_utc().to_timespec();
        if now_1970_utc.sec < 0 || now_1970_utc.nsec < 0 {
            // Fuck it.
            return 0
        }
        let now_ms_1970_utc = (now_1970_utc.sec as u64 * 1000)
            + (now_1970_utc.nsec as u64 / 1_000_000);
        now_ms_1970_utc
    }
}

#[cfg(unix)]
mod inner {
    pub use super::inner_unix_or_windows::current_time;

    use std::path::{Path, PathBuf};
    use std::{cmp, env, fs};
    use std::os::unix::fs::MetadataExt;
    use error::{MainError, Blame};

    /**
    Gets the last-modified time of a file, in milliseconds since the UNIX epoch.
    */
    pub fn file_last_modified(file: &fs::File) -> u64 {
        let mtime_s_1970_utc = file.metadata()
            .map(|md| md.mtime())
            .unwrap_or(0);

        let mtime_s_1970_utc = cmp::max(0, mtime_s_1970_utc);
        mtime_s_1970_utc as u64 * 1000
    }

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

    This is chosen to match the location where Cargo places its cache data.
    */
    pub fn get_cache_dir_for<P>(product: P) -> Result<PathBuf, MainError>
    where P: AsRef<Path> {
        let home = match env::var_os("HOME") {
            Some(val) => val,
            None => return Err((Blame::Human, "$HOME is not defined").into())
        };

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

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

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

    pub use super::inner_unix_or_windows::current_time;

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

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

        const MS_BETWEEN_1601_1970: u64 = 11_644_473_600_000;

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

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

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

    This is *not* chosen to match the location where Cargo places its cache data, because Cargo is *wrong*.  This is at least *less wrong*.

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

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

    struct WinError(winapi::HRESULT);

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

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

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

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

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

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

#[cfg(any(unix, windows))]
mod inner_unix_or_windows {
    extern crate time;

    /**
    Gets the current system time, in milliseconds since the UNIX epoch.
    */
    pub fn current_time() -> u64 {
        /*
        This is kinda dicey, since *ideally* both this function and `file_last_modified` would be using the same underlying APIs.  They are not, insofar as I know.

        At least, not when targetting Windows.

        That said, so long as everything is in the same units and uses the same epoch, it should be fine.
        */
        let now_1970_utc = time::now_utc().to_timespec();
        if now_1970_utc.sec < 0 || now_1970_utc.nsec < 0 {
            // Fuck it.
            return 0
        }
        let now_ms_1970_utc = (now_1970_utc.sec as u64 * 1000)
            + (now_1970_utc.nsec as u64 / 1_000_000);
        now_ms_1970_utc
    }
}

#[cfg(unix)]
mod inner {
    pub use super::inner_unix_or_windows::current_time;

    use std::path::{Path, PathBuf};
    use std::{cmp, env, fs};
    use std::os::unix::fs::MetadataExt;
    use error::{MainError, Blame};

    /**
    Gets the last-modified time of a file, in milliseconds since the UNIX epoch.
    */
    pub fn file_last_modified(file: &fs::File) -> u64 {
        let mtime_s_1970_utc = file.metadata()
            .map(|md| md.mtime())
            .unwrap_or(0);

        let mtime_s_1970_utc = cmp::max(0, mtime_s_1970_utc);
        mtime_s_1970_utc as u64 * 1000
    }

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

    This is chosen to match the location where Cargo places its cache data.
    */
    pub fn get_cache_dir_for<P>(product: P) -> Result<PathBuf, MainError>
    where P: AsRef<Path> {
        // try $CARGO_HOME then fall back to $HOME
        let home = match env::var_os("CARGO_HOME") {
            Some(val) => val,
            None => match env::var_os("HOME") {
                Some(val) => val,
                None => return Err((Blame::Human, "neither $CARGO_HOME nor $HOME is defined").into())
            }
        };

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

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

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

    pub use super::inner_unix_or_windows::current_time;

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

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

        const MS_BETWEEN_1601_1970: u64 = 11_644_473_600_000;

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

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

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

    This is *not* chosen to match the location where Cargo places its cache data, because Cargo is *wrong*.  This is at least *less wrong*.

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

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

    struct WinError(winapi::HRESULT);

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

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

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

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

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


<commit_before>//! Types for the *m.presence* event.

use js_int::UInt;
use ruma_events_macros::ruma_event;
use ruma_identifiers::UserId;
use serde::{Deserialize, Serialize};

ruma_event! {
    /// Informs the client of a user's presence state change.
    PresenceEvent {
        kind: Event,
        event_type: Presence,
        fields: {
            /// The unique identifier for the user associated with this event.
            pub sender: UserId,
        },
        content: {
            /// The current avatar URL for this user.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub avatar_url: Option<String>,

            /// Whether or not the user is currently active.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub currently_active: Option<bool>,

            /// The current display name for this user.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub displayname: Option<String>,

            /// The last time since this user performed some action, in milliseconds.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub last_active_ago: Option<UInt>,

            /// The presence state for this user.
            pub presence: PresenceState,

            /// An optional description to accompany the presence.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub status_msg: Option<String>,
        },
    }
}

/// A description of a user's connectivity and availability for chat.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum PresenceState {
    /// Disconnected from the service.
    #[serde(rename = "offline")]
    Offline,

    /// Connected to the service.
    #[serde(rename = "online")]
    Online,

    /// Connected to the service but not available for chat.
    #[serde(rename = "unavailable")]
    Unavailable,

    /// Additional variants may be added in the future and will not be considered breaking changes
    /// to ruma-events.
    #[doc(hidden)]
    #[serde(skip)]
    __Nonexhaustive,
}

impl_enum! {
    PresenceState {
        Offline => "offline",
        Online => "online",
        Unavailable => "unavailable",
    }
}

#[cfg(test)]
mod tests {
    use std::convert::TryFrom;

    use js_int::UInt;
    use ruma_identifiers::UserId;
    use serde_json::to_string;

    use super::{PresenceEvent, PresenceEventContent, PresenceState};
    use crate::EventResult;

    #[test]
    fn serialization() {
        let event = PresenceEvent {
            content: PresenceEventContent {
                avatar_url: Some("mxc://localhost:wefuiwegh8742w".to_string()),
                currently_active: Some(false),
                displayname: None,
                last_active_ago: Some(UInt::try_from(2_478_593).unwrap()),
                presence: PresenceState::Online,
                status_msg: Some("Making cupcakes".to_string()),
            },
            sender: UserId::try_from("@example:localhost").unwrap(),
        };

        let json =
            r#"{"content":{"avatar_url":"mxc://localhost:wefuiwegh8742w","currently_active":false,"last_active_ago":2478593,"presence":"online","status_msg":"Making cupcakes"},"sender":"@example:localhost","type":"m.presence"}"#;

        assert_eq!(to_string(&event).unwrap(), json);
    }

    #[test]
    fn deserialization() {
        let event = PresenceEvent {
            content: PresenceEventContent {
                avatar_url: Some("mxc://localhost:wefuiwegh8742w".to_string()),
                currently_active: Some(false),
                displayname: None,
                last_active_ago: Some(UInt::try_from(2_478_593).unwrap()),
                presence: PresenceState::Online,
                status_msg: Some("Making cupcakes".to_string()),
            },
            sender: UserId::try_from("@example:localhost").unwrap(),
        };

        let json =
            r#"{"content":{"avatar_url":"mxc://localhost:wefuiwegh8742w","currently_active":false,"last_active_ago":2478593,"presence":"online","status_msg":"Making cupcakes"},"sender":"@example:localhost","type":"m.presence"}"#;

        assert_eq!(
            serde_json::from_str::<EventResult<PresenceEvent>>(json)
                .unwrap()
                .into_result()
                .unwrap(),
            event
        );
    }
}
<commit_msg>Re-run `rustfmt`<commit_after>//! Types for the *m.presence* event.

use js_int::UInt;
use ruma_events_macros::ruma_event;
use ruma_identifiers::UserId;
use serde::{Deserialize, Serialize};

ruma_event! {
    /// Informs the client of a user's presence state change.
    PresenceEvent {
        kind: Event,
        event_type: Presence,
        fields: {
            /// The unique identifier for the user associated with this event.
            pub sender: UserId,
        },
        content: {
            /// The current avatar URL for this user.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub avatar_url: Option<String>,

            /// Whether or not the user is currently active.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub currently_active: Option<bool>,

            /// The current display name for this user.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub displayname: Option<String>,

            /// The last time since this user performed some action, in milliseconds.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub last_active_ago: Option<UInt>,

            /// The presence state for this user.
            pub presence: PresenceState,

            /// An optional description to accompany the presence.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub status_msg: Option<String>,
        },
    }
}

/// A description of a user's connectivity and availability for chat.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum PresenceState {
    /// Disconnected from the service.
    #[serde(rename = "offline")]
    Offline,

    /// Connected to the service.
    #[serde(rename = "online")]
    Online,

    /// Connected to the service but not available for chat.
    #[serde(rename = "unavailable")]
    Unavailable,

    /// Additional variants may be added in the future and will not be considered breaking changes
    /// to ruma-events.
    #[doc(hidden)]
    #[serde(skip)]
    __Nonexhaustive,
}

impl_enum! {
    PresenceState {
        Offline => "offline",
        Online => "online",
        Unavailable => "unavailable",
    }
}

#[cfg(test)]
mod tests {
    use std::convert::TryFrom;

    use js_int::UInt;
    use ruma_identifiers::UserId;
    use serde_json::to_string;

    use super::{PresenceEvent, PresenceEventContent, PresenceState};
    use crate::EventResult;

    #[test]
    fn serialization() {
        let event = PresenceEvent {
            content: PresenceEventContent {
                avatar_url: Some("mxc://localhost:wefuiwegh8742w".to_string()),
                currently_active: Some(false),
                displayname: None,
                last_active_ago: Some(UInt::try_from(2_478_593).unwrap()),
                presence: PresenceState::Online,
                status_msg: Some("Making cupcakes".to_string()),
            },
            sender: UserId::try_from("@example:localhost").unwrap(),
        };

        let json = r#"{"content":{"avatar_url":"mxc://localhost:wefuiwegh8742w","currently_active":false,"last_active_ago":2478593,"presence":"online","status_msg":"Making cupcakes"},"sender":"@example:localhost","type":"m.presence"}"#;

        assert_eq!(to_string(&event).unwrap(), json);
    }

    #[test]
    fn deserialization() {
        let event = PresenceEvent {
            content: PresenceEventContent {
                avatar_url: Some("mxc://localhost:wefuiwegh8742w".to_string()),
                currently_active: Some(false),
                displayname: None,
                last_active_ago: Some(UInt::try_from(2_478_593).unwrap()),
                presence: PresenceState::Online,
                status_msg: Some("Making cupcakes".to_string()),
            },
            sender: UserId::try_from("@example:localhost").unwrap(),
        };

        let json = r#"{"content":{"avatar_url":"mxc://localhost:wefuiwegh8742w","currently_active":false,"last_active_ago":2478593,"presence":"online","status_msg":"Making cupcakes"},"sender":"@example:localhost","type":"m.presence"}"#;

        assert_eq!(
            serde_json::from_str::<EventResult<PresenceEvent>>(json)
                .unwrap()
                .into_result()
                .unwrap(),
            event
        );
    }
}
<|endoftext|>


<commit_before>//! Defines the various kinds of memory in the NES and provides an interface
//! for them,
use std::rc::Rc;
use std::cell::RefCell;

use nes::MemMapped;
use nes::ppu::Ppu;
//use nes::apu::Apu; // TODO
use nes::io::Io;
use ines::InesRom;

use sdl2::Sdl;

pub mod mapper;
use self::mapper::*;

mod constants;
use self::constants::*;

// TODO: Add CHR
/// This is a raw container of the various memories in the NES.
/// This does NOT include memory mapped I/O.
/// Things that are mapped are handled by their respective components
/// memory_map modules.
pub struct Memory<'a> {
    pub ppu: Ppu<'a>,
    // apu: Apu, // TODO
    io:  Io,
    ram: Ram,
    // exp: ExpansionRom // TODO
    // sram: Sram // TODO
    prg: Rc<RefCell<Box<Mapper>>>,
}

impl<'a> Memory<'a> {
    pub fn new(rom: &InesRom, sdl_context: &Sdl) -> Memory<'a> {
        let mapper = choose_mapper(rom);
        let mapper = Rc::new(RefCell::new(mapper));
        Memory {
            ppu: Ppu::new(mapper.clone(), sdl_context, rom.mirroring()),
            // apu: Apu::new(), // TODO
            io:  Io::new(),
            ram: Ram::new(),
            prg: mapper.clone(),
        }
    }

    pub fn read_ppu_byte(&mut self, addr: u16) -> u8 {
        self.ppu.read_byte(addr)
    }

    pub fn write_ppu_byte(&mut self, addr: u16, val: u8) {
        self.ppu.write_byte(addr, val);
    }

    pub fn read_io_byte(&mut self, addr: u16) -> u8 {
        self.io.read_byte(addr)
    }

    pub fn write_io_byte(&mut self, addr: u16, val: u8) {
        self.io.write_byte(addr, val);
    }

    /// Reads a byte from RAM.
    pub fn read_ram_byte(&mut self, addr: u16) -> u8 {
        self.ram.read_byte(addr)
    }

    /// Writes a byte to RAM.
    pub fn write_ram_byte(&mut self, addr: u16, val: u8) {
        self.ram.write_byte(addr, val);
    }

    /// Reads a byte from PRG-ROM as defined by the mapper.
    pub fn read_rom_byte(&self, addr: u16) -> u8 {
        println!("Reading rom at: {:#X}", addr);
        self.prg.borrow().read_rom_byte(addr)
    }
}

/// Provides an interface for the CPU's RAM
struct Ram {
    zero_page: Vec<u8>,
    stack: Vec<u8>,
    ram: Vec<u8>
}

impl Ram {
    pub fn new() -> Ram {
        Ram {
            zero_page: vec![0; ZERO_PAGE_SIZE],
            stack: vec![0; STACK_SIZE],
            ram: vec![0; RAM_SIZE],
        }
    }
}

impl MemMapped for Ram {
    /// Reads a byte from RAM.
    ///
    /// #Panics
    /// Will panic if the address is not in RAM.
    fn read_byte(&mut self, addr: u16) -> u8 {
        match addr {
            ZERO_PAGE_BEG...ZERO_PAGE_END => {
                self.zero_page[addr as usize]
            },
            STACK_BEG...STACK_END => {
                let rel_addr = (addr - STACK_BEG) as usize;
                self.stack[rel_addr]
            },
            RAM_BEG...RAM_END => {
                let rel_addr = (addr - RAM_BEG) as usize;
                self.ram[rel_addr]
            }
            _ => panic!("Improper attempt to read from RAM at addr: {:#X}", addr)
        }
    }

    /// Writes a byte to RAM.
    ///
    /// #Panics
    /// Will panic if the address is not in RAM.
    fn write_byte(&mut self, addr: u16, val: u8) {
        match addr {
            ZERO_PAGE_BEG...ZERO_PAGE_END => {
                self.zero_page[addr as usize] = val
            },
            STACK_BEG...STACK_END => {
                let rel_addr = (addr - STACK_BEG) as usize;
                self.stack[rel_addr] = val
            },
            RAM_BEG...RAM_END => {
                let rel_addr = (addr - RAM_BEG) as usize;
                self.ram[rel_addr] = val
            }
            _ => panic!("Improper attempt to write to RAM at addr: {:#X}", addr)
        }
    }
}
<commit_msg>Added license<commit_after>//! Defines the various kinds of memory in the NES and provides an interface
//! for them,
use std::rc::Rc;
use std::cell::RefCell;

use nes::MemMapped;
use nes::ppu::Ppu;
//use nes::apu::Apu; // TODO
use nes::io::Io;
use ines::InesRom;

use sdl2::Sdl;

pub mod mapper;
use self::mapper::*;

mod constants;
use self::constants::*;

// TODO: Add CHR
/// This is a raw container of the various memories in the NES.
/// This does NOT include memory mapped I/O.
/// Things that are mapped are handled by their respective components
/// memory_map modules.
pub struct Memory<'a> {
    pub ppu: Ppu<'a>,
    // apu: Apu, // TODO
    io:  Io,
    ram: Ram,
    // exp: ExpansionRom // TODO
    // sram: Sram // TODO
    prg: Rc<RefCell<Box<Mapper>>>,
}

impl<'a> Memory<'a> {
    pub fn new(rom: &InesRom, sdl_context: &Sdl) -> Memory<'a> {
        let mapper = choose_mapper(rom);
        let mapper = Rc::new(RefCell::new(mapper));
        Memory {
            ppu: Ppu::new(mapper.clone(), sdl_context, rom.mirroring()),
            // apu: Apu::new(), // TODO
            io:  Io::new(),
            ram: Ram::new(),
            prg: mapper.clone(),
        }
    }

    pub fn read_ppu_byte(&mut self, addr: u16) -> u8 {
        self.ppu.read_byte(addr)
    }

    pub fn write_ppu_byte(&mut self, addr: u16, val: u8) {
        self.ppu.write_byte(addr, val);
    }

    pub fn read_io_byte(&mut self, addr: u16) -> u8 {
        self.io.read_byte(addr)
    }

    pub fn write_io_byte(&mut self, addr: u16, val: u8) {
        self.io.write_byte(addr, val);
    }

    /// Reads a byte from RAM.
    pub fn read_ram_byte(&mut self, addr: u16) -> u8 {
        self.ram.read_byte(addr)
    }

    /// Writes a byte to RAM.
    pub fn write_ram_byte(&mut self, addr: u16, val: u8) {
        self.ram.write_byte(addr, val);
    }

    /// Reads a byte from PRG-ROM as defined by the mapper.
    pub fn read_rom_byte(&self, addr: u16) -> u8 {
        self.prg.borrow().read_rom_byte(addr)
    }
}

/// Provides an interface for the CPU's RAM
struct Ram {
    zero_page: Vec<u8>,
    stack: Vec<u8>,
    ram: Vec<u8>
}

impl Ram {
    pub fn new() -> Ram {
        Ram {
            zero_page: vec![0; ZERO_PAGE_SIZE],
            stack: vec![0; STACK_SIZE],
            ram: vec![0; RAM_SIZE],
        }
    }
}

impl MemMapped for Ram {
    /// Reads a byte from RAM.
    ///
    /// #Panics
    /// Will panic if the address is not in RAM.
    fn read_byte(&mut self, addr: u16) -> u8 {
        match addr {
            ZERO_PAGE_BEG...ZERO_PAGE_END => {
                self.zero_page[addr as usize]
            },
            STACK_BEG...STACK_END => {
                let rel_addr = (addr - STACK_BEG) as usize;
                self.stack[rel_addr]
            },
            RAM_BEG...RAM_END => {
                let rel_addr = (addr - RAM_BEG) as usize;
                self.ram[rel_addr]
            }
            _ => panic!("Improper attempt to read from RAM at addr: {:#X}", addr)
        }
    }

    /// Writes a byte to RAM.
    ///
    /// #Panics
    /// Will panic if the address is not in RAM.
    fn write_byte(&mut self, addr: u16, val: u8) {
        match addr {
            ZERO_PAGE_BEG...ZERO_PAGE_END => {
                self.zero_page[addr as usize] = val
            },
            STACK_BEG...STACK_END => {
                let rel_addr = (addr - STACK_BEG) as usize;
                self.stack[rel_addr] = val
            },
            RAM_BEG...RAM_END => {
                let rel_addr = (addr - RAM_BEG) as usize;
                self.ram[rel_addr] = val
            }
            _ => panic!("Improper attempt to write to RAM at addr: {:#X}", addr)
        }
    }
}
<|endoftext|>


<commit_before>use quick_fn::QuickFn;
use arbitrary::Arbitrary;
use generate::{Generator, GenerateCtx};
use testable::{IntoTestable, Testable, TestResult};

use std::marker::PhantomData;
use rand::Rng;

#[derive(Copy, Clone)]
pub struct Property<Args> {
    _marker: PhantomData<Args>
}

#[derive(Copy, Clone)]
pub struct ForAllProperty<Args, G, F> {
    generator: G,
    f: F,
    _marker: PhantomData<Args>
}

impl <G, F, T> Testable for ForAllProperty<G::Output, G, F>
    where G: Generator,
          F: QuickFn<G::Output, Output=T>,
          T: Into<TestResult>
{
    #[inline]
    fn test<R: Rng>(&self, ctx: &mut GenerateCtx<R>) -> TestResult {
        let args = self.generator.generate(ctx);
        self.f.call(args).into()
    }
}

#[derive(Copy, Clone)]
pub struct ForAll<Args, G> {
    generator: G,
    _marker: PhantomData<Args>
}

impl <Args, G> ForAll<Args, G> {
    #[inline]
    pub fn property<F: QuickFn<Args>>(self, f: F) -> ForAllProperty<Args, G, F>
        where F::Output: Into<TestResult>,
              G: Generator<Output=Args>
    {
        ForAllProperty {
            generator: self.generator,
            f: f,
            _marker: PhantomData
        }
    }
}

#[derive(Copy, Clone)]
pub struct When<Args, P> {
    predicate: P,
    _marker: PhantomData<Args>
}

pub fn when<Args, P>(p: P) -> When<Args, P>
    where P: QuickFn<Args, Output=bool>
{
    When { predicate: p, _marker: PhantomData }
}

#[derive(Copy, Clone)]
pub struct WhenFn<Args, P, F> {
    predicate: P,
    f: F,
    _marker: PhantomData<Args>
}

impl <Args, P> When<Args, P> {
    #[inline]
    pub fn property<F: QuickFn<Args>>(self, f: F)
        -> ForAllProperty<Args, Args::Generator, WhenFn<Args, P, F>>
        where Args: Arbitrary,
              P: QuickFn<Args, Output=bool>,
              WhenFn<Args, P, F>: QuickFn<Args>,
              <WhenFn<Args, P, F> as QuickFn<Args>>::Output: Into<TestResult>
    {
        Property::<Args>::new(WhenFn {
            predicate: self.predicate,
            f: f,
            _marker: PhantomData
        })
    }
}

impl <Args, P, F> IntoTestable for WhenFn<Args, P, F>
    where Args: Arbitrary,
          WhenFn<Args, P, F>: QuickFn<Args>,
          <WhenFn<Args, P, F> as QuickFn<Args>>::Output: Into<TestResult>
{
    type Testable = ForAllProperty<Args, Args::Generator, Self>;

    #[inline]
    fn into_testable(self) -> Self::Testable {
        Property::<Args>::new(self)
    }
}

#[cfg(not(feature = "no_function_casts"))]
mod stable {
    use super::*;
    use quick_fn::QuickFn;
    use testable::{TestResult, Status};

    impl <Args, G, F> QuickFn<Args> for ForAllProperty<Args, G, F>
        where F: QuickFn<Args>
    {
        type Output = F::Output;

        #[inline]
        fn call(&self, args: Args) -> Self::Output {
            self.f.call(args)
        }
    }

    impl <Args, P, F> QuickFn<Args> for WhenFn<Args, P, F>
        where Args: Clone,
              P: QuickFn<Args, Output=bool>,
              F: QuickFn<Args>,
              F::Output: Into<TestResult>
    {
        type Output = TestResult;

        #[inline]
        fn call(&self, args: Args) -> Self::Output {
            let fn_args = args.clone();
            match self.predicate.call(args) {
                false => TestResult { status: Status::Discard },
                true  => self.f.call(fn_args).into()
            }
        }
    }
}

#[cfg(feature = "no_function_casts")]
mod unstable {
    use super::*;
    use quick_fn::QuickFn;
    use testable::{TestResult, Status};

    impl <Args, G, F> Fn<Args> for ForAllProperty<Args, G, F>
        where F: QuickFn<Args>
    {
        type Output = F::Output;

        #[inline]
        fn call(&self, args: Args) -> Self::Output {
            self.f.call(args)
        }
    }

    impl <Args, P, F> Fn<Args> for WhenFn<Args, P, F>
        where Args: Clone,
              P: Fn<Args, Output=bool>,
              F: Fn<Args>,
              F::Output: Into<TestResult>
    {
        type Output = TestResult;

        #[inline]
        fn call(&self, args: Args) -> Self::Output {
            let fn_args = args.clone();
            match self.predicate.call(args) {
                false => TestResult { status: Status::Discard },
                true  => self.f.call(fn_args).into()
            }
        }
    }
}

impl <Args> Property<Args> {
    pub fn new<F: QuickFn<Args>>(f: F) -> ForAllProperty<Args, Args::Generator, F>
        where Args: Arbitrary,
              F::Output: Into<TestResult>
    {
        Property::<Args>::for_all(Args::arbitrary()).property(f)
    }

    pub fn for_all<G: Generator<Output=Args>>(g: G) -> ForAll<Args, G> {
        ForAll {
            generator: g,
            _marker: PhantomData
        }
    }

    pub fn when<P: QuickFn<Args, Output=bool>>(p: P) -> When<Args, P>
        where Args: Arbitrary
    {
        when(p)
    }
}

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

    #[test]
    fn test_simple_property() {
        Property::<()>::new(|| false);
    }

    #[test]
    fn test_for_all_property() {
        Property::<()>::for_all(<()>::arbitrary()).property(|| true);
    }

    #[test]
    fn test_when_property() {
        Property::<()>::when(|| false).property(|| true);
    }

    #[test]
    fn test_nested_when_property() {
        Property::<()>::for_all(<()>::arbitrary()).property(when(|| true).property(|| false));
    }

    #[test]
    fn test_generic_property() {
        fn property<A>(_: A) -> bool {
            ::std::mem::size_of::<A>() == 0
        }

        Property::<(usize,)>::new(property);
        // Doesn't type check
        // Property::new(property as fn(usize) -> bool);
    }
}

#[cfg(all(test, feature = "no_function_casts"))]
mod unstable_tests {
    use super::*;
    use arbitrary::Arbitrary;

    #[test]
    fn test_simple_property() {
        Property::new(|| false);
    }

    #[test]
    fn test_for_all_property() {
        Property::for_all(<()>::arbitrary()).property(|| true);
    }

    #[test]
    fn test_when_property() {
        Property::when(|| false).then(|| true);
    }

    #[test]
    fn test_nested_when_property() {
        Property::for_all(<()>::arbitrary()).property(when(|| true).property(|| false));
    }

    #[test]
    fn test_generic_property() {
        fn property<A>(_: A) -> bool {
            ::std::mem::size_of::<A>() == 0
        }

        Property::<(usize,)>::new(property);
        Property::new(property as fn(usize) -> bool);
    }
}
<commit_msg>Starting to reduce usage of QuickFn.<commit_after>use quick_fn::QuickFn;
use arbitrary::Arbitrary;
use generate::{Generator, GenerateCtx};
use testable::{IntoTestable, Testable, TestResult, Status};

use std::marker::PhantomData;
use rand::Rng;

#[derive(Copy, Clone)]
pub struct Property<Args> {
    _marker: PhantomData<Args>
}

#[derive(Copy, Clone)]
pub struct ForAllProperty<Args, G, F> {
    generator: G,
    f: F,
    _marker: PhantomData<Args>
}

impl <G, F, T> Testable for ForAllProperty<G::Output, G, F>
    where G: Generator,
          F: QuickFn<G::Output, Output=T>,
          T: Into<TestResult>
{
    #[inline]
    fn test<R: Rng>(&self, ctx: &mut GenerateCtx<R>) -> TestResult {
        let args = self.generator.generate(ctx);
        self.f.call(args).into()
    }
}

#[derive(Copy, Clone)]
pub struct ForAll<Args, G> {
    generator: G,
    _marker: PhantomData<Args>
}

impl <Args, G> ForAll<Args, G> {
    #[inline]
    pub fn property<F: QuickFn<Args>>(self, f: F) -> ForAllProperty<Args, G, F>
        where F::Output: Into<TestResult>,
              G: Generator<Output=Args>
    {
        ForAllProperty {
            generator: self.generator,
            f: f,
            _marker: PhantomData
        }
    }
}

#[derive(Copy, Clone)]
pub struct When<Args, P> {
    predicate: P,
    _marker: PhantomData<Args>
}

#[derive(Copy, Clone)]
pub struct WhenFn<Args, P, F> {
    predicate: P,
    f: F,
    _marker: PhantomData<Args>
}

impl <Args, P> When<Args, P> {
    #[inline]
    pub fn property<F: QuickFn<Args>>(self, f: F)
        -> ForAllProperty<Args, Args::Generator, WhenFn<Args, P, F>>
        where Args: Arbitrary,
              P: QuickFn<Args, Output=bool>,
              WhenFn<Args, P, F>: QuickFn<Args>,
              <WhenFn<Args, P, F> as QuickFn<Args>>::Output: Into<TestResult>
    {
        Property::<Args>::new(WhenFn {
            predicate: self.predicate,
            f: f,
            _marker: PhantomData
        })
    }
}

impl <Args, P, F> IntoTestable for WhenFn<Args, P, F>
    where Args: Arbitrary,
          WhenFn<Args, P, F>: QuickFn<Args>,
          <WhenFn<Args, P, F> as QuickFn<Args>>::Output: Into<TestResult>
{
    type Testable = ForAllProperty<Args, Args::Generator, Self>;

    #[inline]
    fn into_testable(self) -> Self::Testable {
        Property::<Args>::new(self)
    }
}

impl <Args, P, F> QuickFn<Args> for WhenFn<Args, P, F>
    where Args: Clone,
          P: QuickFn<Args, Output=bool>,
          F: QuickFn<Args>,
          F::Output: Into<TestResult>
{
    type Output = TestResult;

    #[inline]
    fn call(&self, args: Args) -> Self::Output {
        let fn_args = args.clone();
        match self.predicate.call(args) {
            false => TestResult { status: Status::Discard },
            true  => self.f.call(fn_args).into()
        }
    }
}

impl <Args> Property<Args> {
    pub fn new<F: QuickFn<Args>>(f: F) -> ForAllProperty<Args, Args::Generator, F>
        where Args: Arbitrary,
              F::Output: Into<TestResult>
    {
        Property::<Args>::for_all(Args::arbitrary()).property(f)
    }

    pub fn for_all<G: Generator<Output=Args>>(g: G) -> ForAll<Args, G> {
        ForAll {
            generator: g,
            _marker: PhantomData
        }
    }

    pub fn when<P: QuickFn<Args, Output=bool>>(p: P) -> When<Args, P>
        where Args: Arbitrary
    {
        When { predicate: p, _marker: PhantomData }
    }
}

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

    #[test]
    fn test_simple_property() {
        Property::<()>::new(|| false);
    }

    #[test]
    fn test_for_all_property() {
        Property::<()>::for_all(<()>::arbitrary()).property(|| true);
    }

    #[test]
    fn test_when_property() {
        Property::<()>::when(|| false).property(|| true);
    }

    #[test]
    fn test_generic_property() {
        fn property<A>(_: A) -> bool {
            ::std::mem::size_of::<A>() == 0
        }

        Property::<(usize,)>::new(property);
        // Doesn't type check
        // Property::new(property as fn(usize) -> bool);
    }
}

#[cfg(all(test, feature = "no_function_casts"))]
mod unstable_tests {
    use super::*;
    use arbitrary::Arbitrary;

    #[test]
    fn test_simple_property() {
        Property::new(|| false);
    }

    #[test]
    fn test_for_all_property() {
        Property::for_all(<()>::arbitrary()).property(|| true);
    }

    #[test]
    fn test_when_property() {
        Property::when(|| false).then(|| true);
    }

    #[test]
    fn test_nested_when_property() {
        Property::for_all(<()>::arbitrary()).property(when(|| true).property(|| false));
    }

    #[test]
    fn test_generic_property() {
        fn property<A>(_: A) -> bool {
            ::std::mem::size_of::<A>() == 0
        }

        Property::<(usize,)>::new(property);
        Property::new(property as fn(usize) -> bool);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use conversion::ToPyObject;
use err::{self, PyErr, PyResult};
use ffi;
use libc::c_char;
use objectprotocol::ObjectProtocol;
use objects::{exc, PyDict, PyObject, PyTuple};
use py_class::PythonObjectFromPyClassMacro;
use python::{PyDrop, Python, PythonObject};
use std;
use std::ffi::{CStr, CString};

/// Represents a Python module object.
pub struct PyModule(PyObject);

pyobject_newtype!(PyModule, PyModule_Check, PyModule_Type);

impl PyModule {
    /// Create a new module object with the `__name__` attribute set to name.
    pub fn new(py: Python, name: &str) -> PyResult<PyModule> {
        let name = CString::new(name).unwrap();
        unsafe { err::result_cast_from_owned_ptr(py, ffi::PyModule_New(name.as_ptr())) }
    }

    /// Import the Python module with the specified name.
    pub fn import(py: Python, name: &str) -> PyResult<PyModule> {
        let name = CString::new(name).unwrap();
        unsafe { err::result_cast_from_owned_ptr(py, ffi::PyImport_ImportModule(name.as_ptr())) }
    }

    /// Return the dictionary object that implements module's namespace;
    /// this object is the same as the `__dict__` attribute of the module object.
    pub fn dict(&self, py: Python) -> PyDict {
        unsafe {
            let r = PyObject::from_borrowed_ptr(py, ffi::PyModule_GetDict(self.0.as_ptr()));
            r.unchecked_cast_into::<PyDict>()
        }
    }

    unsafe fn str_from_ptr<'a>(&'a self, py: Python, ptr: *const c_char) -> PyResult<&'a str> {
        if ptr.is_null() {
            Err(PyErr::fetch(py))
        } else {
            let slice = CStr::from_ptr(ptr).to_bytes();
            match std::str::from_utf8(slice) {
                Ok(s) => Ok(s),
                Err(e) => Err(PyErr::from_instance(
                    py,
                    exc::UnicodeDecodeError::new_utf8(py, slice, e)?,
                )),
            }
        }
    }

    /// Gets the module name.
    ///
    /// May fail if the module does not have a `__name__` attribute.
    pub fn name<'a>(&'a self, py: Python) -> PyResult<&'a str> {
        unsafe { self.str_from_ptr(py, ffi::PyModule_GetName(self.0.as_ptr())) }
    }

    /// Gets the module filename.
    ///
    /// May fail if the module does not have a `__file__` attribute.
    pub fn filename<'a>(&'a self, py: Python) -> PyResult<&'a str> {
        unsafe { self.str_from_ptr(py, ffi::PyModule_GetFilename(self.0.as_ptr())) }
    }

    /// Gets a member from the module.
    /// This is equivalent to the Python expression: `getattr(module, name)`
    pub fn get(&self, py: Python, name: &str) -> PyResult<PyObject> {
        self.as_object().getattr(py, name)
    }

    /// Calls a function in the module.
    /// This is equivalent to the Python expression: `getattr(module, name)(*args, **kwargs)`
    ///
    /// `args` should be a value that, when converted to Python, results in a tuple.
    /// For this purpose, you can use:
    ///  * `cpython::NoArgs` when calling a method without any arguments
    ///  * otherwise, a Rust tuple with 1 or more elements
    ///
    /// # Example
    /// ```
    /// use cpython::NoArgs;
    /// # use cpython::Python;
    /// # let gil = Python::acquire_gil();
    /// # let py = gil.python();
    /// let sys = py.import("sys").unwrap();
    /// // Call function without arguments:
    /// let encoding = sys.call(py, "getdefaultencoding", NoArgs, None).unwrap();
    /// // Call function with a single argument:
    /// sys.call(py, "setrecursionlimit", (1000,), None).unwrap();
    /// ```
    pub fn call<A>(
        &self,
        py: Python,
        name: &str,
        args: A,
        kwargs: Option<&PyDict>,
    ) -> PyResult<PyObject>
    where
        A: ToPyObject<ObjectType = PyTuple>,
    {
        self.as_object().getattr(py, name)?.call(py, args, kwargs)
    }

    /// Adds a member to the module.
    ///
    /// This is a convenience function which can be used from the module's initialization function.
    pub fn add<V>(&self, py: Python, name: &str, value: V) -> PyResult<()>
    where
        V: ToPyObject,
    {
        self.as_object().setattr(py, name, value)
    }

    /// Adds a new extension type to the module.
    ///
    /// This is a convenience function that initializes the `py_class!()`,
    /// sets `new_type.__module__` to this module's name,
    /// and adds the type to this module.
    pub fn add_class<'p, T>(&self, py: Python<'p>) -> PyResult<()>
    where
        T: PythonObjectFromPyClassMacro,
    {
        T::add_to_module(py, self)
    }
}
<commit_msg>allow deprecated use of get module filename and provide access to filename object<commit_after>// Copyright (c) 2015 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use conversion::ToPyObject;
use err::{self, PyErr, PyResult};
use ffi;
use libc::c_char;
use objectprotocol::ObjectProtocol;
use objects::{exc, PyDict, PyObject, PyTuple};
use py_class::PythonObjectFromPyClassMacro;
use python::{PyDrop, Python, PythonObject};
use std;
use std::ffi::{CStr, CString};

/// Represents a Python module object.
pub struct PyModule(PyObject);

pyobject_newtype!(PyModule, PyModule_Check, PyModule_Type);

impl PyModule {
    /// Create a new module object with the `__name__` attribute set to name.
    pub fn new(py: Python, name: &str) -> PyResult<PyModule> {
        let name = CString::new(name).unwrap();
        unsafe { err::result_cast_from_owned_ptr(py, ffi::PyModule_New(name.as_ptr())) }
    }

    /// Import the Python module with the specified name.
    pub fn import(py: Python, name: &str) -> PyResult<PyModule> {
        let name = CString::new(name).unwrap();
        unsafe { err::result_cast_from_owned_ptr(py, ffi::PyImport_ImportModule(name.as_ptr())) }
    }

    /// Return the dictionary object that implements module's namespace;
    /// this object is the same as the `__dict__` attribute of the module object.
    pub fn dict(&self, py: Python) -> PyDict {
        unsafe {
            let r = PyObject::from_borrowed_ptr(py, ffi::PyModule_GetDict(self.0.as_ptr()));
            r.unchecked_cast_into::<PyDict>()
        }
    }

    unsafe fn str_from_ptr<'a>(&'a self, py: Python, ptr: *const c_char) -> PyResult<&'a str> {
        if ptr.is_null() {
            Err(PyErr::fetch(py))
        } else {
            let slice = CStr::from_ptr(ptr).to_bytes();
            match std::str::from_utf8(slice) {
                Ok(s) => Ok(s),
                Err(e) => Err(PyErr::from_instance(
                    py,
                    exc::UnicodeDecodeError::new_utf8(py, slice, e)?,
                )),
            }
        }
    }

    /// Gets the module name.
    ///
    /// May fail if the module does not have a `__name__` attribute.
    pub fn name<'a>(&'a self, py: Python) -> PyResult<&'a str> {
        unsafe { self.str_from_ptr(py, ffi::PyModule_GetName(self.0.as_ptr())) }
    }

    /// Gets the module filename.
    ///
    /// May fail if the module does not have a `__file__` attribute.
    #[allow(deprecated)]
    pub fn filename<'a>(&'a self, py: Python) -> PyResult<&'a str> {
        unsafe { self.str_from_ptr(py, ffi::PyModule_GetFilename(self.0.as_ptr())) }
    }

    /// Gets the module filename object.
    ///
    /// May fail if the module does not have a `__file__` attribute.
    #[cfg(feature = "python3-sys")]
    pub fn filename_object<'a>(&'a self, py: Python) -> PyResult<PyObject> {
        let ptr = unsafe { ffi::PyModule_GetFilenameObject(self.0.as_ptr()) };
        if ptr.is_null() {
            Err(PyErr::fetch(py))
        } else {
            Ok(unsafe { PyObject::from_borrowed_ptr(py, ptr) })
        }
    }

    /// Gets a member from the module.
    /// This is equivalent to the Python expression: `getattr(module, name)`
    pub fn get(&self, py: Python, name: &str) -> PyResult<PyObject> {
        self.as_object().getattr(py, name)
    }

    /// Calls a function in the module.
    /// This is equivalent to the Python expression: `getattr(module, name)(*args, **kwargs)`
    ///
    /// `args` should be a value that, when converted to Python, results in a tuple.
    /// For this purpose, you can use:
    ///  * `cpython::NoArgs` when calling a method without any arguments
    ///  * otherwise, a Rust tuple with 1 or more elements
    ///
    /// # Example
    /// ```
    /// use cpython::NoArgs;
    /// # use cpython::Python;
    /// # let gil = Python::acquire_gil();
    /// # let py = gil.python();
    /// let sys = py.import("sys").unwrap();
    /// // Call function without arguments:
    /// let encoding = sys.call(py, "getdefaultencoding", NoArgs, None).unwrap();
    /// // Call function with a single argument:
    /// sys.call(py, "setrecursionlimit", (1000,), None).unwrap();
    /// ```
    pub fn call<A>(
        &self,
        py: Python,
        name: &str,
        args: A,
        kwargs: Option<&PyDict>,
    ) -> PyResult<PyObject>
    where
        A: ToPyObject<ObjectType = PyTuple>,
    {
        self.as_object().getattr(py, name)?.call(py, args, kwargs)
    }

    /// Adds a member to the module.
    ///
    /// This is a convenience function which can be used from the module's initialization function.
    pub fn add<V>(&self, py: Python, name: &str, value: V) -> PyResult<()>
    where
        V: ToPyObject,
    {
        self.as_object().setattr(py, name, value)
    }

    /// Adds a new extension type to the module.
    ///
    /// This is a convenience function that initializes the `py_class!()`,
    /// sets `new_type.__module__` to this module's name,
    /// and adds the type to this module.
    pub fn add_class<'p, T>(&self, py: Python<'p>) -> PyResult<()>
    where
        T: PythonObjectFromPyClassMacro,
    {
        T::add_to_module(py, self)
    }
}
<|endoftext|>


<commit_before>//! Endpoints for the media repository.
<commit_msg>Implement content/media repository endpoints.<commit_after>//! Endpoints for the media repository.

/// [GET /_matrix/media/r0/download/{serverName}/{mediaId}](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-media-r0-download-servername-mediaid)
pub mod get_content {
    /// Details about this API endpoint.
    pub struct Endpoint;

    /// This API endpoint's path parameters.
    #[derive(Clone, Debug)]
    pub struct PathParams {
        /// The media ID from the mxc:// URI (the path component).
        pub media_id: String,
        /// The server name from the mxc:// URI (the authoritory component).
        pub server_name: String,
    }

    impl ::Endpoint for Endpoint {
        type BodyParams = ();
        type PathParams = PathParams;
        type QueryParams = ();
        type Response = (); // TODO: How should a file be represented as a response?

        fn method() -> ::Method {
            ::Method::Get
        }

        fn request_path(params: Self::PathParams) -> String {
            format!(
                "/_matrix/media/r0/download/{}/{}",
                params.server_name,
                params.media_id
            )
        }

        fn router_path() -> String {
            "/_matrix/media/r0/download/:server_name/:media_id".to_string()
        }
    }
}

/// [POST /_matrix/media/r0/upload](https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-media-r0-upload)
pub mod create_content {
    /// Details about this API endpoint.
    pub struct Endpoint;

    /// This API endpoint's response.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Response {
        /// The MXC URI for the uploaded content.
        pub content_uri: String,
    }

    impl ::Endpoint for Endpoint {
        type BodyParams = (); // TODO: How should a file be represented as the request body?
        type PathParams = ();
        type QueryParams = ();
        type Response = Response;

        fn method() -> ::Method {
            ::Method::Post
        }

        fn request_path(_params: Self::PathParams) -> String {
            Self::router_path()
        }

        fn router_path() -> String {
            "/_matrix/media/r0/upload".to_string()
        }
    }
}

/// [GET /_matrix/media/r0/thumbnail/{serverName}/{mediaId}](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-media-r0-thumbnail-servername-mediaid)
pub mod get_content_thumbnail {
    use std::fmt::{Display, Error as FmtError, Formatter};

    /// Details about this API endpoint.
    pub struct Endpoint;

    /// The desired resizing method.
    #[derive(Clone, Copy, Debug)]
    pub enum Method {
        /// Crop the original to produce the requested image dimensions.
        Crop,
        /// Maintain the original aspect ratio of the source image.
        Scale,
    }

    /// This API endpoint's path parameters.
    pub struct PathParams {
        /// The media ID from the mxc:// URI (the path component).
        pub media_id: String,
        /// The server name from the mxc:// URI (the authoritory component).
        pub server_name: String,
    }

    /// This API endpoint's query string parameters.
    #[derive(Clone, Debug)]
    pub struct QueryParams {
        /// The *desired* height of the thumbnail. The actual thumbnail may not match the size
        /// specified.
        pub height: Option<u64>,
        /// The desired resizing method.
        pub method: Option<Method>,
        /// The *desired* width of the thumbnail. The actual thumbnail may not match the size
        /// specified.
        pub width: Option<u64>,
    }

    impl ::Endpoint for Endpoint {
        type BodyParams = ();
        type PathParams = PathParams;
        type QueryParams = QueryParams;
        type Response = (); // TODO: How should a file be represented as a response?

        fn method() -> ::Method {
            ::Method::Post
        }

        fn request_path(params: Self::PathParams) -> String {
            format!(
                "/_matrix/media/r0/thumbnail/{}/{}",
                params.server_name,
                params.media_id
            )
        }

        fn router_path() -> String {
            "/_matrix/media/r0/thumbnail/:server_name/:media_id".to_string()
        }
    }

    impl Display for Method {
        fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
            match *self {
                Method::Crop => write!(f, "crop"),
                Method::Scale => write!(f, "scale"),
            }
        }
    }
}
<|endoftext|>