<commit_before>use ndarray::*;
use ndarray_linalg::*;
use super::traits::*;

pub fn accuracy<A, D, F, Sc>(
    mut teo: Sc,
    init: Array<A, D>,
    dt_base: A::Real,
    step_base: usize,
    num_scale: u32,
) -> Vec<(Sc::Time, A::Real)>
where
    A: Scalar,
    D: Dimension,
    Sc: Scheme<F, Scalar = A, Dim = D, Time = A::Real>,
{
    let data: Vec<_> = (0..num_scale)
        .map(|n| {
            let rate = 2_usize.pow(n);
            let dt = dt_base / into_scalar(rate as f64);
            let t = step_base * rate;
            teo.set_dt(dt);
            (dt, iterate(&mut teo, init.clone(), t))
        })
        .collect();
    data.windows(2)
        .map(|w| {
            let dt = w[0].0;
            let dev = (&w[1].1 - &w[0].1).norm();
            (dt, dev)
        })
        .collect()
}

pub fn iterate<TEO, S>(
    teo: &mut TEO,
    x0: ArrayBase<S, TEO::Dim>,
    step: usize,
) -> ArrayBase<S, TEO::Dim>
where
    TEO: TimeEvolution,
    S: DataMut<Elem = TEO::Scalar> + DataClone,
{
    let mut ts = time_series(x0, teo);
    ts.nth(step - 1).unwrap()
}

pub struct TimeSeries<'a, TEO, S>
where
    S: DataMut<Elem = TEO::Scalar> + DataClone,
    TEO: TimeEvolution + 'a,
{
    state: ArrayBase<S, TEO::Dim>,
    teo: &'a mut TEO,
}

pub fn time_series<'a, TEO, S>(
    x0: ArrayBase<S, TEO::Dim>,
    teo: &'a mut TEO,
) -> TimeSeries<'a, TEO, S>
where
    S: DataMut<Elem = TEO::Scalar> + DataClone,
    TEO: TimeEvolution,
{
    TimeSeries {
        state: x0,
        teo: teo,
    }
}

impl<'a, TEO, A, S> TimeSeries<'a, TEO, S>
where
    A: Scalar,
    S: DataMut<Elem = A> + DataClone,
    TEO: TimeEvolution<Scalar = A>,
{
    pub fn iterate(&mut self) {
        self.teo.iterate(&mut self.state);
    }
}

impl<'a, TEO, A, S> Iterator for TimeSeries<'a, TEO, S>
where
    A: Scalar,
    S: DataMut<Elem = A> + DataClone,
    TEO: TimeEvolution<Scalar = A>,
{
    type Item = ArrayBase<S, TEO::Dim>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iterate();
        Some(self.state.clone())
    }
}

/// N-step adaptor
///
/// ```rust
/// use eom::*;
/// use eom::traits::*;
/// let teo = explicit::RK4::new(ode::Lorenz63::default(), 0.01);
/// let nstep = adaptor::nstep(teo, 10);
/// ```
#[derive(Debug, Clone)]
pub struct NStep<TEO> {
    teo: TEO,
    n: usize,
}

pub fn nstep<TEO>(teo: TEO, n: usize) -> NStep<TEO> {
    NStep { teo, n }
}

impl<TEO> ModelSpec for NStep<TEO>
where
    TEO: ModelSpec,
{
    type Scalar = TEO::Scalar;
    type Dim = TEO::Dim;

    fn model_size(&self) -> <Self::Dim as Dimension>::Pattern {
        self.teo.model_size()
    }
}

impl<TEO> TimeStep for NStep<TEO>
where
    TEO: TimeStep,
{
    type Time = TEO::Time;

    fn get_dt(&self) -> Self::Time {
        self.teo.get_dt() * into_scalar(self.n as f64)
    }

    fn set_dt(&mut self, dt: Self::Time) {
        self.teo.set_dt(dt / into_scalar(self.n as f64));
    }
}

impl<TEO> TimeEvolution for NStep<TEO>
where
    TEO: TimeEvolution,
{
    fn iterate<'a, S>(
        &mut self,
        x: &'a mut ArrayBase<S, TEO::Dim>,
    ) -> &'a mut ArrayBase<S, TEO::Dim>
    where
        S: DataMut<Elem = TEO::Scalar>,
    {
        for _ in 0..self.n {
            self.teo.iterate(x);
        }
        x
    }
}
<commit_msg>Unify trait boundary of nstep<commit_after>use ndarray::*;
use ndarray_linalg::*;
use super::traits::*;

pub fn accuracy<A, D, F, Sc>(
    mut teo: Sc,
    init: Array<A, D>,
    dt_base: A::Real,
    step_base: usize,
    num_scale: u32,
) -> Vec<(Sc::Time, A::Real)>
where
    A: Scalar,
    D: Dimension,
    Sc: Scheme<F, Scalar = A, Dim = D, Time = A::Real>,
{
    let data: Vec<_> = (0..num_scale)
        .map(|n| {
            let rate = 2_usize.pow(n);
            let dt = dt_base / into_scalar(rate as f64);
            let t = step_base * rate;
            teo.set_dt(dt);
            (dt, iterate(&mut teo, init.clone(), t))
        })
        .collect();
    data.windows(2)
        .map(|w| {
            let dt = w[0].0;
            let dev = (&w[1].1 - &w[0].1).norm();
            (dt, dev)
        })
        .collect()
}

pub fn iterate<TEO, S>(
    teo: &mut TEO,
    x0: ArrayBase<S, TEO::Dim>,
    step: usize,
) -> ArrayBase<S, TEO::Dim>
where
    TEO: TimeEvolution,
    S: DataMut<Elem = TEO::Scalar> + DataClone,
{
    let mut ts = time_series(x0, teo);
    ts.nth(step - 1).unwrap()
}

pub struct TimeSeries<'a, TEO, S>
where
    S: DataMut<Elem = TEO::Scalar> + DataClone,
    TEO: TimeEvolution + 'a,
{
    state: ArrayBase<S, TEO::Dim>,
    teo: &'a mut TEO,
}

pub fn time_series<'a, TEO, S>(
    x0: ArrayBase<S, TEO::Dim>,
    teo: &'a mut TEO,
) -> TimeSeries<'a, TEO, S>
where
    S: DataMut<Elem = TEO::Scalar> + DataClone,
    TEO: TimeEvolution,
{
    TimeSeries {
        state: x0,
        teo: teo,
    }
}

impl<'a, TEO, A, S> TimeSeries<'a, TEO, S>
where
    A: Scalar,
    S: DataMut<Elem = A> + DataClone,
    TEO: TimeEvolution<Scalar = A>,
{
    pub fn iterate(&mut self) {
        self.teo.iterate(&mut self.state);
    }
}

impl<'a, TEO, A, S> Iterator for TimeSeries<'a, TEO, S>
where
    A: Scalar,
    S: DataMut<Elem = A> + DataClone,
    TEO: TimeEvolution<Scalar = A>,
{
    type Item = ArrayBase<S, TEO::Dim>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iterate();
        Some(self.state.clone())
    }
}

/// N-step adaptor
///
/// ```rust
/// use eom::*;
/// use eom::traits::*;
/// let teo = explicit::RK4::new(ode::Lorenz63::default(), 0.01);
/// let nstep = adaptor::nstep(teo, 10);
/// ```
#[derive(Debug, Clone)]
pub struct NStep<TEO: TimeEvolution> {
    teo: TEO,
    n: usize,
}

pub fn nstep<TEO: TimeEvolution>(teo: TEO, n: usize) -> NStep<TEO> {
    NStep { teo, n }
}

impl<TEO: TimeEvolution> ModelSpec for NStep<TEO> {
    type Scalar = TEO::Scalar;
    type Dim = TEO::Dim;

    fn model_size(&self) -> <Self::Dim as Dimension>::Pattern {
        self.teo.model_size()
    }
}

impl<TEO: TimeEvolution> TimeStep for NStep<TEO> {
    type Time = TEO::Time;

    fn get_dt(&self) -> Self::Time {
        self.teo.get_dt() * into_scalar(self.n as f64)
    }

    fn set_dt(&mut self, dt: Self::Time) {
        self.teo.set_dt(dt / into_scalar(self.n as f64));
    }
}

impl<TEO: TimeEvolution> TimeEvolution for NStep<TEO> {
    fn iterate<'a, S>(
        &mut self,
        x: &'a mut ArrayBase<S, TEO::Dim>,
    ) -> &'a mut ArrayBase<S, TEO::Dim>
    where
        S: DataMut<Elem = TEO::Scalar>,
    {
        for _ in 0..self.n {
            self.teo.iterate(x);
        }
        x
    }
}
<|endoftext|>


<commit_before>// Parts of this are based on the work on alexcrichton, here:
// https://github.com/alexcrichton/git2-rs/blob/master/libgit2-sys/build.rs
//
// This has been tested on Ubuntu and it assumes that CMake is available.
// Patches are welcome to help make it work on other operating systems!

extern crate pkg_config;

use std::env;
use std::fs::{PathExt, create_dir};
use std::path::Path;
use std::process::{Command, Stdio};

fn main() {
    // Do nothing if this package is already provided by the system.
    if pkg_config::find_library("uchardet").is_ok() { return; }

    // Get our configuration from our environment.
    let mut cxxflags = env::var("CXXFLAGS").unwrap_or(String::new());
    let target = env::var("TARGET").unwrap();
    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let src = Path::new(&manifest_dir);
    let out_dir = env::var("OUT_DIR").unwrap();
    let dst = Path::new(&out_dir);

    // Fix up our build flags.
    if target.contains("i686") {
        cxxflags.push_str(" -m32");
    } else if target.contains("x86_64") {
        cxxflags.push_str(" -m64");
    }
    if !target.contains("i686") {
        cxxflags.push_str(" -fPIC");
    }

    // Make a build directory.
    let build = dst.join("build");
    // This isn't ideal but until is_dir() is stable just always try to create
    // the build directory. If it exists and error is returned, which is
    // ignored.
    create_dir(&build);

    // Set up our CMake command.
    run(Command::new("cmake")
            .current_dir(&dst.join("build"))
            .arg(&src.join("uchardet"))
            .arg("-DCMAKE_BUILD_TYPE=Release")
            .arg(&format!("-DCMAKE_INSTALL_PREFIX={}", dst.display()))
            .arg(&format!("-DCMAKE_CXX_FLAGS={}", cxxflags)));

    // Run our make command.
    run(Command::new("make")
            .current_dir(&dst.join("build"))
            .arg("install"));

    // Decide how to link our C++ runtime.  Feel free to submit patches
    // to make this work on your platform.  Other likely options are "c++"
    // and "c++abi" depending on OS and compiler.
    let cxx_abi = "stdc++";

    // Print out link instructions for Cargo.
    println!("cargo:rustc-flags=-L {} -l uchardet:static -l {}",
             dst.join("lib").display(), cxx_abi);
    println!("cargo:root={}", dst.display());
}

// Run an external build command.
fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(cmd.stdout(Stdio::inherit())
               .stderr(Stdio::inherit())
               .status()
               .unwrap()
               .success());
}
<commit_msg>Resolve issue with linking on OS X<commit_after>// Parts of this are based on the work on alexcrichton, here:
// https://github.com/alexcrichton/git2-rs/blob/master/libgit2-sys/build.rs
//
// This has been tested on Ubuntu and it assumes that CMake is available.
// Patches are welcome to help make it work on other operating systems!

extern crate pkg_config;

use std::env;
use std::fs::{PathExt, create_dir};
use std::path::Path;
use std::process::{Command, Stdio};

fn main() {
    // Do nothing if this package is already provided by the system.
    if pkg_config::find_library("uchardet").is_ok() { return; }

    // Get our configuration from our environment.
    let mut cxxflags = env::var("CXXFLAGS").unwrap_or(String::new());
    let target = env::var("TARGET").unwrap();
    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let src = Path::new(&manifest_dir);
    let out_dir = env::var("OUT_DIR").unwrap();
    let dst = Path::new(&out_dir);

    // Fix up our build flags.
    if target.contains("i686") {
        cxxflags.push_str(" -m32");
    } else if target.contains("x86_64") {
        cxxflags.push_str(" -m64");
    }
    if !target.contains("i686") {
        cxxflags.push_str(" -fPIC");
    }

    // Make a build directory.
    let build = dst.join("build");
    // This isn't ideal but until is_dir() is stable just always try to create
    // the build directory. If it exists and error is returned, which is
    // ignored.
    create_dir(&build);

    // Set up our CMake command.
    run(Command::new("cmake")
            .current_dir(&dst.join("build"))
            .arg(&src.join("uchardet"))
            .arg("-DCMAKE_BUILD_TYPE=Release")
            .arg(&format!("-DCMAKE_INSTALL_PREFIX={}", dst.display()))
            .arg(&format!("-DCMAKE_CXX_FLAGS={}", cxxflags)));

    // Run our make command.
    run(Command::new("make")
            .current_dir(&dst.join("build"))
            .arg("install"));

    // Decide how to link our C++ runtime.  Feel free to submit patches
    // to make this work on your platform.  Other likely options are "c++"
    // and "c++abi" depending on OS and compiler.
    let cxx_abi = "stdc++";

    // Print out link instructions for Cargo.
    println!("cargo:rustc-flags=-L {} -l static=uchardet -l {}",
             dst.join("lib").display(), cxx_abi);
    println!("cargo:root={}", dst.display());
}

// Run an external build command.
fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(cmd.stdout(Stdio::inherit())
               .stderr(Stdio::inherit())
               .status()
               .unwrap()
               .success());
}
<|endoftext|>


<commit_before>/// Module with interface to different tag readers
use id3::Tag as id3tag;
use metaflac::{block::Block, Tag as flactag};
use mp3_metadata;
use mp4ameta::Tag as mp4tag;
use std::{fs::File, io::BufReader, time::Duration};

#[allow(dead_code)]
#[derive(Clone)]
pub struct CommonAudioInfo {
    pub title: String,
    pub artist: String,
    pub duration: Duration,
    pub album: Option<String>,
    pub track: Option<u32>,
    pub album_artist: Option<String>,
    pub genre: Option<String>,
    pub disc: Option<u32>,
    pub total_discs: Option<u32>,
    pub total_tracks: Option<u32>,
    pub year: Option<i32>,
}

/// Trait to ensure same calls
pub trait TagReader<'a> {
    fn read_tag_from(file: &mut BufReader<File>) -> Result<CommonAudioInfo, String>;
    fn known_suffixes() -> Vec<&'a str>;
}

pub struct MP4TagReader;
impl MP4TagReader {
    pub fn read_tag_from(file_buffer: &mut BufReader<File>) -> Result<CommonAudioInfo, String> {
        match mp4tag::read_from(file_buffer.get_mut()) {
            Ok(tag) => {
                // track info need extra treatment in mp4ameta
                let try_track_info = tag.track_number();
                let (track, total_tracks) = match try_track_info {
                    Some(good_track_info) => {
                        let (track, total_tracks) = good_track_info;
                        (Some(track as u32), Some(total_tracks as u32))
                    }
                    None => (None, None),
                };
                // year needs extra treatment
                let year = tag
                    .year()
                    .map_or(None, |good_string| good_string.parse::<i32>().ok());

                let info = CommonAudioInfo {
                    title: tag.title().unwrap_or("").to_string(),
                    artist: tag.artist().unwrap_or("").to_string(),
                    duration: Duration::from_secs(tag.duration().unwrap_or(0.0) as u64),
                    album: tag.album().map(|op| op.to_string()),
                    track,
                    album_artist: tag.album_artist().map(|op| op.to_string()),
                    genre: tag.genre().map(|op| op.to_string()),
                    disc: None,        // no supported
                    total_discs: None, // no supported
                    total_tracks,
                    year,
                };
                Ok(info)
            }
            Err(e) => Err(format!("{:?}", e)),
        }
    }

    pub fn known_suffixes<'a>() -> Vec<&'a str> {
        vec!["mp4"]
    }
}

pub struct ID3TagReader;
impl ID3TagReader {
    pub fn read_tag_from(file_buffer: &mut BufReader<File>) -> Result<CommonAudioInfo, String> {
        match id3tag::read_from(file_buffer.get_mut()) {
            Ok(tag) => {
                // write into common audio info that can be analyzed
                let info = CommonAudioInfo {
                    title: tag.title().unwrap_or("").to_string(),
                    artist: tag.artist().unwrap_or("").to_string(),
                    duration: Duration::from_secs(tag.duration().unwrap_or(0) as u64),
                    album: tag.album().map(|s| s.to_string()),
                    track: tag.track(),
                    album_artist: tag.album_artist().map(|st| st.to_string()),
                    genre: tag.genre().map(|s| s.to_string()),
                    disc: tag.disc(),
                    total_discs: tag.total_discs(),
                    total_tracks: tag.total_tracks(),
                    year: tag.year(),
                };
                Ok(info)
            }
            Err(e) => Err(format!("{:?}", e)),
        }
    }

    pub fn known_suffixes<'a>() -> Vec<&'a str> {
        vec!["mpeg"]
    }
}

pub struct FlacTagReader;
impl FlacTagReader {
    pub fn read_tag_from(file_buffer: &mut BufReader<File>) -> Result<CommonAudioInfo, String> {
        match flactag::read_from(file_buffer) {
            Ok(tag_block) => {
                // try the first block
                let mut res_info = Err("vorbis comment block not found".to_string());
                for good_tag_block in tag_block.blocks() {
                    match good_tag_block {
                        Block::VorbisComment(tag) => {
                            // helper
                            let take_first_or_empty = |o: Option<&Vec<String>>| -> String {
                                (*o.map(|v_s| v_s.first().unwrap_or(&"".to_string()).clone())
                                    .unwrap_or("".to_string()))
                                .to_string()
                            };
                            let take_first_or_option = |o: Option<&Vec<String>>| -> Option<String> {
                                o.map(|v_s| Some(v_s.first().unwrap_or(&"".to_string()).clone()))
                                    .unwrap_or(None)
                            };

                            res_info = Ok(CommonAudioInfo {
                                title: take_first_or_empty(tag.title()),
                                artist: take_first_or_empty(tag.artist()),
                                // todo: duration somewhere else
                                duration: Duration::from_secs(0),
                                album: take_first_or_option(tag.album()),
                                track: tag.track(),
                                album_artist: take_first_or_option(tag.album_artist()),
                                genre: take_first_or_option(tag.genre()),
                                disc: Some(0), // tag.disc(),
                                // todo: discs, total discs, year somewhere else??
                                total_discs: Some(0), // tag.total_discs(),
                                total_tracks: tag.total_tracks(),
                                year: Some(0), //tag.year(),
                            });
                        }
                        _ => (),
                    }
                }
                res_info
            }
            Err(e) => Err(format!("{:?}", e)),
        }
    }

    pub fn known_suffixes<'a>() -> Vec<&'a str> {
        vec!["flac", "x-vorbis+ogg"]
    }
}

pub struct MP3TagReader;
impl MP3TagReader {
    pub fn read_tag_from(file_buffer: &mut BufReader<File>) -> Result<CommonAudioInfo, String> {
        match mp3_metadata::read_from_slice(file_buffer.buffer()) {
            Ok(metadata) => {
                match metadata.tag {
                    Some(tag) => {
                        // write into common audio info that can be analyzed
                        let info = CommonAudioInfo {
                            title: tag.title,
                            artist: tag.artist,
                            duration: Duration::from_secs(0),
                            album: Some(tag.album),
                            track: None,
                            album_artist: None,
                            genre: Some(format!("{:?}", tag.genre)),
                            disc: None,
                            total_discs: None,
                            total_tracks: None,
                            year: Some(tag.year as i32),
                        };
                        Ok(info)
                    }
                    None => Err("no audio tag found".to_string()),
                }
            }
            Err(e) => Err(format!("{:?}", e)),
        }
    }

    pub fn known_suffixes<'a>() -> Vec<&'a str> {
        vec!["mpeg", "mp3"]
    }
}
<commit_msg>[collection] correct trait, and add easier trait type binding by adding self<commit_after>/// Module with interface to different tag readers
use id3::Tag as id3tag;
use metaflac::{block::Block, Tag as flactag};
use mp3_metadata;
use mp4ameta::Tag as mp4tag;
use std::{fs::File, io::BufReader, time::Duration};

#[allow(dead_code)]
#[derive(Clone)]
pub struct CommonAudioInfo {
    pub title: String,
    pub artist: String,
    pub duration: Duration,
    pub album: Option<String>,
    pub track: Option<u32>,
    pub album_artist: Option<String>,
    pub genre: Option<String>,
    pub disc: Option<u32>,
    pub total_discs: Option<u32>,
    pub total_tracks: Option<u32>,
    pub year: Option<i32>,
}

/// Trait to ensure same calls
pub trait TagReader<'a> {
    fn read_tag_from(&self, file: &mut BufReader<File>) -> Result<CommonAudioInfo, String>;
    fn known_suffixes(&self) -> Vec<&'a str>;
}

pub struct MP4TagReader;
impl<'a> TagReader<'a> for MP4TagReader {
    fn read_tag_from(&self, file_buffer: &mut BufReader<File>) -> Result<CommonAudioInfo, String> {
        match mp4tag::read_from(file_buffer.get_mut()) {
            Ok(tag) => {
                // track info need extra treatment in mp4ameta
                let try_track_info = tag.track_number();
                let (track, total_tracks) = match try_track_info {
                    Some(good_track_info) => {
                        let (track, total_tracks) = good_track_info;
                        (Some(track as u32), Some(total_tracks as u32))
                    }
                    None => (None, None),
                };
                // year needs extra treatment
                let year = tag
                    .year()
                    .map_or(None, |good_string| good_string.parse::<i32>().ok());

                let info = CommonAudioInfo {
                    title: tag.title().unwrap_or("").to_string(),
                    artist: tag.artist().unwrap_or("").to_string(),
                    duration: Duration::from_secs(tag.duration().unwrap_or(0.0) as u64),
                    album: tag.album().map(|op| op.to_string()),
                    track,
                    album_artist: tag.album_artist().map(|op| op.to_string()),
                    genre: tag.genre().map(|op| op.to_string()),
                    disc: None,        // no supported
                    total_discs: None, // no supported
                    total_tracks,
                    year,
                };
                Ok(info)
            }
            Err(e) => Err(format!("{:?}", e)),
        }
    }

    fn known_suffixes(&self) -> Vec<&'a str> {
        vec!["mp4"]
    }
}

pub struct ID3TagReader;
impl<'a> TagReader<'a> for ID3TagReader {
    fn read_tag_from(&self, file_buffer: &mut BufReader<File>) -> Result<CommonAudioInfo, String> {
        match id3tag::read_from(file_buffer.get_mut()) {
            Ok(tag) => {
                // write into common audio info that can be analyzed
                let info = CommonAudioInfo {
                    title: tag.title().unwrap_or("").to_string(),
                    artist: tag.artist().unwrap_or("").to_string(),
                    duration: Duration::from_secs(tag.duration().unwrap_or(0) as u64),
                    album: tag.album().map(|s| s.to_string()),
                    track: tag.track(),
                    album_artist: tag.album_artist().map(|st| st.to_string()),
                    genre: tag.genre().map(|s| s.to_string()),
                    disc: tag.disc(),
                    total_discs: tag.total_discs(),
                    total_tracks: tag.total_tracks(),
                    year: tag.year(),
                };
                Ok(info)
            }
            Err(e) => Err(format!("{:?}", e)),
        }
    }

    fn known_suffixes(&self) -> Vec<&'a str> {
        vec!["mpeg"]
    }
}

pub struct FlacTagReader;
impl<'a> TagReader<'a> for FlacTagReader {
    fn read_tag_from(&self, file_buffer: &mut BufReader<File>) -> Result<CommonAudioInfo, String> {
        match flactag::read_from(file_buffer) {
            Ok(tag_block) => {
                // try the first block
                let mut res_info = Err("vorbis comment block not found".to_string());
                for good_tag_block in tag_block.blocks() {
                    match good_tag_block {
                        Block::VorbisComment(tag) => {
                            // helper
                            let take_first_or_empty = |o: Option<&Vec<String>>| -> String {
                                (*o.map(|v_s| v_s.first().unwrap_or(&"".to_string()).clone())
                                    .unwrap_or("".to_string()))
                                .to_string()
                            };
                            let take_first_or_option = |o: Option<&Vec<String>>| -> Option<String> {
                                o.map(|v_s| Some(v_s.first().unwrap_or(&"".to_string()).clone()))
                                    .unwrap_or(None)
                            };

                            res_info = Ok(CommonAudioInfo {
                                title: take_first_or_empty(tag.title()),
                                artist: take_first_or_empty(tag.artist()),
                                // todo: duration somewhere else
                                duration: Duration::from_secs(0),
                                album: take_first_or_option(tag.album()),
                                track: tag.track(),
                                album_artist: take_first_or_option(tag.album_artist()),
                                genre: take_first_or_option(tag.genre()),
                                disc: Some(0), // tag.disc(),
                                // todo: discs, total discs, year somewhere else??
                                total_discs: Some(0), // tag.total_discs(),
                                total_tracks: tag.total_tracks(),
                                year: Some(0), //tag.year(),
                            });
                        }
                        _ => (),
                    }
                }
                res_info
            }
            Err(e) => Err(format!("{:?}", e)),
        }
    }

    fn known_suffixes(&self) -> Vec<&'a str> {
        vec!["flac", "x-vorbis+ogg"]
    }
}

pub struct MP3TagReader;
impl<'a> TagReader<'a> for MP3TagReader {
    fn read_tag_from(&self, file_buffer: &mut BufReader<File>) -> Result<CommonAudioInfo, String> {
        match mp3_metadata::read_from_slice(file_buffer.buffer()) {
            Ok(metadata) => {
                match metadata.tag {
                    Some(tag) => {
                        // write into common audio info that can be analyzed
                        let info = CommonAudioInfo {
                            title: tag.title,
                            artist: tag.artist,
                            duration: Duration::from_secs(0),
                            album: Some(tag.album),
                            track: None,
                            album_artist: None,
                            genre: Some(format!("{:?}", tag.genre)),
                            disc: None,
                            total_discs: None,
                            total_tracks: None,
                            year: Some(tag.year as i32),
                        };
                        Ok(info)
                    }
                    None => Err("no audio tag found".to_string()),
                }
            }
            Err(e) => Err(format!("{:?}", e)),
        }
    }

    fn known_suffixes(&self) -> Vec<&'a str> {
        vec!["mpeg", "mp3"]
    }
}
<|endoftext|>


<commit_before>use std::process;
use rustyline::error::ReadlineError;
use rustyline::Editor;
use std::num::ParseIntError;

use debugger::Debugger;

pub struct Console {
    rl: Editor<'static>
}

impl Console {
    // FixMe: handle arrow key control chars, command history, etc

    pub fn new() -> Console {
        Console {
            rl: Editor::new()
        }
    }

    pub fn read(&mut self) -> Command {
        loop {
            let readline = self.rl.readline("(rustcube) ");

            match readline {
                Ok(line) => {
                    self.rl.add_history_entry(&line);
                    return Command::new(line);
                },
                Err(ReadlineError::Interrupted) => {
                    println!("CTRL-C");
                    process::exit(0);
                },
                Err(ReadlineError::Eof) => {
                    println!("CTRL-D");
                    process::exit(0);
                },
                Err(err) => {
                    println!("Error: {:?}", err);
                    process::exit(1);
                }
            }
        }
    }

    pub fn intro(&mut self) {
        println!("For help, type \"help\"");
    }
}

pub struct Command {
    data: String
}

impl Command {
    pub fn new(data: String) -> Command {
        Command {
            data: data
        }
    }

    pub fn execute(&self, debugger: &mut Debugger) {
        let args = self.data.trim().split(" ").collect::<Vec<&str>>();

        if args.len() == 0 {
            self.help(&args);
        } else {

            match args[0] {
                "advance" => self.advance(&args, debugger),
                "break" | "b" => self.break_(&args, debugger),
                "clear" => self.clear(&args, debugger),
                "continue" | "c" => self.continue_(debugger),
                "help" => self.help(&args),
                "show" => self.show(&args, debugger),
                "step" | "" => self.step(&args, debugger),
                "watch" | "w" => self.watch_(&args, debugger),
                _ => self.help(&args)
            }

        }
    }

    fn advance(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {
            match parse_hex_str(&args[1]) {
                Ok(v) => debugger.set_advance(v),
                Err(e) => println!("Error: {}", e)
            }
        } else {
            println!("Missing required argument.");
        }
        println!("FixMe: continue running till given location.");
    }

    fn break_(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {
            match parse_hex_str(&args[1]) {
                Ok(v) => debugger.add_breakpoint(v),
                Err(e) => println!("Error: {}", e)
            }
        } else {
            println!("Missing required argument.");
        }
    }

    fn watch_(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {
            match parse_hex_str(&args[1]) {
                Ok(v) => debugger.add_watchpoint(v),
                Err(e) => println!("Error: {}", e)
            }
        } else {
            println!("Missing required argument.");
        }
    }

    fn clear(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {
            match parse_hex_str(&args[1]) {
                Ok(v) => {
                    debugger.remove_breakpoint(v);
                    debugger.remove_watchpoint(v);
                },
                Err(e) => println!("Error: {}", e)
            }
        } else {
            println!("Missing required argument.");
        }
    }

    fn continue_(&self, debugger: &mut Debugger) {
        debugger.continue_();
    }

    fn help(&self, args: &Vec<&str>) {
        if args.len() < 2 {
            println!("List of available commands:\n");
            println!("advance  - continue running to given location");
            println!("break    - set a breakpoint");
            println!("clear    - delete a breakpoint");
            println!("continue - continue running program");
            println!("show     - show things about program");
            println!("step     - step a single instruction");
            println!("watch    - set a watchpoint for written value\n");
            println!("Note: the ipl starts at address 0x81300000")
        } else {
            println!("Unrecognized help command: \"{}\". Try \"help\"", args[1])
        }
    }

    fn show(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {

            match args[1] {
                "breakpoints" | "b" => {
                    for breakpoint in &debugger.breakpoints {
                        println!("break: {:#010x}", breakpoint);
                    }
                },
                "ci" => debugger.print_instruction(),
                "cia" => println!("cia: {:#010x}", debugger.gamecube.cpu.cia),
                "gpr" => {
                    for i in 0..debugger.gamecube.cpu.gpr.len() {
                        if debugger.gamecube.cpu.gpr[i] != 0 {
                            println!("r{:<10} {:#010x}    {}", i, debugger.gamecube.cpu.gpr[i], debugger.gamecube.cpu.gpr[i]);
                        }
                    }
                },
                "lr" => println!("lr: {:#010x}", debugger.gamecube.cpu.lr),
                "watchpoints" | "w" => {
                    for watchpoint in &debugger.watchpoints {
                        println!("watch: {:#010x}", watchpoint);
                    }
                },
                _ => println!("Unrecognized show command: \"{}\". Try \"help show\"", args[1])
            }

        } else {
            println!("Missing required argument.");
        }
    }

    fn step(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {
            match u32::from_str_radix(&args[1], 10) {
                Ok(v) => debugger.set_step(v),
                Err(e) => println!("Error: {}", e)
            }
        } else {
            debugger.set_step(1);
        }
    }
}

fn parse_hex_str(val: &str) -> Result<u32, ParseIntError> {
    if val.starts_with("0x") {
        u32::from_str_radix(&val[2..], 16)
    } else {
        u32::from_str_radix(val, 16)
    }
}
<commit_msg>fix unexpected listetime error<commit_after>use std::process;
use rustyline::error::ReadlineError;
use rustyline::Editor;
use std::num::ParseIntError;

use debugger::Debugger;

pub struct Console {
    rl: Editor<()>
}

impl Console {
    // FixMe: handle arrow key control chars, command history, etc

    pub fn new() -> Console {
        Console {
            rl: Editor::new()
        }
    }

    pub fn read(&mut self) -> Command {
        loop {
            let readline = self.rl.readline("(rustcube) ");

            match readline {
                Ok(line) => {
                    self.rl.add_history_entry(&line);
                    return Command::new(line);
                },
                Err(ReadlineError::Interrupted) => {
                    println!("CTRL-C");
                    process::exit(0);
                },
                Err(ReadlineError::Eof) => {
                    println!("CTRL-D");
                    process::exit(0);
                },
                Err(err) => {
                    println!("Error: {:?}", err);
                    process::exit(1);
                }
            }
        }
    }

    pub fn intro(&mut self) {
        println!("For help, type \"help\"");
    }
}

pub struct Command {
    data: String
}

impl Command {
    pub fn new(data: String) -> Command {
        Command {
            data: data
        }
    }

    pub fn execute(&self, debugger: &mut Debugger) {
        let args = self.data.trim().split(" ").collect::<Vec<&str>>();

        if args.len() == 0 {
            self.help(&args);
        } else {

            match args[0] {
                "advance" => self.advance(&args, debugger),
                "break" | "b" => self.break_(&args, debugger),
                "clear" => self.clear(&args, debugger),
                "continue" | "c" => self.continue_(debugger),
                "help" => self.help(&args),
                "show" => self.show(&args, debugger),
                "step" | "" => self.step(&args, debugger),
                "watch" | "w" => self.watch_(&args, debugger),
                _ => self.help(&args)
            }

        }
    }

    fn advance(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {
            match parse_hex_str(&args[1]) {
                Ok(v) => debugger.set_advance(v),
                Err(e) => println!("Error: {}", e)
            }
        } else {
            println!("Missing required argument.");
        }
        println!("FixMe: continue running till given location.");
    }

    fn break_(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {
            match parse_hex_str(&args[1]) {
                Ok(v) => debugger.add_breakpoint(v),
                Err(e) => println!("Error: {}", e)
            }
        } else {
            println!("Missing required argument.");
        }
    }

    fn watch_(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {
            match parse_hex_str(&args[1]) {
                Ok(v) => debugger.add_watchpoint(v),
                Err(e) => println!("Error: {}", e)
            }
        } else {
            println!("Missing required argument.");
        }
    }

    fn clear(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {
            match parse_hex_str(&args[1]) {
                Ok(v) => {
                    debugger.remove_breakpoint(v);
                    debugger.remove_watchpoint(v);
                },
                Err(e) => println!("Error: {}", e)
            }
        } else {
            println!("Missing required argument.");
        }
    }

    fn continue_(&self, debugger: &mut Debugger) {
        debugger.continue_();
    }

    fn help(&self, args: &Vec<&str>) {
        if args.len() < 2 {
            println!("List of available commands:\n");
            println!("advance  - continue running to given location");
            println!("break    - set a breakpoint");
            println!("clear    - delete a breakpoint");
            println!("continue - continue running program");
            println!("show     - show things about program");
            println!("step     - step a single instruction");
            println!("watch    - set a watchpoint for written value\n");
            println!("Note: the ipl starts at address 0x81300000")
        } else {
            println!("Unrecognized help command: \"{}\". Try \"help\"", args[1])
        }
    }

    fn show(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {

            match args[1] {
                "breakpoints" | "b" => {
                    for breakpoint in &debugger.breakpoints {
                        println!("break: {:#010x}", breakpoint);
                    }
                },
                "ci" => debugger.print_instruction(),
                "cia" => println!("cia: {:#010x}", debugger.gamecube.cpu.cia),
                "gpr" => {
                    for i in 0..debugger.gamecube.cpu.gpr.len() {
                        if debugger.gamecube.cpu.gpr[i] != 0 {
                            println!("r{:<10} {:#010x}    {}", i, debugger.gamecube.cpu.gpr[i], debugger.gamecube.cpu.gpr[i]);
                        }
                    }
                },
                "lr" => println!("lr: {:#010x}", debugger.gamecube.cpu.lr),
                "watchpoints" | "w" => {
                    for watchpoint in &debugger.watchpoints {
                        println!("watch: {:#010x}", watchpoint);
                    }
                },
                _ => println!("Unrecognized show command: \"{}\". Try \"help show\"", args[1])
            }

        } else {
            println!("Missing required argument.");
        }
    }

    fn step(&self, args: &Vec<&str>, debugger: &mut Debugger) {
        if args.len() > 1 {
            match u32::from_str_radix(&args[1], 10) {
                Ok(v) => debugger.set_step(v),
                Err(e) => println!("Error: {}", e)
            }
        } else {
            debugger.set_step(1);
        }
    }
}

fn parse_hex_str(val: &str) -> Result<u32, ParseIntError> {
    if val.starts_with("0x") {
        u32::from_str_radix(&val[2..], 16)
    } else {
        u32::from_str_radix(val, 16)
    }
}
<|endoftext|>


<commit_before>//! Converts the from ESIL/CFG representation to SSA.

use std::collections::HashMap;
use petgraph::graph::NodeIndex;
use frontend::structs::LRegInfo;
use middle::cfg::NodeData as CFGNodeData;
use middle::cfg::EdgeType as CFGEdgeType;
use middle::cfg::{CFG, BasicBlock};
use middle::ssa::{BBInfo, SSA, SSAMod, ValueType};
use middle::ssa::verifier::Verify;
use middle::ssa::verifier::VerifiedAdd;
use middle::ir::{MVal, MInst, MOpcode, MValType};
use middle::phiplacement::PhiPlacer;
use middle::regfile::SubRegisterFile;
use middle::dce;

pub type VarId = usize;

pub struct SSAConstruction<'a, T> where
	T: Clone + Verify + SSAMod<BBInfo=BBInfo> + 'a
{
	pub phiplacer: PhiPlacer<'a, T>,
	pub regfile:   SubRegisterFile,
	pub temps:     HashMap<String, T::ValueRef>,
}

impl<'a, T> SSAConstruction<'a, T> where
	T: 'a + Clone + Verify +
       SSAMod<BBInfo=BBInfo, ValueRef=NodeIndex, ActionRef=NodeIndex>
{
	pub fn new(ssa: &'a mut T, reg_info: &LRegInfo) -> SSAConstruction<'a, T> {
		let mut sc = SSAConstruction {
			phiplacer: PhiPlacer::new(ssa),
			regfile:   SubRegisterFile::new(reg_info),
			temps:     HashMap::new(),
		};
		sc.phiplacer.add_variables(vec![
								   ValueType::Integer{width: 64}, // cur
								   ValueType::Integer{width: 64},  // old
								   ValueType::Integer{width: 64}  // lastsz
		]);
		// make the following a method of regfile?
		sc.phiplacer.add_variables(sc.regfile.whole_registers.clone());
		sc
	}

	pub fn run(&mut self, cfg: &CFG) {
		let mut blocks = Vec::<T::ActionRef>::with_capacity(cfg.g.node_count());
		let bb_iter = cfg.bbs.iter();

		for _ in 0..cfg.g.node_count() {
			blocks.push(self.phiplacer.ssa.invalid_action());
		}

		{
			// Insert the entry and exit blocks for the ssa.
			let block = self.phiplacer.add_block(BBInfo { addr: 0 });
			self.phiplacer.ssa.mark_start_node(&block);
			let zero = self.phiplacer.ssa.add_const(block, 0);
			self.phiplacer.write_variable(block, 0, zero); // cur = 0
			self.phiplacer.write_variable(block, 1, zero); // old = 0

			for (i, name) in self.regfile.whole_names.iter().enumerate() {
				let argnode = self.phiplacer.ssa.add_comment(block, self.regfile.whole_registers[i], name.clone());
				self.phiplacer.write_variable(block, i+2, argnode);
			}

			blocks[cfg.entry.index()] = block;

			let block = self.phiplacer.add_dynamic();
			self.phiplacer.ssa.mark_exit_node(&block);
			blocks[cfg.exit.index()] = block;
		}

		for (addr, i) in bb_iter {
			let block = self.phiplacer.add_block(BBInfo { addr: *addr });
			blocks[i.index()] = block;
			match cfg.g[*i] {
				CFGNodeData::Block(ref srcbb) => {
					self.process_block(block, srcbb);
				}
				_ => unreachable!(),
			}
		}

		for edge in cfg.g.raw_edges() {
			let i = match edge.weight.edge_type {
				CFGEdgeType::False => 0,
				CFGEdgeType::True => 1,
				CFGEdgeType::Unconditional => 2,
			};
			self.phiplacer.ssa.add_control_edge(
				blocks[edge.source().index()],
				blocks[edge.target().index()],
				i);
		}
		for &block in &blocks {
			self.phiplacer.seal_block(block);
		}

		//self.phiplacer.ssa.stable_indexing = false;
		//self.phiplacer.ssa.cleanup();

		{
			dce::collect(self.phiplacer.ssa);
		}
		//dce::collect(self.phiplacer.ssa, &[exit_regstate]);
		//self.phiplacer.ssa.cleanup();
	}

	fn process_in(&mut self, block: T::ActionRef, mval: &MVal) -> T::ValueRef {
		match mval.val_type {
			MValType::Register  => self.regfile.read_register(&mut self.phiplacer, 2, block, &mval.name),
			MValType::Temporary => self.temps[&mval.name],
			MValType::Internal  => panic!("This value type should be eliminated during parsing"),
			MValType::EsilCur   => self.phiplacer.read_variable(block, 0),
			MValType::EsilOld   => self.phiplacer.read_variable(block, 1),
			MValType::Lastsz    => self.phiplacer.read_variable(block, 2),
			MValType::Unknown   => self.phiplacer.ssa.invalid_value(),
			                       //self.phiplacer.ssa.add_comment(block, &"Unknown".to_string()), // unimplemented!()
			MValType::Null      => self.phiplacer.ssa.invalid_value(),
		}
	}

	fn process_out(&mut self, block: T::ActionRef, mval: &MVal, value: T::ValueRef) {
		match mval.val_type {
			MValType::Register  => self.regfile.write_register(&mut self.phiplacer, 2, block, &mval.name, value),
			MValType::Temporary => {self.temps.insert(mval.name.clone(), value);},
			MValType::Null      => {},
			_                   => panic!(),
		}
	}

	fn process_op(&mut self, block: T::ActionRef, inst: &MInst, n0: T::ValueRef, n1: T::ValueRef) -> T::ValueRef {
		if inst.opcode == MOpcode::OpEq {
			return n0
		}

		let dsttype = match inst.dst.val_type {
			MValType::Null => ValueType::Integer{width: 0}, // there is no ValueType::None?
			_              => ValueType::Integer{width: inst.dst.size},
		};

		let nn = {
			// let ref mut ssa = self.phiplacer.ssa;
			// let nn = ssa.add_op(block, inst.opcode, dsttype);
			// ssa.op_use(nn, 0, n0);
			// ssa.op_use(nn, 1, n1);
			// nn
			(*self.phiplacer.ssa).verified_add_op(block, inst.opcode, dsttype, &[n0, n1])
		};

		if inst.update_flags {
			let mut nn64 = nn;

			if inst.dst.size != 64 {
				let ref mut ssa = self.phiplacer.ssa;
				nn64 = ssa.add_op(block,
					MOpcode::OpWiden(64),
					ValueType::Integer{width: 64});
				ssa.op_use(nn64, 0, nn);
			}

			let old = self.phiplacer.read_variable(block, 0);
			self.phiplacer.write_variable(block, 1, old);
			self.phiplacer.write_variable(block, 0, nn64);
		}

		return nn
	}

	fn process_block(&mut self, block: T::ActionRef, source: &BasicBlock) {
		let mut machinestate = self.phiplacer.ssa.to_value(block);
		for ref instruction in &source.instructions {
			let n0 = self.process_in(block, &instruction.operand_1);
			let n1 = self.process_in(block, &instruction.operand_2);

			if let MOpcode::OpNarrow(i) = instruction.opcode {
				println!("Found narrow. Narrow to : {}, n0: {:?}, n1: {:?},
				op1: {}, op2: {}", i, n0, n1, instruction.operand_1, instruction.operand_2);
			}

			if instruction.opcode == MOpcode::OpJmp {
				// TODO: In case of static jumps, this is trivial and does not need a selector.
				// In case of dynamic jump, the jump targets have to be determined.
				//self.ssa.g.add_edge(block, n0, SSAEdgeData::DynamicControl(0));
				break;
			}

			if instruction.opcode == MOpcode::OpCJmp {
				println!("Identified a selector: {:?} for block {:?}", n0, block);
				self.phiplacer.ssa.mark_selector(n0, block);
				continue;
			}

			let nn = self.process_op(block, instruction, n0, n1);

			if instruction.opcode == MOpcode::OpLoad {
				self.phiplacer.ssa.op_use(nn, 3, machinestate);
			}
			if instruction.opcode == MOpcode::OpStore {
				self.phiplacer.ssa.op_use(nn, 3, machinestate);
				machinestate = nn;
			}

			self.process_out(block, &instruction.dst, nn);
		}
	}
}
<commit_msg>esilssa.rs: Shift register indices up by one to make space for lastsz<commit_after>//! Converts the from ESIL/CFG representation to SSA.

use std::collections::HashMap;
use petgraph::graph::NodeIndex;
use frontend::structs::LRegInfo;
use middle::cfg::NodeData as CFGNodeData;
use middle::cfg::EdgeType as CFGEdgeType;
use middle::cfg::{CFG, BasicBlock};
use middle::ssa::{BBInfo, SSA, SSAMod, ValueType};
use middle::ssa::verifier::Verify;
use middle::ssa::verifier::VerifiedAdd;
use middle::ir::{MVal, MInst, MOpcode, MValType};
use middle::phiplacement::PhiPlacer;
use middle::regfile::SubRegisterFile;
use middle::dce;

pub type VarId = usize;

pub struct SSAConstruction<'a, T> where
	T: Clone + Verify + SSAMod<BBInfo=BBInfo> + 'a
{
	pub phiplacer: PhiPlacer<'a, T>,
	pub regfile:   SubRegisterFile,
	pub temps:     HashMap<String, T::ValueRef>,
}

impl<'a, T> SSAConstruction<'a, T> where
	T: 'a + Clone + Verify +
       SSAMod<BBInfo=BBInfo, ValueRef=NodeIndex, ActionRef=NodeIndex>
{
	pub fn new(ssa: &'a mut T, reg_info: &LRegInfo) -> SSAConstruction<'a, T> {
		let mut sc = SSAConstruction {
			phiplacer: PhiPlacer::new(ssa),
			regfile:   SubRegisterFile::new(reg_info),
			temps:     HashMap::new(),
		};
		sc.phiplacer.add_variables(vec![
								   ValueType::Integer{width: 64}, // cur
								   ValueType::Integer{width: 64}, // old
								   ValueType::Integer{width: 64}  // lastsz
		]);
		// make the following a method of regfile?
		sc.phiplacer.add_variables(sc.regfile.whole_registers.clone());
		sc
	}

	pub fn run(&mut self, cfg: &CFG) {
		let mut blocks = Vec::<T::ActionRef>::with_capacity(cfg.g.node_count());
		let bb_iter = cfg.bbs.iter();

		for _ in 0..cfg.g.node_count() {
			blocks.push(self.phiplacer.ssa.invalid_action());
		}

		{
			// Insert the entry and exit blocks for the ssa.
			let block = self.phiplacer.add_block(BBInfo { addr: 0 });
			self.phiplacer.ssa.mark_start_node(&block);
			let zero = self.phiplacer.ssa.add_const(block, 0);
			self.phiplacer.write_variable(block, 0, zero); // cur = 0
			self.phiplacer.write_variable(block, 1, zero); // old = 0
			self.phiplacer.write_variable(block, 2, zero); // lastsz = 0

			for (i, name) in self.regfile.whole_names.iter().enumerate() {
				let argnode = self.phiplacer.ssa.add_comment(block, self.regfile.whole_registers[i], name.clone());
				self.phiplacer.write_variable(block, i+3, argnode);
			}

			blocks[cfg.entry.index()] = block;

			let block = self.phiplacer.add_dynamic();
			self.phiplacer.ssa.mark_exit_node(&block);
			blocks[cfg.exit.index()] = block;
		}

		for (addr, i) in bb_iter {
			let block = self.phiplacer.add_block(BBInfo { addr: *addr });
			blocks[i.index()] = block;
			match cfg.g[*i] {
				CFGNodeData::Block(ref srcbb) => {
					self.process_block(block, srcbb);
				}
				_ => unreachable!(),
			}
		}

		for edge in cfg.g.raw_edges() {
			let i = match edge.weight.edge_type {
				CFGEdgeType::False => 0,
				CFGEdgeType::True => 1,
				CFGEdgeType::Unconditional => 2,
			};
			self.phiplacer.ssa.add_control_edge(
				blocks[edge.source().index()],
				blocks[edge.target().index()],
				i);
		}
		for &block in &blocks {
			self.phiplacer.seal_block(block);
		}

		//self.phiplacer.ssa.stable_indexing = false;
		//self.phiplacer.ssa.cleanup();

		{
			dce::collect(self.phiplacer.ssa);
		}
		//dce::collect(self.phiplacer.ssa, &[exit_regstate]);
		//self.phiplacer.ssa.cleanup();
	}

	fn process_in(&mut self, block: T::ActionRef, mval: &MVal) -> T::ValueRef {
		match mval.val_type {
			MValType::Register  => self.regfile.read_register(&mut self.phiplacer, 3, block, &mval.name),
			MValType::Temporary => self.temps[&mval.name],
			MValType::Internal  => panic!("This value type should be eliminated during parsing"),
			MValType::EsilCur   => self.phiplacer.read_variable(block, 0),
			MValType::EsilOld   => self.phiplacer.read_variable(block, 1),
			MValType::Lastsz    => self.phiplacer.read_variable(block, 2),
			MValType::Unknown   => self.phiplacer.ssa.invalid_value(),
			                       //self.phiplacer.ssa.add_comment(block, &"Unknown".to_string()), // unimplemented!()
			MValType::Null      => self.phiplacer.ssa.invalid_value(),
		}
	}

	fn process_out(&mut self, block: T::ActionRef, mval: &MVal, value: T::ValueRef) {
		match mval.val_type {
			MValType::Register  => self.regfile.write_register(&mut self.phiplacer, 3, block, &mval.name, value),
			MValType::Temporary => {self.temps.insert(mval.name.clone(), value);},
			MValType::Null      => {},
			_                   => panic!(),
		}
	}

	fn process_op(&mut self, block: T::ActionRef, inst: &MInst, n0: T::ValueRef, n1: T::ValueRef) -> T::ValueRef {
		if inst.opcode == MOpcode::OpEq {
			return n0
		}

		let dsttype = match inst.dst.val_type {
			MValType::Null => ValueType::Integer{width: 0}, // there is no ValueType::None?
			_              => ValueType::Integer{width: inst.dst.size},
		};

		let nn = {
			// let ref mut ssa = self.phiplacer.ssa;
			// let nn = ssa.add_op(block, inst.opcode, dsttype);
			// ssa.op_use(nn, 0, n0);
			// ssa.op_use(nn, 1, n1);
			// nn
			(*self.phiplacer.ssa).verified_add_op(block, inst.opcode, dsttype, &[n0, n1])
		};

		if inst.update_flags {
			let mut nn64 = nn;

			if inst.dst.size != 64 {
				let ref mut ssa = self.phiplacer.ssa;
				nn64 = ssa.add_op(block,
					MOpcode::OpWiden(64),
					ValueType::Integer{width: 64});
				ssa.op_use(nn64, 0, nn);
			}

			let old = self.phiplacer.read_variable(block, 0);
			self.phiplacer.write_variable(block, 1, old);
			self.phiplacer.write_variable(block, 0, nn64);
		}

		return nn
	}

	fn process_block(&mut self, block: T::ActionRef, source: &BasicBlock) {
		let mut machinestate = self.phiplacer.ssa.to_value(block);
		for ref instruction in &source.instructions {
			let n0 = self.process_in(block, &instruction.operand_1);
			let n1 = self.process_in(block, &instruction.operand_2);

			if let MOpcode::OpNarrow(i) = instruction.opcode {
				println!("Found narrow. Narrow to : {}, n0: {:?}, n1: {:?},
				op1: {}, op2: {}", i, n0, n1, instruction.operand_1, instruction.operand_2);
			}

			if instruction.opcode == MOpcode::OpJmp {
				// TODO: In case of static jumps, this is trivial and does not need a selector.
				// In case of dynamic jump, the jump targets have to be determined.
				//self.ssa.g.add_edge(block, n0, SSAEdgeData::DynamicControl(0));
				break;
			}

			if instruction.opcode == MOpcode::OpCJmp {
				println!("Identified a selector: {:?} for block {:?}", n0, block);
				self.phiplacer.ssa.mark_selector(n0, block);
				continue;
			}

			let nn = self.process_op(block, instruction, n0, n1);

			if instruction.opcode == MOpcode::OpLoad {
				self.phiplacer.ssa.op_use(nn, 3, machinestate);
			}
			if instruction.opcode == MOpcode::OpStore {
				self.phiplacer.ssa.op_use(nn, 3, machinestate);
				machinestate = nn;
			}

			self.process_out(block, &instruction.dst, nn);
		}
	}
}
<|endoftext|>


<commit_before>// TODO: COPYRIGHT, USE & AUTHORS

use super::ga_core::GASolution;

use std::cmp::Ordering;
use std::iter::FromIterator;

// Better name than 'Basis'?
pub enum GAPopulationSortBasis
{
    Raw,
    Scaled,
}

// Isn't a boolean enough?
pub enum GAPopulationSortOrder
{
    LowIsBest,
    HighIsBest,
}

/// Genetic Algorithm Population
// TODO: RUST DOCS!
pub struct GAPopulation<T: GASolution>
{
    population: Vec<T>,

    sort_order: GAPopulationSortOrder,

    // 'population' ordered by Raw score.
    population_order_raw: Vec<usize>,
    // Is 'population_order_raw' sorted?
    is_raw_sorted: bool,

    // 'population' ordered by Scaled score.
    population_order_scaled: Vec<usize>,
    // Is 'population_scaled' sorted?
    is_scaled_sorted: bool,

    // We keep 2 lists of indexes to the population vector.
    // One sorted by Raw Score and one by Scaled Score (Fitness).
}
impl<T: GASolution> GAPopulation<T>
{
    // TODO: New should use some parameters, maybe a Config
    pub fn new(p: Vec<T>, order: GAPopulationSortOrder) -> GAPopulation<T>
    {
        let gap = GAPopulation
                  {
                      population: p,
                      sort_order: order,
                      population_order_raw: vec![],
                      is_raw_sorted: false,
                      population_order_scaled: vec![],
                      is_scaled_sorted: false
                  };

        gap
    }

    pub fn population(&mut self) -> &mut Vec<T>
    {
        return &mut self.population
    }

    pub fn evaluate(&mut self)
    {
        for ref mut ind in &mut self.population
        {
            ind.evaluate();
        }
    }

    pub fn size(&self) -> usize
    {
        self.population.len()
    }

    //TODO: this is a temporary implementation
    pub fn select(&self) -> &T
    {
        self.individual(0, GAPopulationSortBasis::Scaled)
    }

    //TODO: This is a temporary implementation
    pub fn best(&self) -> &T
    {
        // TODO: Call GAPopulation.scale().

        self.individual(0, GAPopulationSortBasis::Scaled)
    }

    //TODO: This is a temporary implementation
    pub fn worst(&self) -> &T
    {
        self.individual(self.size()-1, GAPopulationSortBasis::Scaled)
    }

    pub fn individual(&self, i : usize, sort_basis : GAPopulationSortBasis) -> &T
    {
        // TODO: Check that i makes sense
        match sort_basis
        {
            GAPopulationSortBasis::Raw
            => { &self.population[self.population_order_raw[i]] },
            GAPopulationSortBasis::Scaled
            => { &self.population[self.population_order_scaled[i]] },
        }
    }

    pub fn sort(&mut self)
    {
        self.sort_int(false, GAPopulationSortBasis::Scaled);
        self.sort_int(false, GAPopulationSortBasis::Raw);
    }

    //TODO: I hate this name
    pub fn sort_int(&mut self, force_sort: bool, sort_basis: GAPopulationSortBasis)
    {
        let mut ordered : Vec<usize> = Vec::from_iter(0..self.size());
        match sort_basis
        {
            GAPopulationSortBasis::Raw
            =>  if (!self.is_raw_sorted) || force_sort
                {
                    match self.sort_order
                    {
                        GAPopulationSortOrder::LowIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s1].score()
                                                .partial_cmp(&self.population[*s2].score()).unwrap_or(Ordering::Equal));

                        },
                        GAPopulationSortOrder::HighIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s2].score()
                                                .partial_cmp(&self.population[*s1].score()).unwrap_or(Ordering::Equal));

                        },
                    };
                    self.population_order_raw = ordered;
                    self.is_raw_sorted = true;
                },

            GAPopulationSortBasis::Scaled
            =>  if (!self.is_scaled_sorted) || force_sort
                {
                    match self.sort_order
                    {
                        GAPopulationSortOrder::LowIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s1].fitness()
                                                .partial_cmp(&self.population[*s2].fitness()).unwrap_or(Ordering::Equal));
                        },

                        GAPopulationSortOrder::HighIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s2].fitness()
                                                .partial_cmp(&self.population[*s1].fitness()).unwrap_or(Ordering::Equal));
                        }
                    };
                    self.population_order_scaled = ordered;
                    self.is_scaled_sorted = true;
                },
        };
    }
}

#[cfg(test)]
mod test
{
}
<commit_msg>Implement Copy and Clone traits for GAPopulationSortBasis and GAPopulationSortOrder.<commit_after>// TODO: COPYRIGHT, USE & AUTHORS

use super::ga_core::GASolution;

use std::cmp::Ordering;
use std::iter::FromIterator;

// Better name than 'Basis'?
#[derive(Clone, Copy)]
pub enum GAPopulationSortBasis
{
    Raw,
    Scaled,
}

// The 'Copy' trait requires the 'Clone' trait.
// 'Copy' removes the 'move' semantics from an assignment or a function return of value.
#[derive(Clone, Copy)]
pub enum GAPopulationSortOrder
{
    LowIsBest,
    HighIsBest,
}

/// Genetic Algorithm Population
// TODO: RUST DOCS!
pub struct GAPopulation<T: GASolution>
{
    population: Vec<T>,

    sort_order: GAPopulationSortOrder,

    // 'population' ordered by Raw score.
    population_order_raw: Vec<usize>,
    // Is 'population_order_raw' sorted?
    is_raw_sorted: bool,

    // 'population' ordered by Scaled score.
    population_order_scaled: Vec<usize>,
    // Is 'population_scaled' sorted?
    is_scaled_sorted: bool,

    // We keep 2 lists of indexes to the population vector.
    // One sorted by Raw Score and one by Scaled Score (Fitness).
}
impl<T: GASolution> GAPopulation<T>
{
    // TODO: New should use some parameters, maybe a Config
    pub fn new(p: Vec<T>, order: GAPopulationSortOrder) -> GAPopulation<T>
    {
        let gap = GAPopulation
                  {
                      population: p,
                      sort_order: order,
                      population_order_raw: vec![],
                      is_raw_sorted: false,
                      population_order_scaled: vec![],
                      is_scaled_sorted: false
                  };

        gap
    }

    pub fn population(&mut self) -> &mut Vec<T>
    {
        return &mut self.population
    }

    pub fn evaluate(&mut self)
    {
        for ref mut ind in &mut self.population
        {
            ind.evaluate();
        }
    }

    pub fn size(&self) -> usize
    {
        self.population.len()
    }

    pub fn order(&self) -> GAPopulationSortOrder
    {
        // This is not a 'move', but a copy (GAPopulationSortOrder implements the
        // 'Copy' trait). A move from a borrowed reference (such as 'self') would
        // not be permitted.
        self.sort_order
    }

    //TODO: this is a temporary implementation
    pub fn select(&self) -> &T
    {
        self.individual(0, GAPopulationSortBasis::Scaled)
    }

    //TODO: This is a temporary implementation
    pub fn best(&self) -> &T
    {
        // TODO: Call GAPopulation.scale().

        self.individual(0, GAPopulationSortBasis::Scaled)
    }

    //TODO: This is a temporary implementation
    pub fn worst(&self) -> &T
    {
        self.individual(self.size()-1, GAPopulationSortBasis::Scaled)
    }

    pub fn individual(&self, i : usize, sort_basis : GAPopulationSortBasis) -> &T
    {
        // TODO: Check that i makes sense
        match sort_basis
        {
            GAPopulationSortBasis::Raw
            => { &self.population[self.population_order_raw[i]] },
            GAPopulationSortBasis::Scaled
            => { &self.population[self.population_order_scaled[i]] },
        }
    }

    pub fn sort(&mut self)
    {
        self.sort_int(false, GAPopulationSortBasis::Scaled);
        self.sort_int(false, GAPopulationSortBasis::Raw);
    }

    //TODO: I hate this name
    pub fn sort_int(&mut self, force_sort: bool, sort_basis: GAPopulationSortBasis)
    {
        let mut ordered : Vec<usize> = Vec::from_iter(0..self.size());
        match sort_basis
        {
            GAPopulationSortBasis::Raw
            =>  if (!self.is_raw_sorted) || force_sort
                {
                    match self.sort_order
                    {
                        GAPopulationSortOrder::LowIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s1].score()
                                                .partial_cmp(&self.population[*s2].score()).unwrap_or(Ordering::Equal));

                        },
                        GAPopulationSortOrder::HighIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s2].score()
                                                .partial_cmp(&self.population[*s1].score()).unwrap_or(Ordering::Equal));

                        },
                    };
                    self.population_order_raw = ordered;
                    self.is_raw_sorted = true;
                },

            GAPopulationSortBasis::Scaled
            =>  if (!self.is_scaled_sorted) || force_sort
                {
                    match self.sort_order
                    {
                        GAPopulationSortOrder::LowIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s1].fitness()
                                                .partial_cmp(&self.population[*s2].fitness()).unwrap_or(Ordering::Equal));
                        },

                        GAPopulationSortOrder::HighIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s2].fitness()
                                                .partial_cmp(&self.population[*s1].fitness()).unwrap_or(Ordering::Equal));
                        }
                    };
                    self.population_order_scaled = ordered;
                    self.is_scaled_sorted = true;
                },
        };
    }
}

#[cfg(test)]
mod test
{
}
<|endoftext|>


<commit_before>// Copyright (c) IxMilia.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

extern crate chrono;
use self::chrono::*;

extern crate uuid;
use self::uuid::Uuid;

use enum_primitive::FromPrimitive;

use ::{Color, DxfError, DxfResult};
use ::enums::*;
use ::tables::Layer;

#[doc(hidden)]
pub fn verify_code(expected: i32, actual: i32) -> DxfResult<()> {
    if expected == actual {
        Ok(())
    }
    else {
        Err(DxfError::UnexpectedCode(actual))
    }
}

#[doc(hidden)]
pub fn as_bool(v: i16) -> bool {
    v == 1
}

fn f64_to_adjusted_duration(f: f64) -> Duration {
    let days_since_dublin = f - 2415020.0; // julian dublin offset, e.g., December 31, 1899 12:00AM
    let seconds = days_since_dublin * 24.0 * 60.0 * 60.0;
    // functions consuming this need to use 1900/01/01 instead of 1899/12/31 as a base
    // so we counter the extra day and leap second here
    Duration::seconds(seconds as i64)
        - Duration::days(1)
        + Duration::seconds(1)
}

fn get_epoch<T>(timezone: &T) -> DateTime<T>
    where T: TimeZone {
    timezone.ymd(1900, 1, 1).and_hms(0, 0, 0)
}

fn as_datetime<T>(timezone: &T, date: f64) -> DateTime<T>
    where T: TimeZone {
    // dates are represented as the fractional number of days elapsed since December 31, 1899.
    let epoch = get_epoch(timezone);
    let duration = if date == 0.0 { Duration::seconds(0) } else { f64_to_adjusted_duration(date) };
    epoch + duration
}

#[doc(hidden)]
pub fn as_datetime_local(date: f64) -> DateTime<Local> {
    as_datetime(&Local, date)
}

#[doc(hidden)]
pub fn as_datetime_utc(date: f64) -> DateTime<UTC> {
    as_datetime(&UTC, date)
}

#[test]
fn as_datetime_conversion_test() {
    // from AutoDesk spec: 2451544.91568287 = 31 December 1999, 9:58:35PM
    assert_eq!(Local.ymd(1999, 12, 31).and_hms(21, 58, 35), as_datetime_local(2451544.91568287));
}

fn as_double<T>(timezone: &T, date: DateTime<T>) -> f64
    where T: TimeZone {
    let epoch = get_epoch(timezone);
    let duration = date - epoch;
    (duration.num_seconds() as f64 / 24.0 / 60.0 / 60.0) + 2415021f64
}

#[doc(hidden)]
pub fn as_double_local(date: DateTime<Local>) -> f64 {
    as_double(&Local, date)
}

#[doc(hidden)]
pub fn as_double_utc(date: DateTime<UTC>) -> f64 {
    as_double(&UTC, date)
}

#[test]
fn as_double_conversion_test() {
    // from AutoDesk spec: 2451544.91568287[04] = 31 December 1999, 9:58:35PM
    assert_eq!(2451544.9156828704, as_double_local(Local.ymd(1999, 12, 31).and_hms(21, 58, 35)));
}

#[doc(hidden)]
pub fn duration_as_double(duration: Duration) -> f64 {
    duration.num_seconds() as f64
}

#[doc(hidden)]
pub fn as_duration(d: f64) -> Duration {
    Duration::seconds(d as i64)
}

#[doc(hidden)]
pub fn as_u32(s: String) -> DxfResult<u32> {
    let mut result = 0;
    for c in s.chars() {
        match c {
            '0' => result = result * 16,
            '1' => result = result * 16 + 1,
            '2' => result = result * 16 + 2,
            '3' => result = result * 16 + 3,
            '4' => result = result * 16 + 4,
            '5' => result = result * 16 + 5,
            '6' => result = result * 16 + 6,
            '7' => result = result * 16 + 7,
            '8' => result = result * 16 + 8,
            '9' => result = result * 16 + 9,
            'A' | 'a' => result = result * 16 + 10,
            'B' | 'b' => result = result * 16 + 11,
            'C' | 'c' => result = result * 16 + 12,
            'D' | 'd' => result = result * 16 + 13,
            'E' | 'e' => result = result * 16 + 14,
            'F' | 'f' => result = result * 16 + 15,
            _ => return Err(DxfError::ParseError),
        }
    }

    Ok(result)
}

#[doc(hidden)]
pub fn as_handle(h: u32) -> String {
    format!("{:X}", h)
}

#[doc(hidden)]
pub fn as_uuid(s: String) -> DxfResult<Uuid> {
    match Uuid::parse_str(s.as_str()) {
        Ok(uuid) => Ok(uuid),
        Err(_) => Err(DxfError::ParseError),
    }
}

#[doc(hidden)]
pub fn as_i16(b: bool) -> i16 {
    if b { 1 } else { 0 }
}

#[doc(hidden)]
pub fn uuid_string(u: &Uuid) -> String {
    format!("{}", u)
}

#[doc(hidden)]
pub fn default_if_empty(val: &String, default: &str) -> String {
    if val.is_empty() { String::from(default) } else { val.clone() }
}

#[doc(hidden)]
pub fn ensure_positive_or_default(val: f64, default: f64) -> f64 {
    if val <= 0.0 { default } else { val }
}

#[doc(hidden)]
pub fn ensure_positive_or_default_i32(val: i32, default: i32) -> i32 {
    if val <= 0 { default } else { val }
}

#[doc(hidden)]
pub fn ensure_positive_or_default_i16(val: i16, default: i16) -> i16 {
    if val <= 0 { default } else { val }
}

#[doc(hidden)]
pub fn get_writable_linetype_name<'a>(val: &'a str) -> &'a str {
    if val.is_empty() { "CONTINUOUS" } else { val }
}

#[doc(hidden)]
pub fn clipping_from_bool(b: bool) -> Option<XrefClippingBoundaryVisibility> {
    XrefClippingBoundaryVisibility::from_i16(if b { 1 } else { 0 })
}

#[doc(hidden)]
pub fn bool_from_clipping(c: XrefClippingBoundaryVisibility) -> bool {
    c != XrefClippingBoundaryVisibility::NotDisplayedNotPlotted
}

#[doc(hidden)]
pub fn parse_bool(s: String) -> DxfResult<bool> {
    match parse_i16(s) {
        Ok(0) => Ok(false),
        Ok(_) => Ok(true),
        Err(x) => Err(x),
    }
}

#[test]
fn parse_bool_test() {
    assert_eq!(true, parse_bool("  2 ".to_string()).unwrap());
}

#[doc(hidden)]
pub fn parse_f64(s: String) -> DxfResult<f64> {
    match s.trim().parse::<f64>() {
        Ok(d) => Ok(d),
        Err(e) => Err(DxfError::ParseFloatError(e)),
    }
}

#[test]
fn parse_f64_test() {
    assert_eq!(3.14, parse_f64("  3.14 ".to_string()).unwrap());
}

#[doc(hidden)]
pub fn parse_i32(s: String) -> DxfResult<i32> {
    match s.trim().parse::<i32>() {
        Ok(i) => Ok(i),
        Err(e) => Err(DxfError::ParseIntError(e)),
    }
}

#[test]
fn parse_i32_test() {
    assert_eq!(2, parse_i32("  2 ".to_string()).unwrap());
}

#[doc(hidden)]
pub fn parse_i64(s: String) -> DxfResult<i64> {
    match s.trim().parse::<i64>() {
        Ok(l) => Ok(l),
        Err(e) => Err(DxfError::ParseIntError(e)),
    }
}

#[test]
fn parse_i64_test() {
    assert_eq!(2, parse_i64("  2 ".to_string()).unwrap());
}

#[doc(hidden)]
pub fn parse_i16(s: String) -> DxfResult<i16> {
    match s.trim().parse::<i16>() {
        Ok(s) => Ok(s),
        Err(e) => Err(DxfError::ParseIntError(e)),
    }
}

#[test]
fn parse_i16_test() {
    assert_eq!(2, parse_i16("  2 ".to_string()).unwrap());
}

#[doc(hidden)]
pub fn trim_trailing_newline(s: &mut String) {
    if s.ends_with('\n') {
        s.pop();
        if s.ends_with('\r') {
            s.pop();
        }
    }
}

#[doc(hidden)]
pub fn read_color_value(layer: &mut Layer, color: i16) -> Color {
    layer.is_layer_on = color >= 0;
    Color::from_raw_value(color.abs())
}
<commit_msg>enable parsing malformed i16 values<commit_after>// Copyright (c) IxMilia.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

extern crate chrono;
use self::chrono::*;

extern crate uuid;
use self::uuid::Uuid;

use enum_primitive::FromPrimitive;

use ::{Color, DxfError, DxfResult};
use ::enums::*;
use ::tables::Layer;

#[doc(hidden)]
pub fn verify_code(expected: i32, actual: i32) -> DxfResult<()> {
    if expected == actual {
        Ok(())
    }
    else {
        Err(DxfError::UnexpectedCode(actual))
    }
}

#[doc(hidden)]
pub fn as_bool(v: i16) -> bool {
    v == 1
}

fn f64_to_adjusted_duration(f: f64) -> Duration {
    let days_since_dublin = f - 2415020.0; // julian dublin offset, e.g., December 31, 1899 12:00AM
    let seconds = days_since_dublin * 24.0 * 60.0 * 60.0;
    // functions consuming this need to use 1900/01/01 instead of 1899/12/31 as a base
    // so we counter the extra day and leap second here
    Duration::seconds(seconds as i64)
        - Duration::days(1)
        + Duration::seconds(1)
}

fn get_epoch<T>(timezone: &T) -> DateTime<T>
    where T: TimeZone {
    timezone.ymd(1900, 1, 1).and_hms(0, 0, 0)
}

fn as_datetime<T>(timezone: &T, date: f64) -> DateTime<T>
    where T: TimeZone {
    // dates are represented as the fractional number of days elapsed since December 31, 1899.
    let epoch = get_epoch(timezone);
    let duration = if date == 0.0 { Duration::seconds(0) } else { f64_to_adjusted_duration(date) };
    epoch + duration
}

#[doc(hidden)]
pub fn as_datetime_local(date: f64) -> DateTime<Local> {
    as_datetime(&Local, date)
}

#[doc(hidden)]
pub fn as_datetime_utc(date: f64) -> DateTime<UTC> {
    as_datetime(&UTC, date)
}

#[test]
fn as_datetime_conversion_test() {
    // from AutoDesk spec: 2451544.91568287 = 31 December 1999, 9:58:35PM
    assert_eq!(Local.ymd(1999, 12, 31).and_hms(21, 58, 35), as_datetime_local(2451544.91568287));
}

fn as_double<T>(timezone: &T, date: DateTime<T>) -> f64
    where T: TimeZone {
    let epoch = get_epoch(timezone);
    let duration = date - epoch;
    (duration.num_seconds() as f64 / 24.0 / 60.0 / 60.0) + 2415021f64
}

#[doc(hidden)]
pub fn as_double_local(date: DateTime<Local>) -> f64 {
    as_double(&Local, date)
}

#[doc(hidden)]
pub fn as_double_utc(date: DateTime<UTC>) -> f64 {
    as_double(&UTC, date)
}

#[test]
fn as_double_conversion_test() {
    // from AutoDesk spec: 2451544.91568287[04] = 31 December 1999, 9:58:35PM
    assert_eq!(2451544.9156828704, as_double_local(Local.ymd(1999, 12, 31).and_hms(21, 58, 35)));
}

#[doc(hidden)]
pub fn duration_as_double(duration: Duration) -> f64 {
    duration.num_seconds() as f64
}

#[doc(hidden)]
pub fn as_duration(d: f64) -> Duration {
    Duration::seconds(d as i64)
}

#[doc(hidden)]
pub fn as_u32(s: String) -> DxfResult<u32> {
    let mut result = 0;
    for c in s.chars() {
        match c {
            '0' => result = result * 16,
            '1' => result = result * 16 + 1,
            '2' => result = result * 16 + 2,
            '3' => result = result * 16 + 3,
            '4' => result = result * 16 + 4,
            '5' => result = result * 16 + 5,
            '6' => result = result * 16 + 6,
            '7' => result = result * 16 + 7,
            '8' => result = result * 16 + 8,
            '9' => result = result * 16 + 9,
            'A' | 'a' => result = result * 16 + 10,
            'B' | 'b' => result = result * 16 + 11,
            'C' | 'c' => result = result * 16 + 12,
            'D' | 'd' => result = result * 16 + 13,
            'E' | 'e' => result = result * 16 + 14,
            'F' | 'f' => result = result * 16 + 15,
            _ => return Err(DxfError::ParseError),
        }
    }

    Ok(result)
}

#[doc(hidden)]
pub fn as_handle(h: u32) -> String {
    format!("{:X}", h)
}

#[doc(hidden)]
pub fn as_uuid(s: String) -> DxfResult<Uuid> {
    match Uuid::parse_str(s.as_str()) {
        Ok(uuid) => Ok(uuid),
        Err(_) => Err(DxfError::ParseError),
    }
}

#[doc(hidden)]
pub fn as_i16(b: bool) -> i16 {
    if b { 1 } else { 0 }
}

#[doc(hidden)]
pub fn uuid_string(u: &Uuid) -> String {
    format!("{}", u)
}

#[doc(hidden)]
pub fn default_if_empty(val: &String, default: &str) -> String {
    if val.is_empty() { String::from(default) } else { val.clone() }
}

#[doc(hidden)]
pub fn ensure_positive_or_default(val: f64, default: f64) -> f64 {
    if val <= 0.0 { default } else { val }
}

#[doc(hidden)]
pub fn ensure_positive_or_default_i32(val: i32, default: i32) -> i32 {
    if val <= 0 { default } else { val }
}

#[doc(hidden)]
pub fn ensure_positive_or_default_i16(val: i16, default: i16) -> i16 {
    if val <= 0 { default } else { val }
}

#[doc(hidden)]
pub fn get_writable_linetype_name<'a>(val: &'a str) -> &'a str {
    if val.is_empty() { "CONTINUOUS" } else { val }
}

#[doc(hidden)]
pub fn clipping_from_bool(b: bool) -> Option<XrefClippingBoundaryVisibility> {
    XrefClippingBoundaryVisibility::from_i16(if b { 1 } else { 0 })
}

#[doc(hidden)]
pub fn bool_from_clipping(c: XrefClippingBoundaryVisibility) -> bool {
    c != XrefClippingBoundaryVisibility::NotDisplayedNotPlotted
}

#[doc(hidden)]
pub fn parse_bool(s: String) -> DxfResult<bool> {
    match parse_i16(s) {
        Ok(0) => Ok(false),
        Ok(_) => Ok(true),
        Err(x) => Err(x),
    }
}

#[test]
fn parse_bool_test() {
    assert_eq!(true, parse_bool("  2 ".to_string()).unwrap());
}

#[doc(hidden)]
pub fn parse_f64(s: String) -> DxfResult<f64> {
    match s.trim().parse::<f64>() {
        Ok(d) => Ok(d),
        Err(e) => Err(DxfError::ParseFloatError(e)),
    }
}

#[test]
fn parse_f64_test() {
    assert_eq!(3.14, parse_f64("  3.14 ".to_string()).unwrap());
}

#[doc(hidden)]
pub fn parse_i32(s: String) -> DxfResult<i32> {
    match s.trim().parse::<i32>() {
        Ok(i) => Ok(i),
        Err(e) => Err(DxfError::ParseIntError(e)),
    }
}

#[test]
fn parse_i32_test() {
    assert_eq!(2, parse_i32("  2 ".to_string()).unwrap());
}

#[doc(hidden)]
pub fn parse_i64(s: String) -> DxfResult<i64> {
    match s.trim().parse::<i64>() {
        Ok(l) => Ok(l),
        Err(e) => Err(DxfError::ParseIntError(e)),
    }
}

#[test]
fn parse_i64_test() {
    assert_eq!(2, parse_i64("  2 ".to_string()).unwrap());
}

#[doc(hidden)]
pub fn parse_i16(s: String) -> DxfResult<i16> {
    match s.trim().parse::<f64>() {
        Ok(s) => Ok(s as i16),
        Err(e) => Err(DxfError::ParseFloatError(e)),
    }
}

#[test]
fn parse_i16_test() {
    assert_eq!(2, parse_i16("  2 ".to_string()).unwrap());

    // some files write shorts as a double
    assert_eq!(2, parse_i16(" 2.0 ".to_string()).unwrap());
}

#[doc(hidden)]
pub fn trim_trailing_newline(s: &mut String) {
    if s.ends_with('\n') {
        s.pop();
        if s.ends_with('\r') {
            s.pop();
        }
    }
}

#[doc(hidden)]
pub fn read_color_value(layer: &mut Layer, color: i16) -> Color {
    layer.is_layer_on = color >= 0;
    Color::from_raw_value(color.abs())
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::fs::{File, Metadata};
use std::io;
use std::path::Path;
use gfx;
use mmap;

use array::*;
use chunk::{
    BiomeId,
    BlockState,
    Chunk,
    ChunkColumn,
    EMPTY_CHUNK,
    LightLevel,
    SIZE
};
use minecraft::nbt::Nbt;

pub struct Region {
    mmap: mmap::MemoryMap,
}

fn array_16x16x16<T, F>(mut f: F) -> [[[T; SIZE]; SIZE]; SIZE]
    where F: FnMut(usize, usize, usize) -> T
{
    Array::from_fn(|y| -> [[T; SIZE]; SIZE] {
        Array::from_fn(|z| -> [T; 16] {
            Array::from_fn(|x| f(x, y, z))
        })
    })
}

impl Region {
    pub fn open(filename: &Path) -> io::Result<Region> {
        #[cfg(not(windows))]
        fn map_fd(file: &File) -> mmap::MapOption {
            use std::os::unix::io::AsRawFd;
            mmap::MapOption::MapFd(file.as_raw_fd())
        }

        #[cfg(windows)]
        fn map_fd(file: &File) -> mmap::MapOption {
            use std::os::windows::io::AsRawHandle;
            let handle: libc::HANDLE = file.as_raw_handle() as libc::HANDLE;
            mmap::MapOption::MapFd(handle)
        }

        let file = try!(File::open(filename));
        let stat: Metadata = try!(file.metadata());
        let min_len = stat.len() as usize;
        let options = &[
            map_fd(&file),
            mmap::MapOption::MapReadable
        ];
        let res = Region {
            mmap: mmap::MemoryMap::new(min_len, options).unwrap()
        };
        Ok(res)
    }

    fn as_slice<'a>(&'a self) -> &'a [u8] {
        use std::slice;
        unsafe {
            slice::from_raw_parts(self.mmap.data() as *const u8, self.mmap.len())
        }
    }

    pub fn get_chunk_column<R: gfx::Resources>(&self, x: u8, z: u8)
                            -> Option<ChunkColumn<R>> {
        let locations = &self.as_slice()[..4096];
        let i = 4 * ((x % 32) as usize + (z % 32) as usize * 32);
        let start = ((locations[i] as usize) << 16)
                  | ((locations[i + 1] as usize) << 8)
                  | (locations[i + 2] as usize);
        let num = locations[i + 3] as usize;
        if start == 0 || num == 0 { return None; }
        let sectors = &self.as_slice()[start * 4096 .. (start + num) * 4096];
        let len = ((sectors[0] as usize) << 24)
                | ((sectors[1] as usize) << 16)
                | ((sectors[2] as usize) << 8)
                | (sectors[3] as usize);
        let nbt = match sectors[4] {
            1 => Nbt::from_gzip(&sectors[5 .. 4 + len]),
            2 => Nbt::from_zlib(&sectors[5 .. 4 + len]),
            c => panic!("unknown region chunk compression method {}", c)
        };

        let mut c = nbt.unwrap().into_compound().unwrap();
        let mut level = c.remove("Level").unwrap().into_compound().unwrap();
        let mut chunks = Vec::new();
        for chunk in level.remove("Sections")
            .unwrap().into_compound_list().unwrap().into_iter() {

            let y = chunk.get("Y")
                .unwrap().as_byte().unwrap();
            let blocks = chunk.get("Blocks")
                .unwrap().as_bytearray().unwrap();
            let blocks_top = chunk.get("Add")
                .and_then(|x| x.as_bytearray());
            let blocks_data = chunk.get("Data")
                .unwrap().as_bytearray().unwrap();
            let block_light = chunk.get("BlockLight")
                .unwrap().as_bytearray().unwrap();
            let sky_light = chunk.get("SkyLight")
                .unwrap().as_bytearray().unwrap();

            let chunk = Chunk {
                blocks: array_16x16x16(|x, y, z| {
                    let i = (y * SIZE + z) * SIZE + x;
                    let top = match blocks_top {
                        Some(blocks_top) => {
                            (blocks_top[i >> 1] >> ((i & 1) * 4)) & 0x0f
                        }
                        None => 0
                    };
                    let data = (blocks_data[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    BlockState {
                        value: ((blocks[i] as u16) << 4)
                             | ((top as u16) << 12)
                             | (data as u16)
                    }
                }),
                light_levels: array_16x16x16(|x, y, z| {
                    let i = (y * 16 + z) * 16 + x;
                    let block = (block_light[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    let sky = (sky_light[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    LightLevel {
                        value: block | (sky << 4)
                    }
                }),
            };
            while chunks.len() <= y as usize {
                chunks.push(*EMPTY_CHUNK);
            }
            chunks[y as usize] = chunk;
        }
        let biomes = level.get("Biomes")
            .unwrap().as_bytearray().unwrap();
        Some(ChunkColumn {
            chunks: chunks,
            buffers: Array::from_fn(|_| RefCell::new(None)),
            biomes: Array::from_fn(|z| -> [BiomeId; SIZE] {
                Array::from_fn(|x| {
                    BiomeId {
                        value: biomes[z * SIZE + x]
                    }
                })
            })
        })
    }
}
<commit_msg>Fixed libc usage for windows<commit_after>use std::cell::RefCell;
use std::fs::{File, Metadata};
use std::io;
use std::path::Path;
use gfx;
use mmap;

use array::*;
use chunk::{
    BiomeId,
    BlockState,
    Chunk,
    ChunkColumn,
    EMPTY_CHUNK,
    LightLevel,
    SIZE
};
use minecraft::nbt::Nbt;

pub struct Region {
    mmap: mmap::MemoryMap,
}

fn array_16x16x16<T, F>(mut f: F) -> [[[T; SIZE]; SIZE]; SIZE]
    where F: FnMut(usize, usize, usize) -> T
{
    Array::from_fn(|y| -> [[T; SIZE]; SIZE] {
        Array::from_fn(|z| -> [T; 16] {
            Array::from_fn(|x| f(x, y, z))
        })
    })
}

impl Region {
    pub fn open(filename: &Path) -> io::Result<Region> {
        #[cfg(not(windows))]
        fn map_fd(file: &File) -> mmap::MapOption {
            use std::os::unix::io::AsRawFd;
            mmap::MapOption::MapFd(file.as_raw_fd())
        }

        #[cfg(windows)]
        fn map_fd(file: &File) -> mmap::MapOption {
            use libc;
            use std::os::windows::io::AsRawHandle;
            let handle = file.as_raw_handle() as libc::HANDLE;
            mmap::MapOption::MapFd(handle)
        }

        let file = try!(File::open(filename));
        let stat: Metadata = try!(file.metadata());
        let min_len = stat.len() as usize;
        let options = &[
            map_fd(&file),
            mmap::MapOption::MapReadable
        ];
        let res = Region {
            mmap: mmap::MemoryMap::new(min_len, options).unwrap()
        };
        Ok(res)
    }

    fn as_slice<'a>(&'a self) -> &'a [u8] {
        use std::slice;
        unsafe {
            slice::from_raw_parts(self.mmap.data() as *const u8, self.mmap.len())
        }
    }

    pub fn get_chunk_column<R: gfx::Resources>(&self, x: u8, z: u8)
                            -> Option<ChunkColumn<R>> {
        let locations = &self.as_slice()[..4096];
        let i = 4 * ((x % 32) as usize + (z % 32) as usize * 32);
        let start = ((locations[i] as usize) << 16)
                  | ((locations[i + 1] as usize) << 8)
                  | (locations[i + 2] as usize);
        let num = locations[i + 3] as usize;
        if start == 0 || num == 0 { return None; }
        let sectors = &self.as_slice()[start * 4096 .. (start + num) * 4096];
        let len = ((sectors[0] as usize) << 24)
                | ((sectors[1] as usize) << 16)
                | ((sectors[2] as usize) << 8)
                | (sectors[3] as usize);
        let nbt = match sectors[4] {
            1 => Nbt::from_gzip(&sectors[5 .. 4 + len]),
            2 => Nbt::from_zlib(&sectors[5 .. 4 + len]),
            c => panic!("unknown region chunk compression method {}", c)
        };

        let mut c = nbt.unwrap().into_compound().unwrap();
        let mut level = c.remove("Level").unwrap().into_compound().unwrap();
        let mut chunks = Vec::new();
        for chunk in level.remove("Sections")
            .unwrap().into_compound_list().unwrap().into_iter() {

            let y = chunk.get("Y")
                .unwrap().as_byte().unwrap();
            let blocks = chunk.get("Blocks")
                .unwrap().as_bytearray().unwrap();
            let blocks_top = chunk.get("Add")
                .and_then(|x| x.as_bytearray());
            let blocks_data = chunk.get("Data")
                .unwrap().as_bytearray().unwrap();
            let block_light = chunk.get("BlockLight")
                .unwrap().as_bytearray().unwrap();
            let sky_light = chunk.get("SkyLight")
                .unwrap().as_bytearray().unwrap();

            let chunk = Chunk {
                blocks: array_16x16x16(|x, y, z| {
                    let i = (y * SIZE + z) * SIZE + x;
                    let top = match blocks_top {
                        Some(blocks_top) => {
                            (blocks_top[i >> 1] >> ((i & 1) * 4)) & 0x0f
                        }
                        None => 0
                    };
                    let data = (blocks_data[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    BlockState {
                        value: ((blocks[i] as u16) << 4)
                             | ((top as u16) << 12)
                             | (data as u16)
                    }
                }),
                light_levels: array_16x16x16(|x, y, z| {
                    let i = (y * 16 + z) * 16 + x;
                    let block = (block_light[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    let sky = (sky_light[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    LightLevel {
                        value: block | (sky << 4)
                    }
                }),
            };
            while chunks.len() <= y as usize {
                chunks.push(*EMPTY_CHUNK);
            }
            chunks[y as usize] = chunk;
        }
        let biomes = level.get("Biomes")
            .unwrap().as_bytearray().unwrap();
        Some(ChunkColumn {
            chunks: chunks,
            buffers: Array::from_fn(|_| RefCell::new(None)),
            biomes: Array::from_fn(|z| -> [BiomeId; SIZE] {
                Array::from_fn(|x| {
                    BiomeId {
                        value: biomes[z * SIZE + x]
                    }
                })
            })
        })
    }
}
<|endoftext|>