<commit_before>#![feature(plugin, custom_derive)]
#![feature(downgraded_weak)]

#![plugin(clippy)]
#![plugin(serde_macros)]
#![plugin(docopt_macros)]

#![recursion_limit="128"]

extern crate env_logger;
extern crate mio;
#[macro_use] extern crate mioco;
extern crate trust_dns;
extern crate rand;
#[macro_use] extern crate quick_error;
#[macro_use] extern crate log;
extern crate byteorder;
extern crate itertools;
#[macro_use] extern crate custom_derive;
#[macro_use] extern crate newtype_derive;
extern crate serde;
extern crate serde_yaml;
extern crate treebitmap;
extern crate rustc_serialize;
extern crate docopt;

mod utils;
mod transport;
mod cache;
mod nscache;
mod query;
mod serve;
mod resolver;
mod config;
mod recursive;
mod forwarding;

use std::net::{SocketAddr};

use resolver::RcResolver;
use serve::{serve_tcp, serve_udp};
use config::Config;

docopt!(Args, "
Usage: euphonium [options]
       euphonium (--help|--version)

Options:
    -c CONFIG, --config CONFIG      Specify configuration file [default: euphonium.yaml]
");

fn mioco_config_start<F, T>(f: F) -> std::thread::Result<T>
    where F: FnOnce() -> T,
          F: Send + 'static,
          T: Send + 'static
{
    let mut config = mioco::Config::new();
    config.set_catch_panics(false);
    mioco::Mioco::new_configured(config).start(f)
}
fn main() {
    env_logger::init().expect("What the ...?");
    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());
    let config = Config::from_file(&args.flag_config)
    .unwrap_or_else(|e| {
        debug!("Error: {:?}", e);
        error!("Failed to load configuration file {}: {}", args.flag_config, e);
        std::process::exit(1);
    });

    mioco_config_start(move || {
        let ip = config.serve.ip;
        let port = config.serve.port;
        let addr = SocketAddr::new(ip, port);
        info!("Listening on {}:{}", ip, port);

        let resolver = RcResolver::new(config);
        serve_tcp(&addr, resolver.clone()).expect("Failed to initialize TCP listener");
        serve_udp(&addr, resolver).expect("Failed to initialize UDP listener");
    }).expect("Unexpected error from mioco::start");
}
<commit_msg>Actually implement --version<commit_after>#![feature(plugin, custom_derive)]
#![feature(downgraded_weak)]

#![plugin(clippy)]
#![plugin(serde_macros)]
#![plugin(docopt_macros)]

#![recursion_limit="128"]

extern crate env_logger;
extern crate mio;
#[macro_use] extern crate mioco;
extern crate trust_dns;
extern crate rand;
#[macro_use] extern crate quick_error;
#[macro_use] extern crate log;
extern crate byteorder;
extern crate itertools;
#[macro_use] extern crate custom_derive;
#[macro_use] extern crate newtype_derive;
extern crate serde;
extern crate serde_yaml;
extern crate treebitmap;
extern crate rustc_serialize;
extern crate docopt;

mod utils;
mod transport;
mod cache;
mod nscache;
mod query;
mod serve;
mod resolver;
mod config;
mod recursive;
mod forwarding;

use std::net::{SocketAddr};

use resolver::RcResolver;
use serve::{serve_tcp, serve_udp};
use config::Config;

docopt!(Args, "
Usage: euphonium [options]
       euphonium (--help|--version)

Options:
    -c CONFIG, --config CONFIG      Specify configuration file [default: euphonium.yaml]
");
const VERSION_FULL: &'static str = concat!(
    env!("CARGO_PKG_NAME"), " ", env!("CARGO_PKG_VERSION"),
);

fn mioco_config_start<F, T>(f: F) -> std::thread::Result<T>
    where F: FnOnce() -> T,
          F: Send + 'static,
          T: Send + 'static
{
    let mut config = mioco::Config::new();
    config.set_catch_panics(false);
    mioco::Mioco::new_configured(config).start(f)
}
fn main() {
    env_logger::init().expect("What the ...?");
    let args: Args = Args::docopt().version(Some(VERSION_FULL.into())).decode()
    .unwrap_or_else(|e| e.exit());
    let config = Config::from_file(&args.flag_config)
    .unwrap_or_else(|e| {
        debug!("Error: {:?}", e);
        error!("Failed to load configuration file {}: {}", args.flag_config, e);
        std::process::exit(1);
    });

    mioco_config_start(move || {
        let ip = config.serve.ip;
        let port = config.serve.port;
        let addr = SocketAddr::new(ip, port);
        info!("Listening on {}:{}", ip, port);

        let resolver = RcResolver::new(config);
        serve_tcp(&addr, resolver.clone()).expect("Failed to initialize TCP listener");
        serve_udp(&addr, resolver).expect("Failed to initialize UDP listener");
    }).expect("Unexpected error from mioco::start");
}
<|endoftext|>


<commit_before>#![feature(lang_items, unboxed_closures)]

use std::io::{File, IoResult, Truncate, Write};
use std::f64::consts::PI;
use std::num::Float;
use std::num::FloatMath;
use std::rand;
use std::rand::Rng;

struct SineWave(pub f64);

impl Fn<(f64, ), f64> for SineWave {
    extern "rust-call" fn call(&self, (t, ): (f64, )) -> f64 {
        let SineWave(frequency) = *self;
        FloatMath::sin(t * frequency * 2.0 * PI)
    }
}

struct SquareWave(pub f64);

impl Fn<(f64, ), f64> for SquareWave {
    extern "rust-call" fn call(&self, (t, ): (f64, )) -> f64 {
        let SquareWave(frequency) = *self;
        let sin_wave = SineWave(frequency);
        if sin_wave(t).is_positive() { 1.0 } else { -1.0 }
    }
}

struct SawtoothWave(pub f64);

impl Fn<(f64, ), f64> for SawtoothWave {
    extern "rust-call" fn call(&self, (t, ): (f64, )) -> f64 {
        let SawtoothWave(frequency) = *self;
        let t_factor = t * frequency;
        t_factor - t_factor.floor()
    }
}

fn generate<F>(x: f64, f: F) -> f64 where F: Fn<(f64, ), f64> {
    f(x)
}

fn quantize_16(y: f64) -> i16 {
    // Quantization levels for 16 bits
    let levels = 2.0.powf(16.0) - 1.0;

    // Convert from [-1, 1] to [-2**16 / 2, 2**16 / 2]
    (y * (levels / 2.0)) as i16
}

fn make_sample_16<F>(length: f64, sample_rate: uint, waveform: F) -> Vec<i16> where F: Fn<(f64, ), f64>+Copy {
    let num_samples = (sample_rate as f64 * length).floor() as uint;
    let mut samples: Vec<i16> = Vec::with_capacity(num_samples);

    for i in range(0u, num_samples) {
        let t = i as f64 / sample_rate as f64;
        samples.push(quantize_16(generate(t, waveform)));
    }

    samples
}

fn write_pcm(filename: &str, samples: Vec<i16>) -> IoResult<()> {
    let path = Path::new(filename);
    let mut f = match File::open_mode(&path, Truncate, Write) {
        Ok(f) => f,
        Err(e) => panic!("File error: {}", e)
    };

    for sample in samples.iter() {
        try!(f.write_le_i16(*sample));
    }

    Ok(())
}

// See: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
fn write_wav(filename: &str, sample_rate: uint, samples: Vec<i16>) -> IoResult<()> {
    let path = Path::new(filename);
    let mut f = match File::open_mode(&path, Truncate, Write) {
        Ok(f) => f,
        Err(e) => panic!("File error: {}", e)
    };

    // Some WAV header fields
    let channels = 1;
    let bit_depth = 16;
    let subchunk_2_size = samples.len() * channels * bit_depth / 8;
    let chunk_size = 36 + subchunk_2_size as i32;
    let byte_rate = (sample_rate * channels * bit_depth / 8) as i32;
    let block_align = (channels * bit_depth / 8) as i16;

    try!(f.write_be_i32(0x52494646))              // ChunkID, RIFF
    try!(f.write_le_i32(chunk_size));             // ChunkSize
    try!(f.write_be_i32(0x57415645));             // Format, WAVE

    try!(f.write_be_i32(0x666d7420));             // Subchunk1ID, fmt
    try!(f.write_le_i32(16));                     // Subchunk1Size, 16 for PCM
    try!(f.write_le_i16(1));                      // AudioFormat, PCM = 1 (linear quantization)
    try!(f.write_le_i16(channels as i16));        // NumChannels
    try!(f.write_le_i32(sample_rate as i32));     // SampleRate
    try!(f.write_le_i32(byte_rate));              // ByteRate
    try!(f.write_le_i16(block_align));            // BlockAlign
    try!(f.write_le_i16(bit_depth as i16));       // BitsPerSample

    try!(f.write_be_i32(0x64617461));             // Subchunk2ID, data
    try!(f.write_le_i32(subchunk_2_size as i32)); // Subchunk2Size, number of bytes in the data

    for sample in samples.iter() {
        try!(f.write_le_i16(*sample))
    }

    Ok(())
}

fn main() {
    println!("Hello, synthrs!");

    write_pcm("out/sin.pcm", make_sample_16(1.0, 44100, SineWave(440.0))).ok();
    write_wav("out/sin.wav", 44100, make_sample_16(1.0, 44100, SineWave(440.0))).ok();
    write_wav("out/square.wav", 44100, make_sample_16(1.0, 44100, SquareWave(440.0))).ok();
    write_wav("out/sawtooth.wav", 44100, make_sample_16(1.0, 44100, SawtoothWave(440.0))).ok();

    write_wav("out/wolftone.wav", 44100, make_sample_16(1.0, 44100, |t: f64| -> f64 {
        (SquareWave(1000.0)(t) + SquareWave(1020.0)(t)) / 2.0
    })).ok();

    write_wav("out/whitenoise.wav", 44100, make_sample_16(1.0, 44100, |_t: f64| -> f64 {
        let mut rng = rand::task_rng();
        (rng.gen::<f64>() - 0.5) * 2.0
    })).ok();

    write_wav("out/rising.wav", 44100, make_sample_16(1.0, 44100, |t: f64| -> f64 {
        let (min_f, max_f) = (1000.0, 8000.0);
        let max_t = 1.0; // Duration of clip in seconds
        let range = max_f - min_f;
        let f = max_f - (max_t - t) * range;
        SineWave(f)(t)
    })).ok();

    write_wav("out/racecar.wav", 44100, make_sample_16(15.0, 44100, |t: f64| -> f64 {
        let mut rng = rand::task_rng();
        let mut out = 0.0;
        if t < 14.0 { out += SawtoothWave(40.63 * (t / 2.0))(t); } // Engine
        if t < 1.0 { out += SawtoothWave(30.0)(t) * 10.0; } // Engine start
        if t < 14.0 && t.tan() > 0.0 { out += SquareWave(t.fract() * 130.8125)(t); } // Gear
        if t < 14.0 && t.tan() < 0.0 { out += SquareWave(t.sin() * 261.625)(t); } // Gear
        if t < 14.0 && t.tan() > 0.866 { out += SquareWave(t.fract() * 523.25)(t); } // Gear
        if t > 14.0 { out += (rng.gen::<f64>() - 0.5) * 8.0 } // Tree
        (out / 4.0).min(1.0)
    })).ok();

    write_wav("out/shepard.wav", 44100, make_sample_16(30.0, 44100, |t: f64| -> f64 {
        let length = 10.0;
        let t_mod = t % length;
        let progress = t_mod / length;
        let tone_a2 = SineWave(110.0 / (1.0 + progress));
        let tone_a3 = SineWave(220.0 / (1.0 + progress));
        let tone_a4 = SineWave(440.0 / (1.0 + progress));
        let tone_a5 = SineWave(880.0 / (1.0 + progress));
        (tone_a2(t_mod) * (1.0 - progress)
        + tone_a5(t_mod) * progress
        + tone_a3(t_mod) + tone_a4(t_mod)) / 4.0
    })).ok();
}
<commit_msg>Add dialtone (North America's Precise Tone Plan)<commit_after>#![feature(lang_items, unboxed_closures)]

use std::io::{File, IoResult, Truncate, Write};
use std::f64::consts::PI;
use std::num::Float;
use std::num::FloatMath;
use std::rand;
use std::rand::Rng;

struct SineWave(pub f64);

impl Fn<(f64, ), f64> for SineWave {
    extern "rust-call" fn call(&self, (t, ): (f64, )) -> f64 {
        let SineWave(frequency) = *self;
        FloatMath::sin(t * frequency * 2.0 * PI)
    }
}

struct SquareWave(pub f64);

impl Fn<(f64, ), f64> for SquareWave {
    extern "rust-call" fn call(&self, (t, ): (f64, )) -> f64 {
        let SquareWave(frequency) = *self;
        let sin_wave = SineWave(frequency);
        if sin_wave(t).is_positive() { 1.0 } else { -1.0 }
    }
}

struct SawtoothWave(pub f64);

impl Fn<(f64, ), f64> for SawtoothWave {
    extern "rust-call" fn call(&self, (t, ): (f64, )) -> f64 {
        let SawtoothWave(frequency) = *self;
        let t_factor = t * frequency;
        t_factor - t_factor.floor()
    }
}

fn generate<F>(x: f64, f: F) -> f64 where F: Fn<(f64, ), f64> {
    f(x)
}

fn quantize_16(y: f64) -> i16 {
    // Quantization levels for 16 bits
    let levels = 2.0.powf(16.0) - 1.0;

    // Convert from [-1, 1] to [-2**16 / 2, 2**16 / 2]
    (y * (levels / 2.0)) as i16
}

fn make_sample_16<F>(length: f64, sample_rate: uint, waveform: F) -> Vec<i16> where F: Fn<(f64, ), f64>+Copy {
    let num_samples = (sample_rate as f64 * length).floor() as uint;
    let mut samples: Vec<i16> = Vec::with_capacity(num_samples);

    for i in range(0u, num_samples) {
        let t = i as f64 / sample_rate as f64;
        samples.push(quantize_16(generate(t, waveform)));
    }

    samples
}

fn write_pcm(filename: &str, samples: Vec<i16>) -> IoResult<()> {
    let path = Path::new(filename);
    let mut f = match File::open_mode(&path, Truncate, Write) {
        Ok(f) => f,
        Err(e) => panic!("File error: {}", e)
    };

    for sample in samples.iter() {
        try!(f.write_le_i16(*sample));
    }

    Ok(())
}

// See: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
fn write_wav(filename: &str, sample_rate: uint, samples: Vec<i16>) -> IoResult<()> {
    let path = Path::new(filename);
    let mut f = match File::open_mode(&path, Truncate, Write) {
        Ok(f) => f,
        Err(e) => panic!("File error: {}", e)
    };

    // Some WAV header fields
    let channels = 1;
    let bit_depth = 16;
    let subchunk_2_size = samples.len() * channels * bit_depth / 8;
    let chunk_size = 36 + subchunk_2_size as i32;
    let byte_rate = (sample_rate * channels * bit_depth / 8) as i32;
    let block_align = (channels * bit_depth / 8) as i16;

    try!(f.write_be_i32(0x52494646))              // ChunkID, RIFF
    try!(f.write_le_i32(chunk_size));             // ChunkSize
    try!(f.write_be_i32(0x57415645));             // Format, WAVE

    try!(f.write_be_i32(0x666d7420));             // Subchunk1ID, fmt
    try!(f.write_le_i32(16));                     // Subchunk1Size, 16 for PCM
    try!(f.write_le_i16(1));                      // AudioFormat, PCM = 1 (linear quantization)
    try!(f.write_le_i16(channels as i16));        // NumChannels
    try!(f.write_le_i32(sample_rate as i32));     // SampleRate
    try!(f.write_le_i32(byte_rate));              // ByteRate
    try!(f.write_le_i16(block_align));            // BlockAlign
    try!(f.write_le_i16(bit_depth as i16));       // BitsPerSample

    try!(f.write_be_i32(0x64617461));             // Subchunk2ID, data
    try!(f.write_le_i32(subchunk_2_size as i32)); // Subchunk2Size, number of bytes in the data

    for sample in samples.iter() {
        try!(f.write_le_i16(*sample))
    }

    Ok(())
}

fn main() {
    println!("Hello, synthrs!");

    write_pcm("out/sin.pcm", make_sample_16(1.0, 44100, SineWave(440.0))).ok();
    write_wav("out/sin.wav", 44100, make_sample_16(1.0, 44100, SineWave(440.0))).ok();
    write_wav("out/square.wav", 44100, make_sample_16(1.0, 44100, SquareWave(440.0))).ok();
    write_wav("out/sawtooth.wav", 44100, make_sample_16(1.0, 44100, SawtoothWave(440.0))).ok();

    write_wav("out/wolftone.wav", 44100, make_sample_16(1.0, 44100, |t: f64| -> f64 {
        (SquareWave(1000.0)(t) + SquareWave(1020.0)(t)) / 2.0
    })).ok();

    write_wav("out/whitenoise.wav", 44100, make_sample_16(1.0, 44100, |_t: f64| -> f64 {
        let mut rng = rand::task_rng();
        (rng.gen::<f64>() - 0.5) * 2.0
    })).ok();

    write_wav("out/rising.wav", 44100, make_sample_16(1.0, 44100, |t: f64| -> f64 {
        let (min_f, max_f) = (1000.0, 8000.0);
        let max_t = 1.0; // Duration of clip in seconds
        let range = max_f - min_f;
        let f = max_f - (max_t - t) * range;
        SineWave(f)(t)
    })).ok();

    write_wav("out/racecar.wav", 44100, make_sample_16(15.0, 44100, |t: f64| -> f64 {
        let mut rng = rand::task_rng();
        let mut out = 0.0;
        if t < 14.0 { out += SawtoothWave(40.63 * (t / 2.0))(t); } // Engine
        if t < 1.0 { out += SawtoothWave(30.0)(t) * 10.0; } // Engine start
        if t < 14.0 && t.tan() > 0.0 { out += SquareWave(t.fract() * 130.8125)(t); } // Gear
        if t < 14.0 && t.tan() < 0.0 { out += SquareWave(t.sin() * 261.625)(t); } // Gear
        if t < 14.0 && t.tan() > 0.866 { out += SquareWave(t.fract() * 523.25)(t); } // Gear
        if t > 14.0 { out += (rng.gen::<f64>() - 0.5) * 8.0 } // Tree
        (out / 4.0).min(1.0)
    })).ok();

    write_wav("out/shepard.wav", 44100, make_sample_16(30.0, 44100, |t: f64| -> f64 {
        let length = 10.0;
        let t_mod = t % length;
        let progress = t_mod / length;
        let tone_a2 = SineWave(110.0 / (1.0 + progress));
        let tone_a3 = SineWave(220.0 / (1.0 + progress));
        let tone_a4 = SineWave(440.0 / (1.0 + progress));
        let tone_a5 = SineWave(880.0 / (1.0 + progress));
        (tone_a2(t_mod) * (1.0 - progress)
        + tone_a5(t_mod) * progress
        + tone_a3(t_mod) + tone_a4(t_mod)) / 4.0
    })).ok();

    write_wav("out/dialtone.wav", 44100, make_sample_16(30.0, 44100, |t: f64| -> f64 {
        0.5 * (SineWave(350.0)(t) + SineWave(440.0)(t))
    })).ok().expect("failed");
}
<|endoftext|>


<commit_before>enum Mnemonic {
    Add, Call, Cls, Drw,
    Jp, Ld, Or, Ret,
    Rnd, Se, Shl, Shr,
    Sknp, Skp, Sne, Sub,
    Subn, Sys, Xor,
}

enum Register {
    V0, V1, V2, V3,
    V4, V5, V6, V7,
    V8, V9, Va, Vb,
    Vc, Vd, Ve, Vf,
    Sp, Pc, I, St, Dt,
}

enum Token {
    Opcode(Mnemonic),
    Reg(Register),
    ImmAddr(u16),
    ImmByte(u8),
    ImmNibb(u8),
}

struct Stream {
}

impl Stream {
    fn next_token(&mut self) -> Option<Token> {
        None
    }
}

fn main() {
    println!("Hello, world!");
}
<commit_msg>Add input file field to the Stream struct<commit_after>use std::fs::File;

enum Mnemonic {
    Add, Call, Cls, Drw,
    Jp, Ld, Or, Ret,
    Rnd, Se, Shl, Shr,
    Sknp, Skp, Sne, Sub,
    Subn, Sys, Xor,
}

enum Register {
    V0, V1, V2, V3,
    V4, V5, V6, V7,
    V8, V9, Va, Vb,
    Vc, Vd, Ve, Vf,
    Sp, Pc, I, St, Dt,
}

enum Token {
    Opcode(Mnemonic),
    Reg(Register),
    ImmAddr(u16),
    ImmByte(u8),
    ImmNibb(u8),
}

struct Stream {
    input: File,
}

impl Stream {
    fn new(input: File) -> Stream {
        Stream {
            input: input,
        }
    }

    fn next_token(&mut self) -> Option<Token> {
        None
    }
}

fn main() {
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]

extern crate rustc_serialize;
extern crate docopt;
extern crate rusqlite;
extern crate walkdir;
extern crate regex;
#[macro_use(log, info, error)]
extern crate log;
extern crate stdio_logger;

use docopt::Docopt;
use rusqlite::Connection;
use std::iter::Iterator;
use walkdir::{DirEntry, WalkDir, WalkDirIterator};
use std::path::{Path, Component};
use std::fs::File;
use std::io;
use std::io::prelude::*;
use log::{Log, LogLevel};
use stdio_logger::Logger;
use std::num;
use std::io::Error;
use std::fmt;

const USAGE: &'static str = "
MBTiles utils.

Usage:
    mbutiles <command> [options] <input> \
                             [<output>]
    mbutiles -h | --help
    mbutiles --version

Options:
  -h --help                   Show this help message and exit.
  --verbose                   Show log info.
  --version                   Show version.
  --scheme=<scheme>           Tiling scheme of the tiles. Default is \"xyz\" (z/x/y),\
 other options are \"tms\" which is also z/x/y but uses a flipped y coordinate,\
 and \"wms\" which replicates the MapServer WMS TileCache directory structure\
 \"z/000/000/x/000/000/y.png\". [default: xyz]
  --image-format=<format>     The format of the image tiles, either png, jpg, webp or pbf.
  --grid-callback=<callback>  Option to control JSONP callback for UTFGrid tiles.\
 If grids are not used as JSONP, you can remove callbacks specifying --grid_callback=\"\".

 Commands:
    import
    export
    metadata
";

#[derive(RustcDecodable, Debug)]
enum Command {
    Import,
    Export,
    Metadata,
}

#[derive(RustcDecodable, Debug)]
enum Scheme {
    Xyz,
    Tms,
    Wms,
}

#[derive(RustcDecodable, Debug, Clone, Copy)]
enum ImageFormat {
    Png,
    Jpg,
    Webp,
    Pbf,
}

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_command: Command,
    flag_verbose: bool,
    flag_scheme: Scheme,
    flag_image_format: Option<ImageFormat>,
    flag_grid_callback: Option<String>,
    arg_input: String,
    arg_output: Option<String>,
}

#[derive(Debug)]
enum InnerError {
    None,
    IO(io::Error),
    Rusqlite(rusqlite::Error),
    ParseInt(num::ParseIntError),
}

struct MBTileError {
    message: String,
    inner_error: InnerError,
}

impl std::fmt::Debug for MBTileError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

impl std::fmt::Display for InnerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InnerError::None => write!(f, ""),
            InnerError::IO(ref err) => write!(f, ", IO error: {}", err),
            InnerError::Rusqlite(ref err) => write!(f, ", SQLite error: {}", err),
            InnerError::ParseInt(ref err) => write!(f, ", Parse integer error: {}", err),
        }
    }
}

impl std::fmt::Display for MBTileError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{}", self.message, self.inner_error)
    }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());
    stdio_logger::init(if args.flag_verbose {
        LogLevel::Info
    } else {
        LogLevel::Error
    })
        .expect("Could not initialize logging");
    info!("{:?}", args);
    match args.arg_command {
        Command::Import => {
            // import tiles dir into mbtiles
            let input = args.arg_input.clone();
            let output = args.arg_output.unwrap_or_else(
                || format!("{}.mbtiles", input));
            if let Err(err) = import(&Path::new(&args.arg_input), &Path::new(&output),
                args.flag_scheme, args.flag_image_format, args.flag_grid_callback) {
                error!("{:?}", err);
            }
        },
        Command::Export =>
            // export mbtiles to a dir
            export(args.arg_input, args.arg_output,
                args.flag_scheme, args.flag_image_format, args.flag_grid_callback),
        Command::Metadata =>
            // dumps metadata
            metadata(args.arg_input, args.arg_output,
                args.flag_scheme, args.flag_image_format, args.flag_grid_callback),
    }
}

fn mbtiles_connect(mbtiles_file: &Path) -> Connection {
    Connection::open(mbtiles_file).unwrap()
}

macro_rules! log_err {
    ($e:expr) => {
        match $e {
            Ok(_) => (),
            Err(e) => {
                error!("{:?}", e);
            }
        }
    }
}

fn optimize_connection(connection: &Connection) {
    if let Err(err) = connection.execute_batch("
        PRAGMA synchronous=0;
        PRAGMA locking_mode=EXCLUSIVE;
        PRAGMA journal_mode=DELETE;
        ") {
        error!("Cannot execute sqlite optimization query {:?}", err);
    }
}

fn optimize_database(connection: &Connection) -> Result<(), MBTileError> {
    info!("SQLite analyse");
    try!(connection.execute_batch("ANALYZE;").to_mbtiles_result("Can't analyze sqlite".to_owned()));
    info!("SQLite vacuum");
    try!(connection.execute_batch("VACUUM;").to_mbtiles_result("Can't vacuum sqlite".to_owned()));
    Ok(())
}

trait ToMBTilesResult<T: Sized, E: Sized> {
    fn to_mbtiles_result(self, message: String) -> Result<T, MBTileError>;
}

impl <T: Sized> ToMBTilesResult<T, io::Error> for Result<T, io::Error> {
    fn to_mbtiles_result(self, message: String) -> Result<T, MBTileError> {
        self.map_err(|err| MBTileError {
                message: message,
                inner_error: InnerError::IO(err),
        })
    }
}

impl <T: Sized> ToMBTilesResult<T, rusqlite::Error> for Result<T, rusqlite::Error> {
    fn to_mbtiles_result(self, message: String) -> Result<T, MBTileError> {
        self.map_err(|err| MBTileError {
                message: message,
                inner_error: InnerError::Rusqlite(err),
        })
    }
}

impl <T: Sized> ToMBTilesResult<T, num::ParseIntError> for Result<T, num::ParseIntError> {
    fn to_mbtiles_result(self, message: String) -> Result<T, MBTileError> {
        self.map_err(|err| MBTileError {
                message: message,
                inner_error: InnerError::ParseInt(err),
        })
    }
}

fn mbtiles_setup(connection: &Connection) -> Result<(), MBTileError> {
    connection.execute_batch("
        CREATE TABLE tiles (
                zoom_level INTEGER,
                tile_column INTEGER,
                tile_row INTEGER,
                tile_data BLOB);
        CREATE TABLE metadata
            (name TEXT, value TEXT);
        CREATE TABLE grids (zoom_level INTEGER, tile_column INTEGER,
            tile_row INTEGER, grid BLOB);
        CREATE TABLE grid_data (zoom_level INTEGER, tile_column
            INTEGER, tile_row INTEGER, key_name TEXT, key_json TEXT);
        CREATE UNIQUE INDEX name ON metadata (name);
        CREATE UNIQUE INDEX tile_index ON tiles
            (zoom_level, tile_column, tile_row);
    ").to_mbtiles_result("Can't create schema".to_owned())
}

fn is_hidden(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map_or(false, |s| s.starts_with('.'))
}

fn get_extension(image_format: ImageFormat) -> String {
    match image_format {
        ImageFormat::Jpg => "jpg".to_owned(),
        ImageFormat::Pbf => "pbf".to_owned(),
        ImageFormat::Png => "png".to_owned(),
        ImageFormat::Webp => "webp".to_owned(),
    }
}

fn parse_component(component: Component, parse_file: Option<ImageFormat>) -> Result<u32, MBTileError> {
    if let Component::Normal(zoom_dir) = component {
        let s = try!(zoom_dir.to_str()
                .ok_or(MBTileError {
                    message: format!("Unvalid unicode path: {:?}", zoom_dir),
                    inner_error: InnerError::None,
                }));
        if let Some(image_format) = parse_file {
            let parts: Vec<&str> = s.split('.').collect();
            let filtered_extension = get_extension(image_format);
            if parts[1] == filtered_extension {
                parts[0].parse::<u32>().to_mbtiles_result("".to_owned())
            } else {
                Err(MBTileError{
                    message: format!("The filtered extention {} is different than the path's \
                             extention {}",
                            filtered_extension,
                            parts[1]),
                    inner_error: InnerError::None,
                })
            }
        } else {
            s.parse::<u32>().to_mbtiles_result("".to_owned())
        }
    } else {
        Err(MBTileError {
            message: format!("Can't read path component {:?}", component),
            inner_error: InnerError::None,
        })
    }
}

fn import(input: &Path,
          output: &Path,
          flag_scheme: Scheme,
          flag_image_format: Option<ImageFormat>,
          flag_grid_callback: Option<String>) -> Result<(), MBTileError> {
    let input_path = Path::new(&input);
    if input_path.is_dir() {
        let connection = mbtiles_connect(output);
        optimize_connection(&connection);
        try!(mbtiles_setup(&connection));
        let base_components_length = input_path.components().count();
        let dir_walker = WalkDir::new(input_path)
                             .follow_links(true)
                             .min_depth(1)
                             .max_depth(3)
                             .into_iter()
                             .filter_entry(|e| !is_hidden(e));
        for entry in dir_walker {
            if let Ok(entry) = entry {
                let entry_path = entry.path();
                if entry_path.is_file() {
                    let end_comp: Vec<Component> = entry_path.components()
                                                             .skip(base_components_length)
                                                             .collect();
                    if end_comp.len() == 3 {
                        parse_component(end_comp[0], None)
                        .and_then(|zoom| parse_component(end_comp[1], None)
                            .and_then(|row| parse_component(end_comp[2], flag_image_format)
                                .and_then(|col| {
                                    info!("Zoom: {}, Row: {}, Col {}", zoom, row, col);
                                    insert_image_sqlite(entry_path, zoom, col, row, &connection)
                                })
                            )
                        ).unwrap_or_else(|err| error!("{}", err))

                    }

                }
                info!("{}", entry.path().display());
            }
        }
        try!(optimize_database(&connection));
        Ok(())
    } else {
        Err(MBTileError {
            message: "Can only import from a directory".to_owned(),
            inner_error: InnerError::None,
        })
    }
}

fn insert_image_sqlite(image_path: &Path,
                       zoom: u32,
                       column: u32,
                       row: u32,
                       connection: &Connection) -> Result<(), MBTileError> {
    let mut image_file = try!(File::open(image_path)
        .to_mbtiles_result(format!("Can't open {:?}", image_path)));
    let mut buffer = Vec::new();
    try!(image_file.read_to_end(&mut buffer)
        .to_mbtiles_result(format!("Can't read file {:?}", image_path)));
    try!(connection.execute("insert into tiles (zoom_level,
                    tile_column, tile_row, tile_data) values
                    ($1, $2, $3, $4);",
                                             &[&(zoom as i64),
                                               &(column as i64),
                                               &(row as i64),
                                               &buffer])
                                               .to_mbtiles_result(format!("Can't insert {:?}", image_path)));
    //error!("Can't insert {:?}, {}", image_path, err);
    //    error!("Can't read file {:?}", image_path);
    //error!("Can't open {:?} =>  {:?}", image_path, err);
    Ok(())
}

fn export(input: String,
          output: Option<String>,
          flag_scheme: Scheme,
          flag_image_format: Option<ImageFormat>,
          flag_grid_callback: Option<String>) {
    let input_path = Path::new(&input);
    if input_path.is_file() {
    } else {
        error!("Can only export from a file")
    }
}

fn metadata(input: String,
            output: Option<String>,
            flag_scheme: Scheme,
            flag_image_format: Option<ImageFormat>,
            flag_grid_callback: Option<String>) {
    let input_path = Path::new(&input);
    if input_path.is_file() {
    } else {
        error!("Can only dumps from a file")
    }
}
<commit_msg>add walker error handling in MBTileError, handle db creation error, simplify entry testing, remove nesting with early exit, fmt<commit_after>#![feature(plugin)]
#![plugin(clippy)]

extern crate rustc_serialize;
extern crate docopt;
extern crate rusqlite;
extern crate walkdir;
extern crate regex;
#[macro_use(log, info, debug, error)]
extern crate log;
extern crate stdio_logger;

use docopt::Docopt;
use rusqlite::Connection;
use std::iter::Iterator;
use walkdir::{DirEntry, WalkDir, WalkDirIterator};
use std::path::{Path, Component};
use std::fs::File;
use std::io;
use std::io::prelude::*;
use log::{Log, LogLevel};
use stdio_logger::Logger;
use std::num;
use std::io::Error;
use std::fmt;

const USAGE: &'static str = "
MBTiles utils.

Usage:
    mbutiles <command> [options] <input> \
                             [<output>]
    mbutiles -h | --help
    mbutiles --version

Options:
  -h --help                   Show this help message and exit.
  --verbose                   Show log info.
  --version                   Show version.
  --scheme=<scheme>           Tiling scheme of the tiles. Default is \"xyz\" (z/x/y),\
 other options are \"tms\" which is also z/x/y but uses a flipped y coordinate,\
 and \"wms\" which replicates the MapServer WMS TileCache directory structure\
 \"z/000/000/x/000/000/y.png\". [default: xyz]
  --image-format=<format>     The format of the image tiles, either png, jpg, webp or pbf.
  --grid-callback=<callback>  Option to control JSONP callback for UTFGrid tiles.\
 If grids are not used as JSONP, you can remove callbacks specifying --grid_callback=\"\".

 Commands:
    import
    export
    metadata
";

#[derive(RustcDecodable, Debug)]
enum Command {
    Import,
    Export,
    Metadata,
}

#[derive(RustcDecodable, Debug)]
enum Scheme {
    Xyz,
    Tms,
    Wms,
}

#[derive(RustcDecodable, Debug, Clone, Copy)]
enum ImageFormat {
    Png,
    Jpg,
    Webp,
    Pbf,
}

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_command: Command,
    flag_verbose: bool,
    flag_scheme: Scheme,
    flag_image_format: Option<ImageFormat>,
    flag_grid_callback: Option<String>,
    arg_input: String,
    arg_output: Option<String>,
}

#[derive(Debug)]
enum InnerError {
    None,
    IO(io::Error),
    Rusqlite(rusqlite::Error),
    ParseInt(num::ParseIntError),
    WalkDir(walkdir::Error),
}

struct MBTileError {
    message: String,
    inner_error: InnerError,
}

impl std::fmt::Debug for MBTileError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

impl std::fmt::Display for InnerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InnerError::None => write!(f, ""),
            InnerError::IO(ref err) => write!(f, ", IO error: {}", err),
            InnerError::Rusqlite(ref err) => write!(f, ", SQLite error: {}", err),
            InnerError::ParseInt(ref err) => write!(f, ", Parse integer error: {}", err),
            InnerError::WalkDir(ref err) => write!(f, ", Directory Walker error: {}", err),
        }
    }
}

impl std::fmt::Display for MBTileError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{}", self.message, self.inner_error)
    }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());
    stdio_logger::init(if args.flag_verbose {
        LogLevel::Info
    } else {
        LogLevel::Error
    })
        .expect("Could not initialize logging");
    info!("{:?}", args);
    match args.arg_command {
        Command::Import => {
            // import tiles dir into mbtiles
            let input = args.arg_input.clone();
            let output = args.arg_output.unwrap_or_else(
                || format!("{}.mbtiles", input));
            if let Err(err) = import(&Path::new(&args.arg_input), &Path::new(&output),
                args.flag_scheme, args.flag_image_format, args.flag_grid_callback) {
                error!("{:?}", err);
            }
        },
        Command::Export =>
            // export mbtiles to a dir
            export(args.arg_input, args.arg_output,
                args.flag_scheme, args.flag_image_format, args.flag_grid_callback),
        Command::Metadata =>
            // dumps metadata
            metadata(args.arg_input, args.arg_output,
                args.flag_scheme, args.flag_image_format, args.flag_grid_callback),
    }
}

fn mbtiles_connect(mbtiles_file: &Path) -> Result<Connection, MBTileError> {
    Connection::open(mbtiles_file).to_mbtiles_result(format!("Can't connect to {:?}", mbtiles_file))
}

macro_rules! log_err {
    ($e:expr) => {
        match $e {
            Ok(_) => (),
            Err(e) => {
                error!("{:?}", e);
            }
        }
    }
}

fn optimize_connection(connection: &Connection) -> Result<(), MBTileError> {
    connection.execute_batch("
        PRAGMA synchronous=0;
        PRAGMA locking_mode=EXCLUSIVE;
        PRAGMA journal_mode=DELETE;
        ")
              .to_mbtiles_result("Cannot execute sqlite optimization query".to_owned())
}

fn optimize_database(connection: &Connection) -> Result<(), MBTileError> {
    info!("SQLite analyse");
    try!(connection.execute_batch("ANALYZE;").to_mbtiles_result("Can't analyze sqlite".to_owned()));
    info!("SQLite vacuum");
    try!(connection.execute_batch("VACUUM;").to_mbtiles_result("Can't vacuum sqlite".to_owned()));
    Ok(())
}

trait ToMBTilesResult<T: Sized, E: Sized> {
    fn to_mbtiles_result(self, message: String) -> Result<T, MBTileError>;
}

impl<T: Sized> ToMBTilesResult<T, io::Error> for Result<T, io::Error> {
    fn to_mbtiles_result(self, message: String) -> Result<T, MBTileError> {
        self.map_err(|err| {
            MBTileError {
                message: message,
                inner_error: InnerError::IO(err),
            }
        })
    }
}

impl<T: Sized> ToMBTilesResult<T, rusqlite::Error> for Result<T, rusqlite::Error> {
    fn to_mbtiles_result(self, message: String) -> Result<T, MBTileError> {
        self.map_err(|err| {
            MBTileError {
                message: message,
                inner_error: InnerError::Rusqlite(err),
            }
        })
    }
}

impl<T: Sized> ToMBTilesResult<T, num::ParseIntError> for Result<T, num::ParseIntError> {
    fn to_mbtiles_result(self, message: String) -> Result<T, MBTileError> {
        self.map_err(|err| {
            MBTileError {
                message: message,
                inner_error: InnerError::ParseInt(err),
            }
        })
    }
}

impl<T: Sized> ToMBTilesResult<T, walkdir::Error> for Result<T, walkdir::Error> {
    fn to_mbtiles_result(self, message: String) -> Result<T, MBTileError> {
        self.map_err(|err| {
            MBTileError {
                message: message,
                inner_error: InnerError::WalkDir(err),
            }
        })
    }
}

fn mbtiles_setup(connection: &Connection) -> Result<(), MBTileError> {
    connection.execute_batch("
        CREATE TABLE tiles (
                zoom_level INTEGER,
                tile_column INTEGER,
                tile_row INTEGER,
                tile_data BLOB);
        CREATE TABLE metadata
            (name TEXT, value TEXT);
        CREATE TABLE grids (zoom_level INTEGER, tile_column INTEGER,
            tile_row INTEGER, grid BLOB);
        CREATE TABLE grid_data (zoom_level INTEGER, tile_column
            INTEGER, tile_row INTEGER, key_name TEXT, key_json TEXT);
        CREATE UNIQUE INDEX name ON metadata (name);
        CREATE UNIQUE INDEX tile_index ON tiles
            (zoom_level, tile_column, tile_row);
    ")
              .to_mbtiles_result("Can't create schema".to_owned())
}

fn is_visible(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map_or(false, |s| !s.starts_with('.'))
}

fn get_extension(image_format: ImageFormat) -> String {
    match image_format {
        ImageFormat::Jpg => "jpg".to_owned(),
        ImageFormat::Pbf => "pbf".to_owned(),
        ImageFormat::Png => "png".to_owned(),
        ImageFormat::Webp => "webp".to_owned(),
    }
}

fn parse_component(component: Component,
                   parse_file: Option<ImageFormat>)
                   -> Result<u32, MBTileError> {
    if let Component::Normal(zoom_dir) = component {
        let s = try!(zoom_dir.to_str()
                             .ok_or(MBTileError {
                                 message: format!("Unvalid unicode path: {:?}", zoom_dir),
                                 inner_error: InnerError::None,
                             }));
        if let Some(image_format) = parse_file {
            let parts: Vec<&str> = s.split('.').collect();
            let filtered_extension = get_extension(image_format);
            if parts[1] == filtered_extension {
                parts[0].parse::<u32>().to_mbtiles_result("".to_owned())
            } else {
                Err(MBTileError {
                    message: format!("The filtered extention {} is different than the path's \
                             extention {}",
                                     filtered_extension,
                                     parts[1]),
                    inner_error: InnerError::None,
                })
            }
        } else {
            s.parse::<u32>().to_mbtiles_result("".to_owned())
        }
    } else {
        Err(MBTileError {
            message: format!("Can't read path component {:?}", component),
            inner_error: InnerError::None,
        })
    }
}

fn import(input: &Path,
          output: &Path,
          flag_scheme: Scheme,
          flag_image_format: Option<ImageFormat>,
          flag_grid_callback: Option<String>)
          -> Result<(), MBTileError> {
    info!("Importing disk to MBTiles");
    debug!("{:?} --> {:?}", &input, &output);
    if !input.is_dir() {
        return Err(MBTileError {
            message: "Can only import from a directory".to_owned(),
            inner_error: InnerError::None,
        });
    }
    let connection = try!(mbtiles_connect(output));
    try!(optimize_connection(&connection));
    try!(mbtiles_setup(&connection));
    let base_components_length = input.components().count();
    let dir_walker = WalkDir::new(input)
                         .follow_links(true)
                         .min_depth(1)
                         .max_depth(3)
                         .into_iter()
                         .filter_entry(is_visible);
    for entry_res in dir_walker {
        let entry = try!(entry_res.to_mbtiles_result("".to_owned()));
        let entry_path = entry.path();
        if entry_path.is_dir() {
            // ignore directories
            continue;
        }
        let end_comp: Vec<Component> = entry_path.components()
                                                 .skip(base_components_length)
                                                 .collect();
        if end_comp.len() == 3 {
            parse_component(end_comp[0], None)
                .and_then(|zoom| {
                    parse_component(end_comp[1], None).and_then(|row| {
                        parse_component(end_comp[2], flag_image_format).and_then(|col| {
                            info!("Zoom: {}, Row: {}, Col {}", zoom, row, col);
                            insert_image_sqlite(entry_path, zoom, col, row, &connection)
                        })
                    })
                })
                .unwrap_or_else(|err| error!("{}", err))
        }
        info!("{}", entry.path().display());
    }
    try!(optimize_database(&connection));
    Ok(())
}

fn insert_image_sqlite(image_path: &Path,
                       zoom: u32,
                       column: u32,
                       row: u32,
                       connection: &Connection)
                       -> Result<(), MBTileError> {
    let mut image_file = try!(File::open(image_path)
                                  .to_mbtiles_result(format!("Can't open {:?}", image_path)));
    let mut buffer = Vec::new();
    try!(image_file.read_to_end(&mut buffer)
                   .to_mbtiles_result(format!("Can't read file {:?}", image_path)));
    try!(connection.execute("insert into tiles (zoom_level,
                    tile_column, tile_row, tile_data) values
                    ($1, $2, $3, $4);",
                            &[&(zoom as i64), &(column as i64), &(row as i64), &buffer])
                   .to_mbtiles_result(format!("Can't insert {:?}", image_path)));
    Ok(())
}

fn export(input: String,
          output: Option<String>,
          flag_scheme: Scheme,
          flag_image_format: Option<ImageFormat>,
          flag_grid_callback: Option<String>) {
    let input_path = Path::new(&input);
    if input_path.is_file() {
    } else {
        error!("Can only export from a file")
    }
}

fn metadata(input: String,
            output: Option<String>,
            flag_scheme: Scheme,
            flag_image_format: Option<ImageFormat>,
            flag_grid_callback: Option<String>) {
    let input_path = Path::new(&input);
    if input_path.is_file() {
    } else {
        error!("Can only dumps from a file")
    }
}
<|endoftext|>


<commit_before>//! Linear algebra for coordinate transformations
//!
//! This module provides basic linear algebra on points on the 2D plane:
//!
//! - You can construct matrices that represent basic 2d transformations like
//!   scaling, translation and rotation.
//!
//! - You can compose and invert matrices.
//!
//! - You can apply matrices to points.
//!
//! This module is only lightly typed: points are [f32; 2] values, and matrices
//! are column-major [[f32; 3]; 3] values. These are the types Glium works with
//! directly anyway.
//!
//! Transformations are represented as 3x3 matrices, using homogeneous
//! coordinates to represent translations as well as linear transformations.
//! When applied to an [f32; 2] point, the point is extended with an implicit
//! `1.0` to make it a homogeneous coordinate.

pub type Vector = [f32; 2];
pub type Matrix = [[f32; 3]; 3];

/// Return a matrix that scales a homogeneous 2D point by `sx` and `sy` along the
/// x and y axes.
pub fn scale_transform(sx: f32, sy: f32) -> Matrix {
    [[sx,  0.0, 0.0],
     [0.0, sy,  0.0],
     [0.0, 0.0, 1.0]]
}

/// Return a matrix that translates a homogeneous 2D point by `dx` and `dy` to
/// the right and upwards.
pub fn translate_transform(dx: f32, dy: f32) -> Matrix {
    [[1.0, 0.0, 0.0],
     [0.0, 1.0, 0.0],
     [dx,  dy,  1.0]]
}

/// We don't need rotation in rbattle, but it'd be straightforward.

/// A vector that can be extended to an [f32; 3] vector, and converted back.
/// On `[f32; 3]` vectors, these are the identity function.
pub trait Homogeneous {
    /// Convert `self` into homogeneous coordinates.
    fn into(self) -> [f32; 3];

    /// Convent a homogeneous vector to `self`.
    fn from([f32; 3]) -> Self;
}

impl Homogeneous for [f32; 2] {
    fn into(self) -> [f32; 3] { [self[0], self[1], 1.0] }
    fn from(h: [f32; 3]) -> Self { [h[0] / h[2], h[1] / h[2]] }
}

impl Homogeneous for [f32; 3] {
    fn into(self) -> [f32; 3] { self }
    fn from(h: [f32; 3]) -> Self { h }
}

/// Multiply each element in `vec` by `scalar`.
pub fn scale(vec: [f32; 3], scalar: f32) -> [f32; 3] {
    [vec[0] * scalar,
     vec[1] * scalar,
     vec[2] * scalar]
}

/// Divide each element in `vec` by `scalar`. This is equivalent to `scale(vec,
/// 1.0 / scalar)`, but might be more accurate.
pub fn scale_inv(vec: [f32; 3], scalar: f32) -> [f32; 3] {
    [vec[0] / scalar,
     vec[1] / scalar,
     vec[2] / scalar]
}

/// Add `lhs` to `rhs` elementwise.
pub fn add(lhs: [f32; 3], rhs: [f32; 3]) -> [f32; 3] {
    [lhs[0] + rhs[0],
     lhs[1] + rhs[1],
     lhs[2] + rhs[02]]
}

/// Compute the cross product or vector product of `lhs` and `rhs`.
pub fn cross(lhs: [f32; 3], rhs: [f32; 3]) -> [f32; 3] {
    [(lhs[1] * rhs[2]) - (lhs[2] * rhs[1]),
     (lhs[2] * rhs[0]) - (lhs[0] * rhs[2]),
     (lhs[0] * rhs[1]) - (lhs[1] * rhs[0])]
}

/// Apply the transformation `trans` to `vec`. The `vec` argument may be either
/// an `[f32; 2]` or an `[f32; 3]`.
pub fn apply<V: Homogeneous>(trans: Matrix, vec: V) -> V {
    let h = vec.into();
    Homogeneous::from(add(add(scale(trans[0], h[0]),
                              scale(trans[1], h[1])),
                          scale(trans[2], h[2])))
}

/// Return a matrix that is the product of `lhs` and `rhs`. In other words,
/// return a matrix whose effects as a transformation are equivalent to first
/// applying `rhs` and then applying `lhs`.
pub fn compose(lhs: Matrix, rhs: Matrix) -> Matrix {
    [apply(lhs, rhs[0]),
     apply(lhs, rhs[1]),
     apply(lhs, rhs[2])]
}

/// Return a matrix whose n'th row is `m`'s n'th column.
pub fn transpose(m: Matrix) -> Matrix {
    [[m[0][0], m[1][0], m[2][0]],
     [m[0][1], m[1][1], m[2][1]],
     [m[0][2], m[1][2], m[2][2]]]
}

/// Return the determinant of `m`.
pub fn determinant(m: Matrix) -> f32 {
    (m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) -
     m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) +
     m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]))
}

/// Return the inverse of `m`. In other words, return a matrix that undoes
/// whatever transformation `m` does. Some matrices have no inverse; for those,
/// this function returns `None`.
pub fn inverse(m: Matrix) -> Option<Matrix> {
    let det = determinant(m);
    if det == 0.0 {
        None
    } else {
        Some(transpose([scale_inv(cross(m[1], m[2]), det),
                        scale_inv(cross(m[2], m[0]), det),
                        scale_inv(cross(m[0], m[1]), det)]))
    }
}

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

    #[test]
    fn test_scale_transform() {
        assert_eq!(apply(scale_transform(2.0, 3.0), [5.0, 7.0]),
                   [10.0, 21.0]);
    }

    #[test]
    fn test_translate_transform() {
        assert_eq!(apply(translate_transform(1.0, 10.0), [100.0, 1000.0]),
                   [101.0, 1010.0]);
    }

    #[test]
    fn test_compose() {
        let scale = scale_transform(2.0, 3.0);
        let translate = translate_transform(1.0, 10.0);
        assert_eq!(apply(compose(translate, scale), [5.0, 7.0]),
                   [11.0, 31.0]);
        assert_eq!(apply(compose(scale, translate), [5.0, 7.0]),
                   [12.0, 51.0]);
    }

    #[test]
    fn test_inverse() {
        let scale = scale_transform(2.0, 8.0);
        assert_eq!(inverse(scale),
                   Some(scale_transform(0.5, 0.125)));

        let translate = translate_transform(1.0, 10.0);
        assert_eq!(inverse(translate),
                   Some(translate_transform(-1.0, -10.0)));

        assert_eq!(inverse(compose(scale, translate)),
                   Some(compose(inverse(translate).unwrap(),
                                inverse(scale).unwrap())));

        assert_eq!(inverse(compose(translate, scale)),
                   Some(compose(inverse(scale).unwrap(),
                                inverse(translate).unwrap())));
    }
}

// Proof that composing two matrices whose bottom row is [0, 0, 1] gives another
// such matrix (just for my own sanity):
//
// Applying a 3x3 matrix whose bottom row is [0, 0, 1] to any vector [_, _, w]
// always produces a vector [_, _, w]: all columns but the last have a zero in
// the final row, so they contribute nothing to the result's final element; and
// the last column is multiplied by the vector's w, and so contributes w to the
// final element.
//
// When composing two 3x3 matrices whose bottom rows are [0, 0, 1], we apply the
// first to each column of the second. The resulting columns thus end with 0, 0,
// and 1. So composing two such matrices produces a matrix with the same bottom
// row.
<commit_msg>math: Comments.<commit_after>//! Linear algebra for coordinate transformations
//!
//! This module provides basic linear algebra on points on the 2D plane:
//!
//! - You can construct matrices that represent basic 2d transformations like
//!   scaling, translation and rotation.
//!
//! - You can compose and invert matrices.
//!
//! - You can apply matrices to points.
//!
//! This module is only lightly typed: points are [f32; 2] values, and matrices
//! are column-major [[f32; 3]; 3] values. These are the types Glium works with
//! directly anyway.
//!
//! Transformations are represented as 3x3 matrices, using homogeneous
//! coordinates to represent translations as well as linear transformations.
//! When applied to an [f32; 2] point, the point is extended with an implicit
//! `1.0` to make it a homogeneous coordinate.

pub type Vector = [f32; 2];
pub type Matrix = [[f32; 3]; 3];

/// Return a matrix that scales a homogeneous 2D point by `sx` and `sy` along the
/// x and y axes.
pub fn scale_transform(sx: f32, sy: f32) -> Matrix {
    [[sx,  0.0, 0.0],
     [0.0, sy,  0.0],
     [0.0, 0.0, 1.0]]
}

/// Return a matrix that translates a homogeneous 2D point by `dx` and `dy` to
/// the right and upwards.
pub fn translate_transform(dx: f32, dy: f32) -> Matrix {
    [[1.0, 0.0, 0.0],
     [0.0, 1.0, 0.0],
     [dx,  dy,  1.0]]
}

// These sorts of modules usually also provide a rotation matrix, but we don't
// need rotation in rbattle.

/// A vector that can be extended to an [f32; 3] vector, and converted back.
/// On `[f32; 3]` vectors, these are the identity function.
pub trait Homogeneous {
    /// Convert `self` into homogeneous coordinates.
    fn into(self) -> [f32; 3];

    /// Convent a homogeneous vector to `self`.
    fn from([f32; 3]) -> Self;
}

impl Homogeneous for [f32; 2] {
    fn into(self) -> [f32; 3] { [self[0], self[1], 1.0] }
    fn from(h: [f32; 3]) -> Self { [h[0] / h[2], h[1] / h[2]] }
}

impl Homogeneous for [f32; 3] {
    fn into(self) -> [f32; 3] { self }
    fn from(h: [f32; 3]) -> Self { h }
}

/// Multiply each element in `vec` by `scalar`.
pub fn scale(vec: [f32; 3], scalar: f32) -> [f32; 3] {
    [vec[0] * scalar,
     vec[1] * scalar,
     vec[2] * scalar]
}

/// Divide each element in `vec` by `scalar`. This is equivalent to `scale(vec,
/// 1.0 / scalar)`, but might be more accurate.
pub fn scale_inv(vec: [f32; 3], scalar: f32) -> [f32; 3] {
    [vec[0] / scalar,
     vec[1] / scalar,
     vec[2] / scalar]
}

/// Add `lhs` to `rhs` elementwise.
pub fn add(lhs: [f32; 3], rhs: [f32; 3]) -> [f32; 3] {
    [lhs[0] + rhs[0],
     lhs[1] + rhs[1],
     lhs[2] + rhs[02]]
}

/// Compute the cross product or vector product of `lhs` and `rhs`.
pub fn cross(lhs: [f32; 3], rhs: [f32; 3]) -> [f32; 3] {
    [(lhs[1] * rhs[2]) - (lhs[2] * rhs[1]),
     (lhs[2] * rhs[0]) - (lhs[0] * rhs[2]),
     (lhs[0] * rhs[1]) - (lhs[1] * rhs[0])]
}

/// Apply the transformation `trans` to `vec`. The `vec` argument may be either
/// an `[f32; 2]` or an `[f32; 3]`.
pub fn apply<V: Homogeneous>(trans: Matrix, vec: V) -> V {
    let h = vec.into();
    Homogeneous::from(add(add(scale(trans[0], h[0]),
                              scale(trans[1], h[1])),
                          scale(trans[2], h[2])))
}

/// Return a matrix that is the product of `lhs` and `rhs`. In other words,
/// return a matrix whose effects as a transformation are equivalent to first
/// applying `rhs` and then applying `lhs`.
pub fn compose(lhs: Matrix, rhs: Matrix) -> Matrix {
    [apply(lhs, rhs[0]),
     apply(lhs, rhs[1]),
     apply(lhs, rhs[2])]
}

/// Return a matrix whose n'th row is `m`'s n'th column.
pub fn transpose(m: Matrix) -> Matrix {
    [[m[0][0], m[1][0], m[2][0]],
     [m[0][1], m[1][1], m[2][1]],
     [m[0][2], m[1][2], m[2][2]]]
}

/// Return the determinant of `m`.
pub fn determinant(m: Matrix) -> f32 {
    (m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) -
     m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) +
     m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]))
}

/// Return the inverse of `m`. In other words, return a matrix that undoes
/// whatever transformation `m` does. Some matrices have no inverse; for those,
/// this function returns `None`.
pub fn inverse(m: Matrix) -> Option<Matrix> {
    let det = determinant(m);
    if det == 0.0 {
        None
    } else {
        Some(transpose([scale_inv(cross(m[1], m[2]), det),
                        scale_inv(cross(m[2], m[0]), det),
                        scale_inv(cross(m[0], m[1]), det)]))
    }
}

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

    #[test]
    fn test_scale_transform() {
        assert_eq!(apply(scale_transform(2.0, 3.0), [5.0, 7.0]),
                   [10.0, 21.0]);
    }

    #[test]
    fn test_translate_transform() {
        assert_eq!(apply(translate_transform(1.0, 10.0), [100.0, 1000.0]),
                   [101.0, 1010.0]);
    }

    #[test]
    fn test_compose() {
        let scale = scale_transform(2.0, 3.0);
        let translate = translate_transform(1.0, 10.0);
        assert_eq!(apply(compose(translate, scale), [5.0, 7.0]),
                   [11.0, 31.0]);
        assert_eq!(apply(compose(scale, translate), [5.0, 7.0]),
                   [12.0, 51.0]);
    }

    #[test]
    fn test_inverse() {
        let scale = scale_transform(2.0, 8.0);
        assert_eq!(inverse(scale),
                   Some(scale_transform(0.5, 0.125)));

        let translate = translate_transform(1.0, 10.0);
        assert_eq!(inverse(translate),
                   Some(translate_transform(-1.0, -10.0)));

        assert_eq!(inverse(compose(scale, translate)),
                   Some(compose(inverse(translate).unwrap(),
                                inverse(scale).unwrap())));

        assert_eq!(inverse(compose(translate, scale)),
                   Some(compose(inverse(scale).unwrap(),
                                inverse(translate).unwrap())));
    }
}
<|endoftext|>


<commit_before>use ::actions;
use ::board;
use ::game;
use ::search_graph;

use rand::Rng;
use std::ops::Add;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Payoff {
    values: [usize; 2],
}

impl Payoff {
    pub fn new() -> Self {
        Payoff { values: [0; 2], }
    }

    pub fn increment(&mut self, player: game::PlayerMarker, value: usize) {
        self.values[player.index()] += value
    }

    pub fn score(&self, player: game::PlayerMarker) -> usize {
        self.values[player.index()]
    }
}

impl Default for Payoff {
    fn default() -> Self {
        Payoff::new()
    }
}

impl Add for Payoff {
    type Output = Payoff;

    fn add(self, other: Payoff) -> Payoff {
        Payoff { values: [self.values[0] + other.values[0],
                          self.values[1] + other.values[1]], }
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Statistics {
    visits: usize,
    payoff: Payoff,
}

impl Statistics {
    pub fn new() -> Self {
        Statistics {
            visits: 0,
            payoff: Payoff::new(),
        }
    }

    pub fn increment_visit(&mut self, p: Payoff) {
        self.visits += 1;
        self.payoff.values[0] += p.values[0];
        self.payoff.values[1] += p.values[1];
    }
}

impl Default for Statistics {
    fn default() -> Self {
        Statistics::new()
    }
}

impl Add for Statistics {
    type Output = Statistics;

    fn add(self, other: Statistics) -> Statistics {
        Statistics { visits: self.visits + other.visits,
                     payoff: self.payoff + other.payoff, }
    }
}

#[derive(Clone, Debug)]
pub struct ActionData {
    action: actions::Action,
    payoff: Statistics,
}

pub type Edge<'a> = search_graph::Edge<'a, Statistics, ActionData>;
pub type Graph = search_graph::Graph<Statistics, ActionData>;
pub type Node<'a> = search_graph::Node<'a, Statistics, ActionData>;

pub enum RolloutResult<'a> {
    Unexpanded(Edge<'a>),
    Terminal(Node<'a>),
    Cycle,
}

pub fn rollout<'a>(mut node: Node<'a>, state: &mut game::State) -> RolloutResult<'a> {
    loop {
        let children = node.child_list();
        if children.is_empty() {
            return RolloutResult::Terminal(node)
        }
        let mut i = 0;
        let mut best_child_index = 0;
        let mut best_child_score = 0.0;
        while i < children.len() {
            let edge = children.get_edge(i);
            match edge.target() {
                search_graph::Target::Unexpanded => {
                    state.do_action(&edge.data().action);
                    return RolloutResult::Unexpanded(edge)
                },
                search_graph::Target::Cycle(_) => (),
                search_graph::Target::Expanded(_) => {
                    let child_score = 0.0;
                    if child_score > best_child_score {
                        // TODO tie-breaking.
                        best_child_score = child_score;
                        best_child_index = i;
                    }
                },
            }
            i += 1;
        }
        let edge = children.get_edge(best_child_index);
        match edge.target() {
            search_graph::Target::Expanded(child) => {
                state.do_action(&edge.data().action);
                node = child;
            },
            _ => return RolloutResult::Cycle,
        }
    }
}

pub fn simulate<R>(mut state: game::State, mut rng: R) -> Payoff where R: Rng {
    loop {
        let action = match payoff(&state) {
            None => {
                let mut actions = state.role_actions(state.active_player().role());
                let mut selected = None;
                let mut i = 0;
                loop {
                    match actions.next() {
                        None => break,
                        Some(a) => {
                            if i == 0 {
                                selected = Some(a);
                            } else if rng.next_f64() < (1.0 / (i as f64)) {
                                selected = Some(a);
                            }
                            i += 1;
                        },
                    }
                }
                selected.expect("Terminal state has no payoff")
            },
            Some(p) => return p,
        };
        state.do_action(&action);
    }
}

fn role_payoff(r: game::Role) -> usize {
    match r {
        game::Role::Dwarf => 1,
        game::Role::Troll => 4,
    }
}

pub fn payoff(state: &game::State) -> Option<Payoff> {
    if state.terminated() {
        let player_1_role = state.player(game::PlayerMarker::One).role();
        let player_1_role_payoff = role_payoff(player_1_role);
        let player_2_role = state.player(game::PlayerMarker::Two).role();
        let player_2_role_payoff = role_payoff(player_2_role);
        let mut payoff = Payoff::new();
        let mut i = state.board().cells_iter();
        loop {
            match i.next() {
                Some((_, board::Content::Occupied(t))) if t.role() == Some(player_1_role) =>
                    payoff.values[0] += player_1_role_payoff,
                Some((_, board::Content::Occupied(t))) if t.role() == Some(player_2_role) =>
                    payoff.values[1] += player_2_role_payoff,
                None => break,
                _ => (),
            }
        }
        Some(payoff)
    } else {
        None
    }
}
<commit_msg>Remove unnecessary code in MCTS statistics objects.<commit_after>use ::actions;
use ::board;
use ::game;
use ::search_graph;

use rand::Rng;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Payoff {
    values: [usize; 2],
}

impl Payoff {
    pub fn new() -> Self {
        Payoff { values: [0; 2], }
    }

    pub fn score(&self, player: game::PlayerMarker) -> usize {
        self.values[player.index()]
    }
}

impl Default for Payoff {
    fn default() -> Self {
        Payoff::new()
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Statistics {
    visits: usize,
    payoff: Payoff,
}

impl Statistics {
    pub fn new() -> Self {
        Statistics {
            visits: 0,
            payoff: Payoff::new(),
        }
    }

    pub fn increment_visit(&mut self, p: Payoff) {
        self.visits += 1;
        self.payoff.values[0] += p.values[0];
        self.payoff.values[1] += p.values[1];
    }
}

impl Default for Statistics {
    fn default() -> Self {
        Statistics::new()
    }
}

#[derive(Clone, Debug)]
pub struct ActionData {
    action: actions::Action,
    payoff: Statistics,
}

pub type Edge<'a> = search_graph::Edge<'a, Statistics, ActionData>;
pub type Graph = search_graph::Graph<Statistics, ActionData>;
pub type Node<'a> = search_graph::Node<'a, Statistics, ActionData>;

pub enum RolloutResult<'a> {
    Unexpanded(Edge<'a>),
    Terminal(Node<'a>),
    Cycle,
}

pub fn rollout<'a>(mut node: Node<'a>, state: &mut game::State) -> RolloutResult<'a> {
    loop {
        let children = node.child_list();
        if children.is_empty() {
            return RolloutResult::Terminal(node)
        }
        let mut i = 0;
        let mut best_child_index = 0;
        let mut best_child_score = 0.0;
        while i < children.len() {
            let edge = children.get_edge(i);
            match edge.target() {
                search_graph::Target::Unexpanded => {
                    state.do_action(&edge.data().action);
                    return RolloutResult::Unexpanded(edge)
                },
                search_graph::Target::Cycle(_) => (),
                search_graph::Target::Expanded(_) => {
                    let child_score = 0.0;
                    if child_score > best_child_score {
                        // TODO tie-breaking.
                        best_child_score = child_score;
                        best_child_index = i;
                    }
                },
            }
            i += 1;
        }
        let edge = children.get_edge(best_child_index);
        match edge.target() {
            search_graph::Target::Expanded(child) => {
                state.do_action(&edge.data().action);
                node = child;
            },
            _ => return RolloutResult::Cycle,
        }
    }
}

pub fn simulate<R>(mut state: game::State, mut rng: R) -> Payoff where R: Rng {
    loop {
        let action = match payoff(&state) {
            None => {
                let mut actions = state.role_actions(state.active_player().role());
                let mut selected = None;
                let mut i = 0;
                loop {
                    match actions.next() {
                        None => break,
                        Some(a) => {
                            if i == 0 {
                                selected = Some(a);
                            } else if rng.next_f64() < (1.0 / (i as f64)) {
                                selected = Some(a);
                            }
                            i += 1;
                        },
                    }
                }
                selected.expect("Terminal state has no payoff")
            },
            Some(p) => return p,
        };
        state.do_action(&action);
    }
}

fn role_payoff(r: game::Role) -> usize {
    match r {
        game::Role::Dwarf => 1,
        game::Role::Troll => 4,
    }
}

pub fn payoff(state: &game::State) -> Option<Payoff> {
    if state.terminated() {
        let player_1_role = state.player(game::PlayerMarker::One).role();
        let player_1_role_payoff = role_payoff(player_1_role);
        let player_2_role = state.player(game::PlayerMarker::Two).role();
        let player_2_role_payoff = role_payoff(player_2_role);
        let mut payoff = Payoff::new();
        let mut i = state.board().cells_iter();
        loop {
            match i.next() {
                Some((_, board::Content::Occupied(t))) if t.role() == Some(player_1_role) =>
                    payoff.values[0] += player_1_role_payoff,
                Some((_, board::Content::Occupied(t))) if t.role() == Some(player_2_role) =>
                    payoff.values[1] += player_2_role_payoff,
                None => break,
                _ => (),
            }
        }
        Some(payoff)
    } else {
        None
    }
}
<|endoftext|>


<commit_before>
use super::raw_vec::*;
use super::plan::*;
use super::enums::*;
use super::r2r::*;

use num_traits::Zero;

pub struct Pair<A, B> {
    pub field: RawVec<A>,
    pub coef: RawVec<B>,
    logical_size: usize,
    forward: Plan<A, B>,
    backward: Plan<B, A>,
}

impl<A, B> Pair<A, B> {
    pub fn logical_size(&self) -> usize { self.logical_size }

    pub fn forward(&mut self) {
        unsafe {
            self.forward.execute();
        }
    }

    pub fn backward(&mut self) {
        unsafe {
            self.backward.execute();
        }
    }
}

impl<R> Pair<R, R>
    where R: R2RPlanCreate + AlignedAllocable + Zero
{
    pub fn r2r_1d(n: usize, kind: R2R_KIND, flag: FLAG) -> Self {
        let mut field = RawVec::new(n);
        let mut coef = RawVec::new(n);
        let forward = Plan::r2r_1d(n, &mut field, &mut coef, forward(kind), flag);
        let backward = Plan::r2r_1d(n, &mut coef, &mut field, backward(kind), flag);
        Pair {
            field: field,
            coef: coef,
            logical_size: logical_size(n, kind),
            forward: forward,
            backward: backward,
        }
    }
}

impl<C> Pair<C, C>
    where C: C2CPlanCreate + AlignedAllocable + Zero
{
    pub fn c2c_1d(n: usize, sign: SIGN, flag: FLAG) -> Self {
        let mut field = RawVec::new(n);
        let mut coef = RawVec::new(n);
        let forward = Plan::c2c_1d(n, &mut field, &mut coef, sign, flag);
        let backward = Plan::c2c_1d(n, &mut coef, &mut field, -sign, flag);
        Pair {
            field: field,
            coef: coef,
            logical_size: n,
            forward: forward,
            backward: backward,
        }
    }
}

impl<R, C> Pair<R, C>
    where (C, R): C2RPlanCreate<Real = R, Complex = C>,
          R: AlignedAllocable + Zero,
          C: AlignedAllocable + Zero
{
    pub fn r2c_1d(n: usize, flag: FLAG) -> Self {
        let mut field = RawVec::<R>::new(n);
        let mut coef = RawVec::<C>::new(n / 2 + 1);
        let forward = Plan::r2c_1d(n, &mut field, &mut coef, flag);
        let backward = Plan::c2r_1d(n, &mut coef, &mut field, flag);
        Pair {
            field: field,
            coef: coef,
            logical_size: n,
            forward: forward,
            backward: backward,
        }
    }
}
<commit_msg>Write doc of Pair module<commit_after>//! Safe-interface corresponding to out-place transform

use super::raw_vec::*;
use super::plan::*;
use super::enums::*;
use super::r2r::*;

use num_traits::Zero;

//! Safe-interface corresponding to out-place transform
//!
//! FFTW interface modifies an array in `fftw_execute` function
//! which does not takes the array as its arguments.
//! It is not compatible to the programing model of safe Rust.
//! `Pair` interface composes the array and plan to manage
//! mutability in the safe Rust way.
pub struct Pair<A, B> {
    pub field: RawVec<A>,
    pub coef: RawVec<B>,
    logical_size: usize,
    forward: Plan<A, B>,
    backward: Plan<B, A>,
}

impl<A, B> Pair<A, B> {
    pub fn logical_size(&self) -> usize { self.logical_size }

    /// Execute forward transformation
    pub fn forward(&mut self) {
        unsafe {
            self.forward.execute();
        }
    }

    /// Execute backward transformation
    pub fn backward(&mut self) {
        unsafe {
            self.backward.execute();
        }
    }
}

impl<R> Pair<R, R>
    where R: R2RPlanCreate + AlignedAllocable + Zero
{
    /// Create one-dimensional Real-to-Real transformation pair
    pub fn r2r_1d(n: usize, kind: R2R_KIND, flag: FLAG) -> Self {
        let mut field = RawVec::new(n);
        let mut coef = RawVec::new(n);
        let forward = Plan::r2r_1d(n, &mut field, &mut coef, forward(kind), flag);
        let backward = Plan::r2r_1d(n, &mut coef, &mut field, backward(kind), flag);
        Pair {
            field: field,
            coef: coef,
            logical_size: logical_size(n, kind),
            forward: forward,
            backward: backward,
        }
    }
}

impl<C> Pair<C, C>
    where C: C2CPlanCreate + AlignedAllocable + Zero
{
    /// Create one-dimensional Complex-to-Complex transformation pair
    pub fn c2c_1d(n: usize, sign: SIGN, flag: FLAG) -> Self {
        let mut field = RawVec::new(n);
        let mut coef = RawVec::new(n);
        let forward = Plan::c2c_1d(n, &mut field, &mut coef, sign, flag);
        let backward = Plan::c2c_1d(n, &mut coef, &mut field, -sign, flag);
        Pair {
            field: field,
            coef: coef,
            logical_size: n,
            forward: forward,
            backward: backward,
        }
    }
}

impl<R, C> Pair<R, C>
    where (C, R): C2RPlanCreate<Real = R, Complex = C>,
          R: AlignedAllocable + Zero,
          C: AlignedAllocable + Zero
{
    /// Create one-dimensional Real-to-Complex transformation pair
    pub fn r2c_1d(n: usize, flag: FLAG) -> Self {
        let mut field = RawVec::<R>::new(n);
        let mut coef = RawVec::<C>::new(n / 2 + 1);
        let forward = Plan::r2c_1d(n, &mut field, &mut coef, flag);
        let backward = Plan::c2r_1d(n, &mut coef, &mut field, flag);
        Pair {
            field: field,
            coef: coef,
            logical_size: n,
            forward: forward,
            backward: backward,
        }
    }
}
<|endoftext|>


<commit_before>use std::io::Write;
use std::fmt;
use std::cmp;

const DEFAULT_NUMBER_OF_SAMPLES:usize = 31;

#[derive(Debug)]
pub struct SampleInfo {
	pub name: String, // [char; 22],
	pub length: u16, // In words, so multiply by 2
	pub finetune: u8,
	pub volume: u8, // 0-64
	pub repeat_start: u16, // In words from start of sample data, so multiply by 2
	pub repeat_length: u16, // Number of words to loop, multiply by 2
}

impl Default for SampleInfo {
	fn default() -> SampleInfo {
		SampleInfo{name: String::new(), length:0, finetune:0, volume:0, repeat_start:0, repeat_length:0}
	}
}

#[derive(Debug)]
pub struct Channel {
	pub period: u16, // Really u12
	pub sample_number: u8,
	pub effect: u16 // Really u12
}

#[derive(Debug)]
pub struct Row {
	pub channels: Vec<Channel>
}

impl Default for Row {
	fn default() -> Row {
		let mut row = Row{channels: Vec::new()};
		for _ in 0..4 {
			let c = Channel{period: 0, sample_number: 0, effect: 0};
			row.channels.push(c);
		}

		row
	}
}

#[derive(Debug)]
pub struct Pattern {
	pub rows: Vec<Row>
}

impl Default for Pattern {
	fn default() -> Pattern {
		let mut p = Pattern{rows: Vec::new()};

		for _ in 0..64 {
			let row:Row = Default::default();
			p.rows.push(row);
		}

		p
	}
}

pub struct Positions {
	pub data: [u8; 128]
}

impl fmt::Debug for Positions {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.data[..].fmt(formatter)
    }
}

#[derive(Debug)]
pub struct PTModule {
	pub name: String, // [char; 20],
	pub sample_info: Vec<SampleInfo>, // [SampleInfo; DEFAULT_NUMBER_OF_SAMPLES]
	pub length: u8, // Length 1-128
	pub nt_restart: u8, // Set to 127
	pub positions: Positions, // The order in which to play patterns
	pub mk: [u8; 4], // Set to M.K.
	pub patterns: Vec<Pattern>,
	pub sample_data: Vec<Vec<u8>> // The bytes in the samples -127 - 127
}

impl Default for PTModule {
	fn default() -> PTModule {
		let mut ptmod = PTModule{name: String::new(), sample_info: Vec::new(), length:0, nt_restart: 127,
			positions: Positions{data: [0; 128]}, mk: ['M' as u8, '.' as u8, 'K' as u8, '.' as u8], patterns: Vec::new(), sample_data: Vec::new() };

		for _ in 0..DEFAULT_NUMBER_OF_SAMPLES {
			let si: SampleInfo = Default::default();
			ptmod.sample_info.push(si);
		}

		ptmod
	}
}

fn write_or_panic(writer: &mut Write, data: &[u8]) {
	match writer.write_all(&data) {
		Ok(_) => (),
		_ => panic!("Failed to write bytes")
	};
}

fn write_0_padded_string(writer: &mut Write, str: &String, len: usize) {
	let mut data = vec![0u8; len];
	let str_buf = str.as_bytes();
	let m = cmp::min(data.len(),str_buf.len());
	for i in 0..m {
		data[i] = str_buf[i];
	}

	write_or_panic(writer, &data);
}

fn write_big_endian_u16(writer: &mut Write, val: u16) {
	let mut data = [0u8; 2];
	data[0] = (val >> 8) as u8;
	data[1] = (val & 0xff) as u8;

	write_or_panic(writer, &data);
}

fn write_u8(writer: &mut Write, val: u8) {
	let mut data = [0u8; 1];
	data[0] = val;

	write_or_panic(writer, &data);
}

pub fn write_mod(writer: &mut Write, module: &mut PTModule) {

	// First write songname, 20 bytes, pad with 0
	write_0_padded_string(writer,&module.name,20);
	// Then write all 32 samples
	// TODO Handle the case when the vector has less than 31 samples
	let mut num_samples = 0;
	for i in 0..DEFAULT_NUMBER_OF_SAMPLES {
		let ref si = module.sample_info[i];
		// Sample name
		write_0_padded_string(writer, &si.name, 22);
		// Sample length
		write_big_endian_u16(writer, si.length);
		if si.length > 0 {
			num_samples += 1;
		}
		// Finetune
		write_u8(writer, si.finetune);
		// Volume
		write_u8(writer, si.volume);
		// Repeat start
		write_big_endian_u16(writer, si.repeat_start);
		// Repeat length
		write_big_endian_u16(writer, si.repeat_length);
	}

	let num_samples = num_samples;
	// Songlength
	write_u8(writer, module.length);
	// nt_restart
	write_u8(writer, module.nt_restart);
	// Song positions
	write_or_panic(writer,&module.positions.data);
	// M.K.
	write_or_panic(writer,&module.mk);

	// All patterns
	for pattern_it in module.patterns.iter() {
		// All rows
		for row_it in pattern_it.rows.iter() {
			// All channels
			for channel_it in row_it.channels.iter() {
				let mut data = [0u8; 4];

				data[0] = (channel_it.sample_number & 0xf0) | ((channel_it.period & 0xf00) >> 8) as u8;
				data[1] = (channel_it.period & 0xff) as u8;
				data[2] = ((channel_it.sample_number & 0x0f) << 4) | ((channel_it.effect & 0xf00) >> 8) as u8;
				data[3] = (channel_it.effect & 0xff) as u8;

				write_or_panic(writer,&data);
			}
		}
	}

	// And finally all samples
	for sample_it in module.sample_data.iter() {
		write_or_panic(writer,sample_it);
	}

	if num_samples != module.sample_data.len() {
		println!("Warning! Number of samples does not match sample data");
	}
}
<commit_msg>Started with reading<commit_after>use std::io::Write;
use std::io::Read;
use std::fmt;
use std::cmp;

const DEFAULT_NUMBER_OF_SAMPLES:usize = 31;

#[derive(Debug)]
pub struct SampleInfo {
	pub name: String, // [char; 22],
	pub length: u16, // In words, so multiply by 2
	pub finetune: u8,
	pub volume: u8, // 0-64
	pub repeat_start: u16, // In words from start of sample data, so multiply by 2
	pub repeat_length: u16, // Number of words to loop, multiply by 2
}

impl Default for SampleInfo {
	fn default() -> SampleInfo {
		SampleInfo{name: String::new(), length:0, finetune:0, volume:0, repeat_start:0, repeat_length:0}
	}
}

#[derive(Debug)]
pub struct Channel {
	pub period: u16, // Really u12
	pub sample_number: u8,
	pub effect: u16 // Really u12
}

#[derive(Debug)]
pub struct Row {
	pub channels: Vec<Channel>
}

impl Default for Row {
	fn default() -> Row {
		let mut row = Row{channels: Vec::new()};
		for _ in 0..4 {
			let c = Channel{period: 0, sample_number: 0, effect: 0};
			row.channels.push(c);
		}

		row
	}
}

#[derive(Debug)]
pub struct Pattern {
	pub rows: Vec<Row>
}

impl Default for Pattern {
	fn default() -> Pattern {
		let mut p = Pattern{rows: Vec::new()};

		for _ in 0..64 {
			let row:Row = Default::default();
			p.rows.push(row);
		}

		p
	}
}

pub struct Positions {
	pub data: [u8; 128]
}

impl fmt::Debug for Positions {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.data[..].fmt(formatter)
    }
}

#[derive(Debug)]
pub struct PTModule {
	pub name: String, // [char; 20],
	pub sample_info: Vec<SampleInfo>, // [SampleInfo; DEFAULT_NUMBER_OF_SAMPLES]
	pub length: u8, // Length 1-128
	pub nt_restart: u8, // Set to 127
	pub positions: Positions, // The order in which to play patterns
	pub mk: [u8; 4], // Set to M.K.
	pub patterns: Vec<Pattern>,
	pub sample_data: Vec<Vec<u8>> // The bytes in the samples -127 - 127
}

impl Default for PTModule {
	fn default() -> PTModule {
		let mut ptmod = PTModule{name: String::new(), sample_info: Vec::new(), length:0, nt_restart: 127,
			positions: Positions{data: [0; 128]}, mk: ['M' as u8, '.' as u8, 'K' as u8, '.' as u8], patterns: Vec::new(), sample_data: Vec::new() };

		for _ in 0..DEFAULT_NUMBER_OF_SAMPLES {
			let si: SampleInfo = Default::default();
			ptmod.sample_info.push(si);
		}

		ptmod
	}
}

fn read_or_panic(reader: &mut Read, data: &mut [u8]) {
	match reader.read(data) {
		Ok(n) if n == data.len() => (),
		_ => panic!("Failed to read bytes")
	};
}

fn write_or_panic(writer: &mut Write, data: &[u8]) {
	match writer.write_all(&data) {
		Ok(_) => (),
		_ => panic!("Failed to write bytes")
	};
}

fn read_0_padded_string(reader: &mut Read, len: usize) -> String {
	let mut data = vec![0u8; len];
	read_or_panic(reader,&mut data);
	let mut str = String::new();
	for byte in data {
		if byte != 0 {
			str.push(byte as char);
		}
	}

	str
}

fn write_0_padded_string(writer: &mut Write, str: &String, len: usize) {
	let mut data = vec![0u8; len];
	let str_buf = str.as_bytes();
	let m = cmp::min(data.len(),str_buf.len());
	for i in 0..m {
		data[i] = str_buf[i];
	}

	write_or_panic(writer, &data);
}

fn read_big_endian_u16(reader: &mut Read) -> u16 {
	let mut data_arr = [0u8; 2];
	read_or_panic(reader,&mut data_arr);

	let mut data:u16 = 0;

	for n in data_arr.iter() {
		data = (data << 8) + *n as u16;
	}

	data
}

fn write_big_endian_u16(writer: &mut Write, val: u16) {
	let mut data = [0u8; 2];
	data[0] = (val >> 8) as u8;
	data[1] = (val & 0xff) as u8;

	write_or_panic(writer, &data);
}

fn read_u8(reader: &mut Read) -> u8 {
	let mut data = [0u8; 1];

	read_or_panic(reader, &mut data);

	data[0]
}

fn write_u8(writer: &mut Write, val: u8) {
	let mut data = [0u8; 1];
	data[0] = val;

	write_or_panic(writer, &data);
}

pub fn write_mod(writer: &mut Write, module: &mut PTModule) {

	// First write songname, 20 bytes, pad with 0
	write_0_padded_string(writer,&module.name,20);
	// Then write all 32 samples
	// TODO Handle the case when the vector has less than 31 samples
	let mut num_samples = 0;
	for i in 0..DEFAULT_NUMBER_OF_SAMPLES {
		let ref si = module.sample_info[i];
		// Sample name
		write_0_padded_string(writer, &si.name, 22);
		// Sample length
		write_big_endian_u16(writer, si.length);
		if si.length > 0 {
			num_samples += 1;
		}
		// Finetune
		write_u8(writer, si.finetune);
		// Volume
		write_u8(writer, si.volume);
		// Repeat start
		write_big_endian_u16(writer, si.repeat_start);
		// Repeat length
		write_big_endian_u16(writer, si.repeat_length);
	}

	let num_samples = num_samples;
	// Songlength
	write_u8(writer, module.length);
	// nt_restart
	write_u8(writer, module.nt_restart);
	// Song positions
	write_or_panic(writer,&module.positions.data);
	// M.K.
	write_or_panic(writer,&module.mk);

	// All patterns
	for pattern_it in module.patterns.iter() {
		// All rows
		for row_it in pattern_it.rows.iter() {
			// All channels
			for channel_it in row_it.channels.iter() {
				let mut data = [0u8; 4];

				data[0] = (channel_it.sample_number & 0xf0) | ((channel_it.period & 0xf00) >> 8) as u8;
				data[1] = (channel_it.period & 0xff) as u8;
				data[2] = ((channel_it.sample_number & 0x0f) << 4) | ((channel_it.effect & 0xf00) >> 8) as u8;
				data[3] = (channel_it.effect & 0xff) as u8;

				write_or_panic(writer,&data);
			}
		}
	}

	// And finally all samples
	for sample_it in module.sample_data.iter() {
		write_or_panic(writer,sample_it);
	}

	if num_samples != module.sample_data.len() {
		println!("Warning! Number of samples does not match sample data");
	}
}

pub fn read_mod(reader: &mut Read) -> PTModule {
	let mut module:PTModule = Default::default();

	// First read 20 bytes songname
	module.name = read_0_padded_string(reader, 20);
	// Read all sample info
	// TODO Handle 15 sample files
	let mut num_samples = 0;
	for i in 0..DEFAULT_NUMBER_OF_SAMPLES {
		let si = &mut module.sample_info[i];
		// Sample name
		si.name = read_0_padded_string(reader, 22);
		si.length = read_big_endian_u16(reader);
		if si.length > 0 {
			num_samples += 1;
		}
		// Finetune
		si.finetune = read_u8(reader);
		// Volume
		si.volume = read_u8(reader);
		// Repeat start
		si.repeat_start = read_big_endian_u16(reader);
		// Repeat length
		si.repeat_length = read_big_endian_u16(reader);
	}

	// Songlength
	module.length = read_u8(reader);
	// nt_restart
	module.nt_restart = read_u8(reader);
	// Song positions
	read_or_panic(reader,&mut module.positions.data);
	// M.K.
	read_or_panic(reader,&mut module.mk);

	module
}
<|endoftext|>