<commit_before>extern crate num;
extern crate portaudio;
extern crate rtlsdr;
extern crate dft;
extern crate gnuplot;

use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::Zero;
use num::complex::Complex;
use std::env;
use std::f32::consts::PI;
use std::error::Error;

use gnuplot::*;
use dft::{Operation, Plan};

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8.
const SDR_BUF_SIZE: usize = 262144;

// Separating out the buffer sizes seems to help some.
const BUF_SIZE: usize = 262144;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SAMPLE_RATE: u32 = 2880000;

// Here is the sample rate of the output waveform we'll try to use.
const SAMPLE_RATE_AUDIO: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args().nth(1)
        .expect("Please specify the SDR index")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args().nth(2)
        .expect("Please specify a center frequency (MHz).")
        .parse::<f32>()?;
    let bandwidth: u32 = env::args().nth(3)
        .expect("Please specify the bandwidth.")
        .parse::<u32>()?;

    // Initialize the PortAudio class.
    let audio = try!(pa::PortAudio::new());
    let settings =
        try!(audio.default_output_stream_settings(CHANNELS,
                                                  SAMPLE_RATE_AUDIO as f64,
                                                  BUF_SIZE as u32));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;

    // We were decimating way too much. We need to decimate in two stages: one
    // to remove nearby stations and another to match the sound card. For
    // wideband signals, 8 and 3 seems to work well and also hits that sweet
    // spot of no buffer underflows!
    //
    // TODO: need to still calculate this on the fly. In addition, we need to
    // find apporpriate decimation values for narrowband. I'm still confident
    // that the decimation value depends on the bandwitdh, but I need to
    // figure out that appropriate formula.
    //
    let dec_rate_filt = 9;
    let dec_rate_audio = 3;
    let mut sdr =
        RTLSDR { rtlsdr: init_sdr(sdr_index, fm_freq, bandwidth).unwrap() };

    // This holds the previous value for the moving average filter so we can
    // keep track in between iterations of reading from the SDR.
    let mut prev = Complex::new(0.0, 0.0);

    // TODO: the number of taps here really affects the speed of the audio. Is
    // the filter decimating or am I just doing the filter wrong?
    let taps_filt = low_pass(bandwidth as f32, SAMPLE_RATE as f32, 8);
    let taps_audio = low_pass(bandwidth as f32 / dec_rate_filt as f32,
                              SAMPLE_RATE as f32 / dec_rate_filt as f32,
                              8);

    loop {
        // Read the samples and decimate down to match the sample rate of
        // the audio that'll be going out.
        let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
        let mut iq_vec = read_samples(bytes).unwrap();
        iq_vec = filter(iq_vec, taps_filt.clone());
        iq_vec = decimate(iq_vec.as_slice(), dec_rate_filt);

        // After decimation, demodulate the signal and send out of the
        // thread to the receiver.
        let res = demod_fm(iq_vec, prev);
        let mut demod_iq = filter_real(res.0, taps_audio.clone());
        demod_iq = decimate(demod_iq.as_slice(), dec_rate_audio);
        prev = res.1;

        // Get the write stream and write our samples to the stream.
        let out_frames = match stream.write_available() {
            Ok(available) => {
                match available {
                    pa::StreamAvailable::Frames(frames) => frames as u32,
                    pa::StreamAvailable::OutputUnderflowed =>
                        return Err(Box::new(pa::error::Error::OutputUnderflowed)),
                    _ => return Err(Box::new(pa::error::Error::NullCallback)),
                }
            }
            Err(e) => return Err(Box::new(e)),
        };

        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let write_frames = std::cmp::min(buffer_frames, out_frames);
        let n_write_samples = write_frames as usize * CHANNELS as usize;

        stream.write(write_frames,
                   |output| for ix in 0..n_write_samples as usize {
                       output[ix] = 0.005 * demod_iq[ix];
                   })?;
    }
}

fn plot_spectrum<'a>(signal: &Vec<Complex<f32>>,
                     figure: &'a mut Figure)
                     -> &'a mut Figure {
    let mut sig = signal.clone();
    let radix_2: u32 = (sig.len() as f32).log2().ceil() as u32;
    let new_len = 2u32.pow(radix_2) as usize;
    println!("signal len: {}, new len: {}", sig.len(), new_len);
    sig.resize(new_len, Complex::zero());
    let plan = Plan::new(Operation::Forward, new_len);
    dft::transform(&mut sig, &plan);

    // Now generate a plot.
    figure.clear_axes();
    figure
        .axes2d()
        .lines(0..new_len, sig.iter().map(|x| x.norm()), &[]);
    figure.show();
    figure
}

fn init_sdr(sdr_index: i32,
            fm_freq: u32,
            bandwidth: u32)
            -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SAMPLE_RATE));
    try!(sdr.set_tuner_bandwidth(bandwidth));
    try!(sdr.set_agc_mode(true));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

fn decimate<T: Copy>(signal: &[T], dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

fn read_samples(bytes: Vec<u8>) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;

    }
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);

    // Write the values to the complex value and normalize from [0, 255] to
    // [-1, 1]. If we don't normalize, it seems we don't get anything.
    for iq in bytes.chunks(2) {
        let iq_cmplx = Complex::new((iq[0] as f32 - 127.0) / 127.0,
                                    (iq[1] as f32 - 127.0) / 127.0);
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

fn demod_fm(iq: Vec<Complex<f32>>,
            prev: Complex<f32>)
            -> (Vec<f32>, Complex<f32>) {

    let mut p = prev.clone();
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());
    let gain = SAMPLE_RATE as f32 / (2.0 * PI * 75e3 / 8.0);

    for samp in iq.iter() {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

fn filter(samples: Vec<Complex<f32>>, taps: Vec<f32>) -> Vec<Complex<f32>> {
    let mut filt_samps: Vec<Complex<f32>> = Vec::new();
    for window in samples.as_slice().windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.map(|(x, y)| x * y)
            .fold(Complex::new(0.0, 0.0), |acc, x| acc + x);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

fn filter_real(samples: Vec<f32>, taps: Vec<f32>) -> Vec<f32> {
    let mut filt_samps: Vec<f32> = Vec::new();
    for window in samples.as_slice().windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.map(|(x, y)| x * y).fold(0.0, |acc, x| acc + x);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

fn low_pass(cutoff_freq: f32, sample_rate: f32, ntaps: usize) -> Vec<f32> {
    let wc: f32 = 2.0 * PI * cutoff_freq / sample_rate;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    let win_taps: Vec<f32> = hamming(ntaps);
    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f: f32 = ix as f32;
        if ix == 0 {
            let hi = wc / PI * win_taps[(ix + m) as usize];
            taps.push(hi);
        } else {
            let hi = (ix_f * wc).sin() / (ix_f * PI) *
                     win_taps[(ix + m) as usize];
            taps.push(hi);
        }
    }
    taps
}

#[inline]
fn moving_average(ntaps: usize) -> Vec<f32> {
    vec![1.0 / ntaps as f32; ntaps]
}
<commit_msg>Made filter and filter_real generic<commit_after>extern crate num;
extern crate portaudio;
extern crate rtlsdr;
extern crate dft;
extern crate gnuplot;

use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::{Num, Zero};
use num::complex::Complex;
use std::env;
use std::f32::consts::PI;
use std::error::Error;
use pa::error::Error as PAError;

use gnuplot::*;
use dft::{Operation, Plan};

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8.
const SDR_BUF_SIZE: usize = 262144;

// Separating out the buffer sizes seems to help some.
const BUF_SIZE: usize = 262144;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SAMPLE_RATE: u32 = 2880000;

// Here is the sample rate of the output waveform we'll try to use.
const SAMPLE_RATE_AUDIO: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args().nth(1)
        .expect("Please specify the SDR index")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args().nth(2)
        .expect("Please specify a center frequency (MHz).")
        .parse::<f32>()?;
    let bandwidth: u32 = env::args().nth(3)
        .expect("Please specify the bandwidth.")
        .parse::<u32>()?;

    // Initialize the PortAudio class.
    let audio = try!(pa::PortAudio::new());
    let settings =
        try!(audio.default_output_stream_settings(CHANNELS,
                                                  SAMPLE_RATE_AUDIO as f64,
                                                  BUF_SIZE as u32));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;

    // We were decimating way too much. We need to decimate in two stages: one
    // to remove nearby stations and another to match the sound card. For
    // wideband signals, 8 and 3 seems to work well and also hits that sweet
    // spot of no buffer underflows!
    //
    // TODO: need to still calculate this on the fly. In addition, we need to
    // find apporpriate decimation values for narrowband. I'm still confident
    // that the decimation value depends on the bandwitdh, but I need to
    // figure out that appropriate formula.
    //
    let dec_rate_filt = 9;
    let dec_rate_audio = 3;
    let mut sdr =
        RTLSDR { rtlsdr: init_sdr(sdr_index, fm_freq, bandwidth).unwrap() };

    // This holds the previous value for the moving average filter so we can
    // keep track in between iterations of reading from the SDR.
    let mut prev = Complex::new(0.0, 0.0);

    // TODO: the number of taps here really affects the speed of the audio. Is
    // the filter decimating or am I just doing the filter wrong?
    let taps_filt = windowed_sinc(bandwidth as f32, SAMPLE_RATE as f32, 8);
    let taps_audio = windowed_sinc(bandwidth as f32 / dec_rate_filt as f32,
                                   SAMPLE_RATE as f32 / dec_rate_filt as f32,
                                   8);

    loop {
        // Read the samples and decimate down to match the sample rate of
        // the audio that'll be going out.
        let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
        let mut iq_vec = read_samples(bytes).unwrap();
        iq_vec = filter(&iq_vec, &taps_filt);
        iq_vec = decimate(iq_vec.as_slice(), dec_rate_filt);

        // After decimation, demodulate the signal and send out of the
        // thread to the receiver.
        let res = demod_fm(iq_vec, prev);
        let mut demod_iq = filter_real(&res.0, &taps_audio);
        demod_iq = decimate(demod_iq.as_slice(), dec_rate_audio);
        prev = res.1;

        // Get the write stream and write our samples to the stream.
        let out_frames = match stream.write_available() {
            Ok(available) => {
                match available {
                    pa::StreamAvailable::Frames(frames) => frames as u32,
                    pa::StreamAvailable::OutputUnderflowed => {
                        return Err(Box::new(PAError::OutputUnderflowed))
                    }
                    _ => return Err(Box::new(PAError::NullCallback)),
                }
            }
            Err(e) => return Err(Box::new(e)),
        };

        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let write_frames = std::cmp::min(buffer_frames, out_frames);
        let n_write_samples = write_frames as usize * CHANNELS as usize;

        stream.write(write_frames,
                   |output| for ix in 0..n_write_samples as usize {
                       output[ix] = 0.005 * demod_iq[ix];
                   })?;
    }
}

fn plot_spectrum<'a>(signal: &Vec<Complex<f32>>,
                     figure: &'a mut Figure)
                     -> &'a mut Figure {
    let mut sig = signal.clone();
    let radix_2: u32 = (sig.len() as f32).log2().ceil() as u32;
    let new_len = 2u32.pow(radix_2) as usize;
    sig.resize(new_len, Complex::zero());
    let plan = Plan::new(Operation::Forward, new_len);
    dft::transform(&mut sig, &plan);

    // Now generate a plot.
    figure.clear_axes();
    figure
        .axes2d()
        .lines(0..new_len, sig.iter().map(|x| x.norm()), &[]);
    figure.show();
    figure
}

fn init_sdr(sdr_index: i32,
            fm_freq: u32,
            bandwidth: u32)
            -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SAMPLE_RATE));
    try!(sdr.set_tuner_bandwidth(bandwidth));
    try!(sdr.set_agc_mode(true));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

fn decimate<T: Copy>(signal: &[T], dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

fn read_samples(bytes: Vec<u8>) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;

    }
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);

    // Write the values to the complex value and normalize from [0, 255] to
    // [-127, 128].
    for iq in bytes.chunks(2) {
        let iq_cmplx = Complex::new((iq[0] as f32 - 127.0),
                                    (iq[1] as f32 - 127.0));
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

fn demod_fm(iq: Vec<Complex<f32>>,
            prev: Complex<f32>)
            -> (Vec<f32>, Complex<f32>) {

    let mut p = prev.clone();
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());
    let gain = SAMPLE_RATE as f32 / (2.0 * PI * 75e3 / 8.0);

    for samp in iq.iter() {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

fn filter<T: Copy + Num + Zero>(samples: &Vec<Complex<T>>,
                                taps: &Vec<T>)
                                -> Vec<Complex<T>> {
    let mut filt_samps: Vec<Complex<T>> = Vec::new();
    for window in samples.as_slice().windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.map(|(x, y)| *x * *y)
            .fold(Complex::zero(), |acc, x| acc + x);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

fn filter_real<T: Copy + Num + Zero>(samples: &Vec<T>,
                                     taps: &Vec<T>)
                                     -> Vec<T> {
    let mut filt_samps: Vec<T> = Vec::new();
    for window in samples.as_slice().windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.map(|(x, y)| *x * *y)
            .fold(T::zero(), |acc, x| acc + x);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

///
/// Generates taps for a Hamming window.
///
fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

///
/// Generates filter taps for a sinc filter with a Hamming window.
///
fn windowed_sinc(cutoff_freq: f32, sample_rate: f32, ntaps: usize) -> Vec<f32> {
    let wc: f32 = 2.0 * PI * cutoff_freq / sample_rate;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    let win_taps: Vec<f32> = hamming(ntaps);
    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f: f32 = ix as f32;
        if ix == 0 {
            let hi = wc / PI * win_taps[(ix + m) as usize];
            taps.push(hi);
        } else {
            let hi = (ix_f * wc).sin() / (ix_f * PI) *
                     win_taps[(ix + m) as usize];
            taps.push(hi);
        }
    }
    taps
}
<|endoftext|>


<commit_before>/*
csql2mongo
Utility to convert a SQL dump to a MongoDB JSON dump.

Copyright 2016 Sam Saint-Pettersen.
Licensed under the MIT/X11 License.

Rust port of original Python tool (1.0.6).
*/

extern crate clioptions;
extern crate regex;
use clioptions::CliOptions;
use regex::Regex;
use std::io::{BufRead, BufReader, Write};
use std::fs::File;
use std::process::exit;

fn preprocess_sql(lines: Vec<String>) -> Vec<String> {
    let mut processed: Vec<String> = Vec::new();
    let patterns = vec![
        "VALUES \\(",
        ",",
        "\\),",
        "\\(",
        "\n\n",
    ];

    let repls = vec![
        "VALUE (\n",
        ",\n",
        "\nINSERT INTO `null` VALUES (\n",
        "",
        "\n",
    ];

    for line in lines {
        let mut i: usize = 0;
        let mut l = String::new();
        for p in patterns.clone() {
            let re = Regex::new(p).unwrap();
            l = re.replace(&line, repls[i]);
            i += 1;
        }
        if l.len() > 0 {
            processed.push(l);
        }
    }
    processed
}

fn convert_sql_to_json(input: &str, output: &str, tz: bool, mongo_types: bool, array: bool, verbose: bool) {
    let mut lines: Vec<String> = Vec::new();
    let f = File::open(input).unwrap();
    let file = BufReader::new(&f);
    for line in file.lines() {
        lines.push(line.unwrap());
    }

    // Preprocess SQL dump so that it is compatible for conversion
    let processed = preprocess_sql(lines);

    let mut fields: Vec<String> = Vec::new();
    let mut values: Vec<String> = Vec::new();
    let mut inserts: Vec<Vec<String>> = Vec::new();
    let mut headers = false;
    for line in processed {
        let mut re = Regex::new("CREATE TABLE|UNLOCK TABLES").unwrap();
        if re.is_match(&line) {
            headers = true;
        }
        re = Regex::new(r"(^[`a-zA-Z0-9_]+)").unwrap();
        if headers {
            for cap in re.captures_iter(&line) {
                let f = cap.at(1).unwrap();
                let mut re = Regex::new("`").unwrap();
                let mut f = re.replace(&f, "");
                re = Regex::new("CREATE|ENGINE|INSERT|PRIMARY|LOCK").unwrap();
                f = re.replace(&f, "");
                if f.len() > 0 {
                    fields.push(f);
                }
            }
        }
        re = Regex::new("INSERT INTO").unwrap();
        if re.is_match(&line) {
            headers = false;
        }
        re = Regex::new(r"(^[\d.]+)").unwrap();
        if !headers {
            for cap in re.captures_iter(&line) {
                values.push(cap.at(1).unwrap().to_string());
            }
        }
        re = Regex::new(r"'([\w\s]+)'").unwrap();
        if !headers {
            for cap in re.captures_iter(&line) {
                values.push(format!("\"{}\"", cap.at(1).unwrap().to_string()));
            }
        }
        re = Regex::new("(TRUE|FALSE|NULL)").unwrap();
        if !headers {
            for cap in re.captures_iter(&line) {
                values.push(cap.at(1).unwrap().to_string().to_lowercase());
            }
        }
        re = Regex::new(r"'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})'").unwrap();
        if !headers {
            for cap in re.captures_iter(&line) {
                let mut v = cap.at(1).unwrap().to_string();
                let re = Regex::new(r"\s").unwrap();
                v = re.replace(&v, "T");
                v = format!("{}.000", v);
                if tz {
                    v = format!("{}Z", v);
                }
                else {
                    v = format!("{}+0000", v);
                }
                if mongo_types {
                    values.push(format!("{{\"$date\":\"{}\"}}", v));
                }
                else {
                    values.push(format!("\"{}\"", v));
                }
            }
        }
    }

    let v = &values;
    for record in v.chunks(fields.len()) {
        let mut formatted: Vec<String> = Vec::new();
        for (i, element) in record.into_iter().enumerate() {
            if fields[i] == "_id" && mongo_types {
                formatted.push(format!("{{\"$oid\":{}}}", element).to_string());
            }
            else {
                formatted.push(element.to_string());
            }
        }
        inserts.push(formatted);
    }

    let mut json: Vec<String> = Vec::new();
    let no_comma = inserts.len() - 1;
    for (x, r) in inserts.iter().enumerate() {
        let mut fr: Vec<String> = Vec::new();
        for (i, v) in r.iter().enumerate() {
            fr.push(format!("\"{}\":{}", fields[i], v));
        }
        let mut ac = String::new();
        if x == no_comma && array {
            ac = "".to_string();
        }
        else if array {
            ac = ",".to_string();
        }
        json.push(format!("{{{}}}{}", fr.join(","), ac));
    }

    if array {
        json.insert(0, "[".to_string());
        json.push("]".to_string());
    }

    json.push(String::new());

    if verbose {
        println!("Generating MongoDB JSON dump file: '{}' from\nSQL dump file: '{}'",
        output, input);
    }

    let mut w = File::create(output).unwrap();
    let _ = w.write_all(json.join("\n").as_bytes());
}

fn display_error(program: &str, err: &str) {
    println!("Error: {}.", err);
    display_usage(&program, -1);
}

fn display_usage(program: &str, code: i32) {
	println!("\ncsql2mongo");
	println!("Utility to convert a SQL dump to a MongoDB JSON dump.");
	println!("\nCopyright 2016 Sam Saint-Pettersen.");
	println!("Licensed under the MIT/X11 License.");
    println!("\nUsage: {} -f <input.sql> -o <output.json>\n-t -n -a -l [-v|-h]", program);
    exit(code);
}

fn display_version() {
    let signature = "csql2mongo 1.0.0 (https://github.com/stpettersens/csql2mongo#rust)";
    println!("\n{}", signature);
    exit(0);
}

fn main() {
	let cli = CliOptions::new("csql2mongo");
    let program = cli.get_program();
    let args = cli.get_args();
    let mut input = String::new();
    let mut output = String::new();
    let mut tz = false;
    let mut mongo_types = true;
    let mut array = false;
    let mut verbose = false;

    if cli.get_num() > 1 {
        for (i, a) in args.iter().enumerate() {

            if a == "-h" || a == "--help" {
                display_usage(&program, 0);
            }
            else if a == "-v" || a == "--version" {
                display_version();
            }

            if a == "-f" || a == "--file" {
                input = cli.next_argument(i);
            }
            if a == "-o" || a == "--out" {
                output = cli.next_argument(i);
            }
            if a == "-t" || a == "--tz" {
                tz = true;
            }
            if a == "-n" || a == "--no-mongo-types" {
                mongo_types = false;
            }
            if a == "-a" || a == "--array" {
                array = true;
            }
            if a == "-l" || a == "--verbose" {
                verbose = true;
            }
        }

        if input.len() > 0 && output.len() > 0 {
            convert_sql_to_json(&input, &output, tz, mongo_types, array, verbose);
        }
        else if input.len() == 0 {
            display_error(&program, "No input file specified");
        }
        else if output.len() == 0 {
            display_error(&program, "No output file specified");
        }
        else {
            display_error(&program, "Incomplete options provided");
        }

    }
    else {
        display_error(&program, "No options specified");
    }
}
<commit_msg>Delete main.rs<commit_after><|endoftext|>


<commit_before>mod logger;
mod toml_file;
extern crate toml;
extern crate regex;
extern crate semver;
extern crate commit_walker;
extern crate commit_analyzer;

use commit_analyzer::CommitType;

fn version_bump(version: Version, bump: CommitType) -> Option<Version> {
    let mut version = version.clone();
    match bump {
        CommitType::Unknown => return None,
        CommitType::Patch => version.increment_patch(),
        CommitType::Minor => version.increment_minor(),
        CommitType::Major => version.increment_major(),
    }

    Some(version)
}

use std::process;
use semver::Version;

fn main() {
    println!("semantic.rs 🚀");

    logger::stdout("Analyzing your repository");

    let version = match toml_file::read_from_file() {
        Ok(toml) => toml,
        Err(e) => {
            logger::stderr(format!("Reading `Cargo.toml` failed: {:?}", e));
            process::exit(1);
        }
    };

    let version = Version::parse(&version).expect("Not a valid version");
    logger::stdout(format!("Current version: {}", version.to_string()));

    logger::stdout("Analyzing commits");

    let bump = commit_walker::version_bump_since_latest(".");
    logger::stdout(format!("Commits analyzed. Bump will be {:?}", bump));

    let new_version = match version_bump(version, bump) {
        Some(new_version) => new_version,
        None => {
            logger::stdout("No version bump. Nothing to do.");
            process::exit(0);
        }
    };

    logger::stdout(format!("New version: {}", new_version.to_string()));
    toml_file::write_new_version(new_version.to_string());
}
<commit_msg>fix(main): Handle result of write_new_version<commit_after>mod logger;
mod toml_file;
extern crate toml;
extern crate regex;
extern crate semver;
extern crate commit_walker;
extern crate commit_analyzer;

use commit_analyzer::CommitType;

fn version_bump(version: Version, bump: CommitType) -> Option<Version> {
    let mut version = version.clone();
    match bump {
        CommitType::Unknown => return None,
        CommitType::Patch => version.increment_patch(),
        CommitType::Minor => version.increment_minor(),
        CommitType::Major => version.increment_major(),
    }

    Some(version)
}

use std::process;
use semver::Version;

fn main() {
    println!("semantic.rs 🚀");

    logger::stdout("Analyzing your repository");

    let version = match toml_file::read_from_file() {
        Ok(toml) => toml,
        Err(e) => {
            logger::stderr(format!("Reading `Cargo.toml` failed: {:?}", e));
            process::exit(1);
        }
    };

    let version = Version::parse(&version).expect("Not a valid version");
    logger::stdout(format!("Current version: {}", version.to_string()));

    logger::stdout("Analyzing commits");

    let bump = commit_walker::version_bump_since_latest(".");
    logger::stdout(format!("Commits analyzed. Bump will be {:?}", bump));

    let new_version = match version_bump(version, bump) {
        Some(new_version) => new_version,
        None => {
            logger::stdout("No version bump. Nothing to do.");
            process::exit(0);
        }
    };

    logger::stdout(format!("New version: {}", new_version.to_string()));
    match toml_file::write_new_version(new_version.to_string()) {
        Ok(_)    => { },
        Err(err) => logger::stderr(format!("Writing `Cargo.toml` failed: {:?}", err))
    }
}
<|endoftext|>


<commit_before>use conrod::UiCell;
use conrod::widget;

use conrod_helper::Gui;
use control::Flow;

widget_ids! {
    pub struct Ids {
        canvas,
        button,
        text,
    }
}

pub struct StartMenu();

impl Gui for StartMenu {
    type Ids = self::Ids;

    fn new() -> Self {
        StartMenu()
    }

    fn ids(&self, w: widget::id::Generator) -> Self::Ids {
        Self::Ids::new(w)
    }

    fn gui(&mut self, ui: &mut UiCell, ids: &Self::Ids) -> Option<Flow> {
        use conrod::{Widget, Positionable, Sizeable, Labelable};

        widget::Canvas::new().set(ids.canvas, ui);

        let button = widget::Button::new()
            .middle_of(ids.canvas)
            .label("Start game")
            .w_h(120.0, 30.0)
            .set(ids.button, ui);

        for _click in button {
            return Some(Flow::StartGame);
        }

        None
    }
}

pub struct PlayAgainMenu();

impl Gui for PlayAgainMenu {
    type Ids = self::Ids;

    fn new() -> Self {
        PlayAgainMenu()
    }

    fn ids(&self, w: widget::id::Generator) -> Self::Ids {
        Self::Ids::new(w)
    }

    fn gui(&mut self, ui: &mut UiCell, ids: &Self::Ids) -> Option<Flow> {
        use conrod::{Widget, Positionable, Sizeable, Labelable};

        widget::Canvas::new().set(ids.canvas, ui);

        let button = widget::Button::new()
            .middle_of(ids.canvas)
            .label("Play again")
            .w_h(120.0, 30.0)
            .set(ids.button, ui);

        widget::Text::new("You lose!!")
            .align_middle_x_of(ids.canvas)
            .up_from(ids.button, 40.0)
            .set(ids.text, ui);

        for _click in button {
            return Some(Flow::PlayAgain);
        }

        None
    }
}
<commit_msg>clippy hint<commit_after>use conrod::UiCell;
use conrod::widget;

use conrod_helper::Gui;
use control::Flow;

widget_ids! {
    pub struct Ids {
        canvas,
        button,
        text,
    }
}

pub struct StartMenu();

impl Gui for StartMenu {
    type Ids = self::Ids;

    fn new() -> Self {
        StartMenu()
    }

    fn ids(&self, w: widget::id::Generator) -> Self::Ids {
        Self::Ids::new(w)
    }

    fn gui(&mut self, ui: &mut UiCell, ids: &Self::Ids) -> Option<Flow> {
        use conrod::{Widget, Positionable, Sizeable, Labelable};

        widget::Canvas::new().set(ids.canvas, ui);

        let mut button = widget::Button::new()
            .middle_of(ids.canvas)
            .label("Start game")
            .w_h(120.0, 30.0)
            .set(ids.button, ui);

        if button.next().is_some() {
            Some(Flow::StartGame)
        } else {
            None
        }
    }
}

pub struct PlayAgainMenu();

impl Gui for PlayAgainMenu {
    type Ids = self::Ids;

    fn new() -> Self {
        PlayAgainMenu()
    }

    fn ids(&self, w: widget::id::Generator) -> Self::Ids {
        Self::Ids::new(w)
    }

    fn gui(&mut self, ui: &mut UiCell, ids: &Self::Ids) -> Option<Flow> {
        use conrod::{Widget, Positionable, Sizeable, Labelable};

        widget::Canvas::new().set(ids.canvas, ui);

        let mut button = widget::Button::new()
            .middle_of(ids.canvas)
            .label("Play again")
            .w_h(120.0, 30.0)
            .set(ids.button, ui);

        widget::Text::new("You lose!!")
            .align_middle_x_of(ids.canvas)
            .up_from(ids.button, 40.0)
            .set(ids.text, ui);

        if button.next().is_some() {
            Some(Flow::PlayAgain)
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>use num::{Signed, Unsigned};
use approx::Approx;

#[inline(always)]
pub fn inverse<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = -a[0];
    out[1] = -a[1];
    out
}
#[test]
fn test_inverse() {
    let mut v = [0, 0];
    inverse(&mut v, &[1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn lerp<'a, 'b, T: Unsigned, N: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2], t: N) -> &'a mut [T; 2] {
    let t_f64 = t.to_f64();
    out[0] = T::from_f64((a[0] + (b[0] - a[0])).to_f64() * t_f64);
    out[1] = T::from_f64((a[1] + (b[1] - a[1])).to_f64() * t_f64);
    out
}
#[test]
fn test_lerp() {
    let mut v = [0, 0];
    lerp(&mut v, &[0, 0], &[2, 2], 0.5);
    assert_eq!(v[0], 1);
    assert_eq!(v[1], 1);
}

#[inline(always)]
pub fn perp_l<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = a[1];
    out[1] = -a[0];
    out
}
#[test]
fn test_perp_l() {
    let mut v = [0, 0];
    perp_l(&mut v, &[1, 1]);
    assert!(v[0] == 1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn perp_r<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = -a[1];
    out[1] = a[0];
    out
}
#[test]
fn test_perp_r() {
    let mut v = [0, 0];
    perp_r(&mut v, &[1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == 1);
}

#[inline(always)]
pub fn min<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if b[0] < a[0] {b[0]} else {a[0]};
    out[1] = if b[1] < a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_min() {
    let mut v = [0, 0];
    min(&mut v, &[1, 0], &[0, 1]);
    assert!(v == [0, 0]);
}

#[inline(always)]
pub fn max<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if b[0] > a[0] {b[0]} else {a[0]};
    out[1] = if b[1] > a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_max() {
    let mut v = [0, 0];
    max(&mut v, &[1, 0], &[0, 1]);
    assert!(v == [1, 1]);
}

#[inline(always)]
pub fn clamp<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], min: &'b [T; 2], max: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if a[0] < min[0] {min[0]} else if a[0] > max[0] {max[0]} else {a[0]};
    out[1] = if a[1] < min[1] {min[1]} else if a[1] > max[1] {max[1]} else {a[1]};
    out
}
#[test]
fn test_clamp() {
    let mut v = [0, 0];
    clamp(&mut v, &[2, 2], &[0, 0], &[1, 1]);
    assert!(v == [1, 1]);
}

#[inline(always)]
pub fn eq<'a, T: Unsigned>(a: &'a [T; 2], b: &'a [T; 2]) -> bool {
    !ne(a, b)
}
#[test]
fn test_eq() {
    assert_eq!(eq(&[1f32, 1f32], &[1f32, 1f32]), true);
    assert_eq!(eq(&[0f32, 0f32], &[1f32, 1f32]), false);
}

#[inline(always)]
pub fn ne<'a, T: Unsigned>(a: &'a [T; 2], b: &'a [T; 2]) -> bool {
    !Approx::approx_eq(a[0], b[0]) ||
    !Approx::approx_eq(a[1], b[1])
}
#[test]
fn test_ne() {
    assert_eq!(ne(&[1f32, 1f32], &[1f32, 1f32]), false);
    assert_eq!(ne(&[0f32, 0f32], &[1f32, 1f32]), true);
}
<commit_msg>clean up<commit_after>use num::{Signed, Unsigned};

#[inline(always)]
pub fn inverse<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = -a[0];
    out[1] = -a[1];
    out
}
#[test]
fn test_inverse() {
    let mut v = [0, 0];
    inverse(&mut v, &[1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn lerp<'a, 'b, T: Unsigned, N: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2], t: N) -> &'a mut [T; 2] {
    let t_f64 = t.to_f64();
    out[0] = T::from_f64((a[0] + (b[0] - a[0])).to_f64() * t_f64);
    out[1] = T::from_f64((a[1] + (b[1] - a[1])).to_f64() * t_f64);
    out
}
#[test]
fn test_lerp() {
    let mut v = [0, 0];
    lerp(&mut v, &[0, 0], &[2, 2], 0.5);
    assert_eq!(v[0], 1);
    assert_eq!(v[1], 1);
}

#[inline(always)]
pub fn perp_l<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = a[1];
    out[1] = -a[0];
    out
}
#[test]
fn test_perp_l() {
    let mut v = [0, 0];
    perp_l(&mut v, &[1, 1]);
    assert!(v[0] == 1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn perp_r<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = -a[1];
    out[1] = a[0];
    out
}
#[test]
fn test_perp_r() {
    let mut v = [0, 0];
    perp_r(&mut v, &[1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == 1);
}

#[inline(always)]
pub fn min<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if b[0] < a[0] {b[0]} else {a[0]};
    out[1] = if b[1] < a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_min() {
    let mut v = [0, 0];
    min(&mut v, &[1, 0], &[0, 1]);
    assert!(v == [0, 0]);
}

#[inline(always)]
pub fn max<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if b[0] > a[0] {b[0]} else {a[0]};
    out[1] = if b[1] > a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_max() {
    let mut v = [0, 0];
    max(&mut v, &[1, 0], &[0, 1]);
    assert!(v == [1, 1]);
}

#[inline(always)]
pub fn clamp<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], min: &'b [T; 2], max: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if a[0] < min[0] {min[0]} else if a[0] > max[0] {max[0]} else {a[0]};
    out[1] = if a[1] < min[1] {min[1]} else if a[1] > max[1] {max[1]} else {a[1]};
    out
}
#[test]
fn test_clamp() {
    let mut v = [0, 0];
    clamp(&mut v, &[2, 2], &[0, 0], &[1, 1]);
    assert!(v == [1, 1]);
}

#[inline(always)]
pub fn eq<'a, T: Unsigned>(a: &'a [T; 2], b: &'a [T; 2]) -> bool {
    !ne(a, b)
}
#[test]
fn test_eq() {
    assert_eq!(eq(&[1f32, 1f32], &[1f32, 1f32]), true);
    assert_eq!(eq(&[0f32, 0f32], &[1f32, 1f32]), false);
}

#[inline(always)]
pub fn ne<'a, T: Unsigned>(a: &'a [T; 2], b: &'a [T; 2]) -> bool {
    !a[0].approx_eq(b[0]) ||
    !a[1].approx_eq(b[1])
}
#[test]
fn test_ne() {
    assert_eq!(ne(&[1f32, 1f32], &[1f32, 1f32]), false);
    assert_eq!(ne(&[0f32, 0f32], &[1f32, 1f32]), true);
}
<|endoftext|>


<commit_before>// Copyright 2016 `multipart` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
//! Mocked types for client-side and server-side APIs.
use std::io::{self, Read, Write};
use std::fmt;

use rand::{self, Rng, ThreadRng};

/// A mock implementation of `client::HttpRequest` which can spawn an `HttpBuffer`.
///
/// `client::HttpRequest` impl requires the `client` feature.
#[derive(Default, Debug)]
pub struct ClientRequest {
    boundary: Option<String>,
    content_len: Option<u64>,
}

#[cfg(feature = "client")]
impl ::client::HttpRequest for ClientRequest {
    type Stream = HttpBuffer;
    type Error = io::Error;

    fn apply_headers(&mut self, boundary: &str, content_len: Option<u64>) -> bool {
        self.boundary = Some(boundary.into());
        self.content_len = content_len;
        true
    }

    /// ##Panics
    /// If `apply_headers()` was not called.
    fn open_stream(self) -> Result<HttpBuffer, io::Error> {
        debug!("ClientRequest::open_stream called! {:?}", self);
        let boundary = self.boundary.expect("ClientRequest::set_headers() was not called!");

        Ok(HttpBuffer::new_empty(boundary, self.content_len))
    }
}

/// A writable buffer which stores the boundary and content-length, if provided.
///
/// Implements `client::HttpStream` if the `client` feature is enabled.
pub struct HttpBuffer {
    /// The buffer containing the raw bytes.
    pub buf: Vec<u8>,
    /// The multipart boundary.
    pub boundary: String,
    /// The value of the content-length header, if set.
    pub content_len: Option<u64>,
    rng: ThreadRng,
}

impl HttpBuffer {
    /// Create an empty buffer with the given boundary and optional content-length.
    pub fn new_empty(boundary: String, content_len: Option<u64>) -> HttpBuffer {
        Self::with_buf(Vec::new(), boundary, content_len)
    }

    /// Wrap the given buffer with the given boundary and optional content-length.
    pub fn with_buf(buf: Vec<u8>, boundary: String, content_len: Option<u64>) -> Self {
        HttpBuffer {
            buf: buf,
            boundary: boundary,
            content_len: content_len,
            rng: rand::thread_rng()
        }
    }

    /// Get a `ServerRequest` wrapping the data in this buffer.
    pub fn for_server(&self) -> ServerRequest {
        ServerRequest {
            data: &self.buf,
            boundary: &self.boundary,
            content_len: self.content_len,
            rng: rand::thread_rng(),
        }
    }
}

impl Write for HttpBuffer {
    /// To simulate a network connection, this will copy a random number of bytes
    /// from `buf` to the buffer.
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        if buf.len() == 0 {
            debug!("HttpBuffer::write() was passed a zero-sized buffer.");
            return Ok(0);
        }

        // Simulate the randomness of a network connection by not always reading everything
        let len = self.rng.gen_range(1, buf.len() + 1);

        self.buf.write(&buf[..len])
    }

    fn flush(&mut self) -> io::Result<()> {
        self.buf.flush()
    }
}

#[cfg(feature = "client")]
impl ::client::HttpStream for HttpBuffer {
    type Request = ClientRequest;
    type Response = HttpBuffer;
    type Error = io::Error;

    /// Returns `Ok(self)`.
    fn finish(self) -> Result<Self, io::Error> { Ok(self) }
}

impl fmt::Debug for HttpBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("multipart::mock::HttpBuffer")
            .field("buf", &self.buf)
            .field("boundary", &self.boundary)
            .field("content_len", &self.content_len)
            .finish()
    }
}

/// A mock implementation of `server::HttpRequest` that can be read.
///
/// Implements `server::HttpRequest` if the `server` feature is enabled.
pub struct ServerRequest<'a> {
    /// Slice of the source `HttpBuffer::buf`
    pub data: &'a [u8],
    /// The multipart boundary.
    pub boundary: &'a str,
    /// The value of the content-length header, if set.
    pub content_len: Option<u64>,
    rng: ThreadRng,
}

impl<'a> Read for ServerRequest<'a> {
    /// To simulate a network connection, this will copy a random number of bytes
    /// from the buffer to `out`.
    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
        if out.len() == 0 {
            debug!("ServerRequest::read() was passed a zero-sized buffer.");
            return Ok(0);
        }

        // Simulate the randomness of a network connection by not always reading everything
        let len = self.rng.gen_range(1, out.len() + 1);
        self.data.read(&mut out[..len])
    }
}

#[cfg(feature = "server")]
impl<'a> ::server::HttpRequest for ServerRequest<'a> {
    type Body = Self;

    fn multipart_boundary(&self) -> Option<&str> { Some(&self.boundary) }

    fn body(self) -> Self::Body {
        self
    }
}<commit_msg>Add a way to construct a standalone `mock::ServerRequest`<commit_after>// Copyright 2016 `multipart` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
//! Mocked types for client-side and server-side APIs.
use std::io::{self, Read, Write};
use std::fmt;

use rand::{self, Rng, ThreadRng};

/// A mock implementation of `client::HttpRequest` which can spawn an `HttpBuffer`.
///
/// `client::HttpRequest` impl requires the `client` feature.
#[derive(Default, Debug)]
pub struct ClientRequest {
    boundary: Option<String>,
    content_len: Option<u64>,
}

#[cfg(feature = "client")]
impl ::client::HttpRequest for ClientRequest {
    type Stream = HttpBuffer;
    type Error = io::Error;

    fn apply_headers(&mut self, boundary: &str, content_len: Option<u64>) -> bool {
        self.boundary = Some(boundary.into());
        self.content_len = content_len;
        true
    }

    /// ##Panics
    /// If `apply_headers()` was not called.
    fn open_stream(self) -> Result<HttpBuffer, io::Error> {
        debug!("ClientRequest::open_stream called! {:?}", self);
        let boundary = self.boundary.expect("ClientRequest::set_headers() was not called!");

        Ok(HttpBuffer::new_empty(boundary, self.content_len))
    }
}

/// A writable buffer which stores the boundary and content-length, if provided.
///
/// Implements `client::HttpStream` if the `client` feature is enabled.
pub struct HttpBuffer {
    /// The buffer containing the raw bytes.
    pub buf: Vec<u8>,
    /// The multipart boundary.
    pub boundary: String,
    /// The value of the content-length header, if set.
    pub content_len: Option<u64>,
    rng: ThreadRng,
}

impl HttpBuffer {
    /// Create an empty buffer with the given boundary and optional content-length.
    pub fn new_empty(boundary: String, content_len: Option<u64>) -> HttpBuffer {
        Self::with_buf(Vec::new(), boundary, content_len)
    }

    /// Wrap the given buffer with the given boundary and optional content-length.
    pub fn with_buf(buf: Vec<u8>, boundary: String, content_len: Option<u64>) -> Self {
        HttpBuffer {
            buf: buf,
            boundary: boundary,
            content_len: content_len,
            rng: rand::thread_rng()
        }
    }

    /// Get a `ServerRequest` wrapping the data in this buffer.
    pub fn for_server(&self) -> ServerRequest {
        ServerRequest {
            data: &self.buf,
            boundary: &self.boundary,
            content_len: self.content_len,
            rng: rand::thread_rng(),
        }
    }
}

impl Write for HttpBuffer {
    /// To simulate a network connection, this will copy a random number of bytes
    /// from `buf` to the buffer.
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        if buf.len() == 0 {
            debug!("HttpBuffer::write() was passed a zero-sized buffer.");
            return Ok(0);
        }

        // Simulate the randomness of a network connection by not always reading everything
        let len = self.rng.gen_range(1, buf.len() + 1);

        self.buf.write(&buf[..len])
    }

    fn flush(&mut self) -> io::Result<()> {
        self.buf.flush()
    }
}

#[cfg(feature = "client")]
impl ::client::HttpStream for HttpBuffer {
    type Request = ClientRequest;
    type Response = HttpBuffer;
    type Error = io::Error;

    /// Returns `Ok(self)`.
    fn finish(self) -> Result<Self, io::Error> { Ok(self) }
}

impl fmt::Debug for HttpBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("multipart::mock::HttpBuffer")
            .field("buf", &self.buf)
            .field("boundary", &self.boundary)
            .field("content_len", &self.content_len)
            .finish()
    }
}

/// A mock implementation of `server::HttpRequest` that can be read.
///
/// Implements `server::HttpRequest` if the `server` feature is enabled.
pub struct ServerRequest<'a> {
    /// Slice of the source `HttpBuffer::buf`
    pub data: &'a [u8],
    /// The multipart boundary.
    pub boundary: &'a str,
    /// The value of the content-length header, if set.
    pub content_len: Option<u64>,
    rng: ThreadRng,
}

impl<'a> ServerRequest<'a> {
    /// Create a new `ServerRequest` with the given data and boundary.
    ///
    /// Assumes `content_len: None`
    pub fn new(data: &'a [u8], boundary: &'a str) -> Self {
        ServerRequest {
            data: data,
            boundary: boundary,
            content_len: None,
            rng: rand::thread_rng(),
        }
    }
}

impl<'a> Read for ServerRequest<'a> {
    /// To simulate a network connection, this will copy a random number of bytes
    /// from the buffer to `out`.
    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
        if out.len() == 0 {
            debug!("ServerRequest::read() was passed a zero-sized buffer.");
            return Ok(0);
        }

        // Simulate the randomness of a network connection by not always reading everything
        let len = self.rng.gen_range(1, out.len() + 1);
        self.data.read(&mut out[..len])
    }
}

#[cfg(feature = "server")]
impl<'a> ::server::HttpRequest for ServerRequest<'a> {
    type Body = Self;

    fn multipart_boundary(&self) -> Option<&str> { Some(&self.boundary) }

    fn body(self) -> Self::Body {
        self
    }
}<|endoftext|>


<commit_before>use std::fmt;
use std::fmt::Write;
use std::str::from_utf8;
use std::ascii::AsciiExt;

use byteorder::{BigEndian, ByteOrder};

use {Error};

/// The DNS name as stored in the original packet
///
/// This is contains just a reference to a slice that contains the data.
/// You may turn this into a string using `.to_string()`
#[derive(Debug, Clone, Copy)]
pub struct Name<'a>{
    labels: &'a [u8],
    /// This is the original buffer size. The compressed names in original
    /// are calculated in this buffer
    original: &'a [u8],
}

impl<'a> Name<'a> {
    pub fn scan(data: &'a[u8], original: &'a[u8]) -> Result<Name<'a>, Error> {
        let mut pos = 0;
        loop {
            if data.len() <= pos {
                return Err(Error::UnexpectedEOF);
            }
            let byte = data[pos];
            if byte == 0 {
                return Ok(Name { labels: &data[..pos+1], original: original });
            } else if byte & 0b1100_0000 == 0b1100_0000 {
                if data.len() < pos+2 {
                    return Err(Error::UnexpectedEOF);
                }
                let off = (BigEndian::read_u16(&data[pos..pos+2])
                           & !0b1100_0000_0000_0000) as usize;
                if off >= original.len() {
                    return Err(Error::UnexpectedEOF);
                }
                // Validate referred to location
                try!(Name::scan(&original[off..], original));
                return Ok(Name { labels: &data[..pos+2], original: original });
            } else if byte & 0b1100_0000 == 0 {
                let end = pos + byte as usize + 1;
                if !data[pos+1..end].is_ascii() {
                    return Err(Error::LabelIsNotAscii);
                }
                pos = end;
                if data.len() <= pos {
                    return Err(Error::UnexpectedEOF);
                }
                continue;
            } else {
                return Err(Error::UnknownLabelFormat);
            }
        }
    }
    pub fn byte_len(&self) -> usize {
        self.labels.len()
    }
}

impl<'a> fmt::Display for Name<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let data = self.labels;
        let original = self.original;
        let mut pos = 0;
        loop {
            let byte = data[pos];
            if byte == 0 {
                return Ok(());
            } else if byte & 0b1100_0000 == 0b1100_0000 {
                let off = (BigEndian::read_u16(&data[pos..pos+2])
                           & !0b1100_0000_0000_0000) as usize;
                if pos != 0 {
                    try!(fmt.write_char('.'));
                }
                return fmt::Display::fmt(
                    &Name::scan(&original[off..], original).unwrap(), fmt)
            } else if byte & 0b1100_0000 == 0 {
                if pos != 0 {
                    try!(fmt.write_char('.'));
                }
                let end = pos + byte as usize + 1;
                try!(fmt.write_str(from_utf8(&data[pos+1..end]).unwrap()));
                pos = end;
                continue;
            } else {
                unreachable!();
            }
        }
    }
}
<commit_msg>Add bounds check to Name Scan<commit_after>use std::fmt;
use std::fmt::Write;
use std::str::from_utf8;
use std::ascii::AsciiExt;

use byteorder::{BigEndian, ByteOrder};

use {Error};

/// The DNS name as stored in the original packet
///
/// This is contains just a reference to a slice that contains the data.
/// You may turn this into a string using `.to_string()`
#[derive(Debug, Clone, Copy)]
pub struct Name<'a>{
    labels: &'a [u8],
    /// This is the original buffer size. The compressed names in original
    /// are calculated in this buffer
    original: &'a [u8],
}

impl<'a> Name<'a> {
    pub fn scan(data: &'a[u8], original: &'a[u8]) -> Result<Name<'a>, Error> {
        let mut pos = 0;
        loop {
            if data.len() <= pos {
                return Err(Error::UnexpectedEOF);
            }
            let byte = data[pos];
            if byte == 0 {
                return Ok(Name { labels: &data[..pos+1], original: original });
            } else if byte & 0b1100_0000 == 0b1100_0000 {
                if data.len() < pos+2 {
                    return Err(Error::UnexpectedEOF);
                }
                let off = (BigEndian::read_u16(&data[pos..pos+2])
                           & !0b1100_0000_0000_0000) as usize;
                if off >= original.len() {
                    return Err(Error::UnexpectedEOF);
                }
                // Validate referred to location
                try!(Name::scan(&original[off..], original));
                return Ok(Name { labels: &data[..pos+2], original: original });
            } else if byte & 0b1100_0000 == 0 {
                let end = pos + byte as usize + 1;
                if data.len() < end {
                    return Err(Error::UnexpectedEOF);
                }
                if !data[pos+1..end].is_ascii() {
                    return Err(Error::LabelIsNotAscii);
                }
                pos = end;
                if data.len() <= pos {
                    return Err(Error::UnexpectedEOF);
                }
                continue;
            } else {
                return Err(Error::UnknownLabelFormat);
            }
        }
    }
    pub fn byte_len(&self) -> usize {
        self.labels.len()
    }
}

impl<'a> fmt::Display for Name<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let data = self.labels;
        let original = self.original;
        let mut pos = 0;
        loop {
            let byte = data[pos];
            if byte == 0 {
                return Ok(());
            } else if byte & 0b1100_0000 == 0b1100_0000 {
                let off = (BigEndian::read_u16(&data[pos..pos+2])
                           & !0b1100_0000_0000_0000) as usize;
                if pos != 0 {
                    try!(fmt.write_char('.'));
                }
                return fmt::Display::fmt(
                    &Name::scan(&original[off..], original).unwrap(), fmt)
            } else if byte & 0b1100_0000 == 0 {
                if pos != 0 {
                    try!(fmt.write_char('.'));
                }
                let end = pos + byte as usize + 1;
                try!(fmt.write_str(from_utf8(&data[pos+1..end]).unwrap()));
                pos = end;
                continue;
            } else {
                unreachable!();
            }
        }
    }
}
<|endoftext|>


<commit_before>use traitdefs::{Float, Point, Vector};
use std::convert::{AsRef, AsMut, From};
use std::cell::{Cell, RefCell};
use std::marker::PhantomData;

use super::BezCurve;

#[inline]
fn lerp<F: Float>(a: F, b: F, factor: F) -> F {
    let fact1 = F::from_f32(1.0).unwrap() - factor;
    a * factor + b * fact1
}

/// A struct that contains range information for slicing, used for slicing into the global factor
/// vector. The reason this is used instead of stdlib's `Range` struct is that `Range` does not
/// implement Copy, which means we have to use `RefCell`s instead of `Cell`s for interior mutability.
#[derive(Copy, Clone)]
struct RangeSlice {
    start: usize,
    end: usize
}

impl RangeSlice {
    #[inline]
    fn new(start: usize, end: usize) -> RangeSlice {
        RangeSlice {
            start: start,
            end: end
        }
    }

    fn len(&self) -> usize {
        self.end - self.start
    }
}

fn combination(n: u64, k: u64) -> u64 {
    factorial(n) / (factorial(k) * factorial(n - k))
}

fn factorial(mut n: u64) -> u64 {
    let mut accumulator: u64 = 1;
    while n > 0 {
        accumulator = accumulator.checked_mul(n).expect("Attempted to create Bézier curve with combination that overflow u64; decrease curve order");
        n -= 1;
    }
    accumulator
}

/// Gets the index of the bezier factors inside of FACTORS global.
fn order_index(order: usize) -> usize {
    (order*order+order)/2
}

thread_local!{
    static FACTORS: RefCell<(isize, Vec<u64>)> = RefCell::new((-1, Vec::with_capacity(order_index(20+1))))
}

/// Returns a RangeSlice for FACTORS with the appropriate factors for the given order. Calculates
/// factors if necessary.
fn factors(order: usize) -> RangeSlice {
    FACTORS.with(|f| {
        let max_order = f.borrow().0;
        if order as isize > max_order {
            let mut f = f.borrow_mut();
            f.0 = order as isize;

            // Because max_order defines the maximum current order, we need to increment it in order to avoid
            // re-pushing the current max order. Also, we increment the upper bound, `order`, so that the
            // calculations include `order`.
            for n in (max_order+1) as usize..order+1 {
                for k in 0..n+1 {
                    f.1.push(combination(n as u64, k as u64));
                }
            }
        }

        let order_index = order_index(order);
        RangeSlice::new(order_index, order_index+order+1)
    })
}

/// An n-order bezier polynomial
#[derive(Clone)]
pub struct NBezPoly<F, C = Vec<F>>
        where F: Float,
              C: AsRef<[F]> {
    points: C,
    factors: Cell<RangeSlice>,
    dfactors: Cell<RangeSlice>,
    phantom: PhantomData<F>
}

impl<F, C> From<C> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    fn from(container: C) -> NBezPoly<F, C> {
        NBezPoly::from_container(container)
    }
}

impl<F, C> NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    #[inline]
    pub fn from_container(points: C) -> NBezPoly<F, C> {
        if points.as_ref().len() >= 22 {
            panic!("Cannot create Bézier polynomials with an order >= 21")
        }

        NBezPoly {
            points: points,
            factors: Cell::new(RangeSlice::new(0, 0)),
            dfactors: Cell::new(RangeSlice::new(0, 0)),
            phantom: PhantomData
        }
    }

    #[inline]
    pub fn unwrap(self) -> C {
        self.points
    }

    unsafe fn interp_unchecked<I: Iterator<Item=F>>(t: F, factors: RangeSlice, iter: I) -> F {
        let t1 = F::from_f32(1.0).unwrap() - t;
        let order = factors.len() - 1;
        let mut acc = F::from_f32(0.0).unwrap();
        let mut factor = 0;

        FACTORS.with(|fs| {
            let fs = fs.borrow();
            for point in iter {
                acc = acc + t.powi(factor as i32) *
                            t1.powi((order-factor) as i32) *
                            point *
                            F::from_u64(fs.1[factors.start + factor]).unwrap();
                factor += 1;
            }
        });
        acc
    }

    unsafe fn slope_unchecked<I: Iterator<Item=F>>(t: F, dfactors: RangeSlice, mut iter: I) -> F {
        let t1 = F::from_f32(1.0).unwrap() - t;
        let order = dfactors.len() - 1;
        let mut acc = F::from_f32(0.0).unwrap();
        let mut factor = 0;
        let mut point_next = iter.next().unwrap();

        FACTORS.with(|fs| {
            let fs = fs.borrow();
            for point in iter {
                acc = acc + t.powi(factor as i32) *
                            t1.powi((order-factor) as i32) *
                            (point_next - point) *
                            F::from_u64(fs.1[dfactors.start + factor] * (order + 1) as u64).unwrap();
                point_next = point;
                factor += 1;
            }
        });
        acc
    }
}

impl<F, C> BezCurve<F> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    type Point = F;
    type Vector = F;
    type Elevated = NBezPoly<F>;

    fn from_slice(_: &[F]) -> Option<NBezPoly<F, C>> {
        None
    }

    fn interp_unbounded(&self, t: F) -> F {
        let points = self.points.as_ref();
        if self.factors.get().len() != self.order() + 1 {
            self.factors.set(factors(self.order()))
        }

        unsafe{ NBezPoly::<_, &[_]>::interp_unchecked(t, self.factors.get(), points.iter().map(|f| *f)) }
    }

    fn slope_unbounded(&self, t: F) -> F {
        let points = self.points.as_ref();
        let order = self.order() - 1;
        if self.dfactors.get().len() != order + 1 {
            self.dfactors.set(factors(order))
        }

        unsafe{ NBezPoly::<_, &[_]>::slope_unchecked(t, self.dfactors.get(), points.iter().map(|f| *f)) }
    }

    fn elevate(&self) -> NBezPoly<F> {
        let points = self.points.as_ref();
        let order = self.order() + 1;
        let order_f = F::from_usize(order).unwrap();

        // Elevated points
        let mut el_points = Vec::with_capacity(order + 1);
        el_points.push(points[0]);

        let mut prev_p = points[0];
        for (i, p) in points.iter().map(|p| *p).enumerate().skip(1) {
            el_points.push(lerp(prev_p, p, F::from_usize(i).unwrap()/order_f));

            prev_p = p;
        }

        el_points.push(points[self.order()]);
        NBezPoly::from_container(el_points)
    }

    fn order(&self) -> usize {
        self.points.as_ref().len()-1
    }
}

impl<F, C> AsRef<C> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    fn as_ref(&self) -> &C {
        &self.points
    }
}

impl<F, C> AsMut<C> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    fn as_mut(&mut self) -> &mut C {
        &mut self.points
    }
}

#[derive(Clone)]
pub struct NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    points: C,
    factors: Cell<RangeSlice>,
    dfactors: Cell<RangeSlice>,

    phantom: PhantomData<(F, P, V)>
}

impl<P, V, F, C> From<C> for NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    fn from(container: C) -> NBez<P, V, F, C> {
        NBez::from_container(container)
    }
}

impl<P, V, F, C> NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    /// Create a new `NBez` curve from a container
    pub fn from_container(container: C) -> NBez<P, V, F, C> {
        if container.as_ref().len() >= 22 {
            panic!("Cannot create Bézier curves with an order >= 21")
        }

        NBez {
            points: container,
            factors: Cell::new(RangeSlice::new(0, 0)),
            dfactors: Cell::new(RangeSlice::new(0, 0)),

            phantom: PhantomData,
        }
    }

    /// Get the wrapped container, destroying the `NBez` curve
    pub fn unwrap(self) -> C {
        self.points
    }
}

impl<P, V, F, C> BezCurve<F> for NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P>
{
    type Point = P;
    type Vector = V;
    type Elevated = NBez<P, V, F, Vec<P>>;

    fn from_slice(_: &[P]) -> Option<NBez<P, V, F, C>> {
        None
    }

    fn interp_unbounded(&self, t: F) -> P {
        let points = self.points.as_ref();

        // Initialize a point by cloning one from the point list
        let mut point = points[0].clone();

        // If the factors aren't correct for the current order, recompute factors
        if self.factors.get().len() != self.order() + 1 {
            self.factors.set(factors(self.order()))
        }

        // Iterate over all elements of the point and set them to the interpolated value
        for (i, f) in point.as_mut().iter_mut().enumerate() {
            let iter = points.iter().map(|p| p.as_ref()[i]);
            *f = unsafe{ NBezPoly::<_, &[_]>::interp_unchecked(t, self.factors.get(), iter) };
        }

        point
    }

    fn slope_unbounded(&self, t: F) -> V {
        let points = self.points.as_ref();

        // Initialize a vector by cloning it from the point list and converting it into a vector
        let mut vector: V = points[0].clone().into();
        let order = self.order() - 1;

        if self.dfactors.get().len() != order + 1{
            self.dfactors.set(factors(order))
        }

        // Iterate over all elements of the vector and set them to the interpolated value
        for (i, f) in vector.as_mut().iter_mut().enumerate() {
            let iter = points.iter().map(|p| p.as_ref()[i]);
            *f = unsafe{ NBezPoly::<_, &[_]>::slope_unchecked(t, self.dfactors.get(), iter) };
        }

        vector
    }

    fn elevate(&self) -> NBez<P, V, F, Vec<P>> {
        let points = self.points.as_ref();
        let order = F::from_usize(self.order() + 1).unwrap();

        let mut el_points = Vec::with_capacity(points.len() + 1);
        el_points.push(points[0].clone());

        let mut prev_p = points[0].clone();
        for (i, p) in points.iter().enumerate().skip(1) {
            // Push an arbitrary point onto the vector for modification
            el_points.push(p.clone());

            // Iterate over each dimension of the current (c) and previous (r) point and interpolate
            // between them
            for (d, (c, r)) in p.as_ref().iter().zip(prev_p.as_ref().iter()).map(|(c, r)| (*c, *r)).enumerate() {
                el_points[i].as_mut()[d] = lerp(r, c, F::from_usize(i).unwrap()/order);
            }
            prev_p = p.clone();
        }
        el_points.push(points[points.len()-1].clone());
        NBez::from_container(el_points)
    }

    fn order(&self) -> usize {
        self.points.as_ref().len() - 1
    }
}

impl<P, V, F, C> AsRef<C> for NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    fn as_ref(&self) -> &C {
        &self.points
    }
}

impl<P, V, F, C> AsMut<C> for NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    fn as_mut(&mut self) -> &mut C {
        &mut self.points
    }
}<commit_msg>Fixed bug where NBez slope would be the negation of the actual slope<commit_after>use traitdefs::{Float, Point, Vector};
use std::convert::{AsRef, AsMut, From};
use std::cell::{Cell, RefCell};
use std::marker::PhantomData;

use super::BezCurve;

#[inline]
fn lerp<F: Float>(a: F, b: F, factor: F) -> F {
    let fact1 = F::from_f32(1.0).unwrap() - factor;
    a * factor + b * fact1
}

/// A struct that contains range information for slicing, used for slicing into the global factor
/// vector. The reason this is used instead of stdlib's `Range` struct is that `Range` does not
/// implement Copy, which means we have to use `RefCell`s instead of `Cell`s for interior mutability.
#[derive(Copy, Clone)]
struct RangeSlice {
    start: usize,
    end: usize
}

impl RangeSlice {
    #[inline]
    fn new(start: usize, end: usize) -> RangeSlice {
        RangeSlice {
            start: start,
            end: end
        }
    }

    fn len(&self) -> usize {
        self.end - self.start
    }
}

fn combination(n: u64, k: u64) -> u64 {
    factorial(n) / (factorial(k) * factorial(n - k))
}

fn factorial(mut n: u64) -> u64 {
    let mut accumulator: u64 = 1;
    while n > 0 {
        accumulator = accumulator.checked_mul(n).expect("Attempted to create Bézier curve with combination that overflow u64; decrease curve order");
        n -= 1;
    }
    accumulator
}

/// Gets the index of the bezier factors inside of FACTORS global.
fn order_index(order: usize) -> usize {
    (order*order+order)/2
}

thread_local!{
    static FACTORS: RefCell<(isize, Vec<u64>)> = RefCell::new((-1, Vec::with_capacity(order_index(20+1))))
}

/// Returns a RangeSlice for FACTORS with the appropriate factors for the given order. Calculates
/// factors if necessary.
fn factors(order: usize) -> RangeSlice {
    FACTORS.with(|f| {
        let max_order = f.borrow().0;
        if order as isize > max_order {
            let mut f = f.borrow_mut();
            f.0 = order as isize;

            // Because max_order defines the maximum current order, we need to increment it in order to avoid
            // re-pushing the current max order. Also, we increment the upper bound, `order`, so that the
            // calculations include `order`.
            for n in (max_order+1) as usize..order+1 {
                for k in 0..n+1 {
                    f.1.push(combination(n as u64, k as u64));
                }
            }
        }

        let order_index = order_index(order);
        RangeSlice::new(order_index, order_index+order+1)
    })
}

/// An n-order bezier polynomial
#[derive(Clone)]
pub struct NBezPoly<F, C = Vec<F>>
        where F: Float,
              C: AsRef<[F]> {
    points: C,
    factors: Cell<RangeSlice>,
    dfactors: Cell<RangeSlice>,
    phantom: PhantomData<F>
}

impl<F, C> From<C> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    fn from(container: C) -> NBezPoly<F, C> {
        NBezPoly::from_container(container)
    }
}

impl<F, C> NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    #[inline]
    pub fn from_container(points: C) -> NBezPoly<F, C> {
        if points.as_ref().len() >= 22 {
            panic!("Cannot create Bézier polynomials with an order >= 21")
        }

        NBezPoly {
            points: points,
            factors: Cell::new(RangeSlice::new(0, 0)),
            dfactors: Cell::new(RangeSlice::new(0, 0)),
            phantom: PhantomData
        }
    }

    #[inline]
    pub fn unwrap(self) -> C {
        self.points
    }

    unsafe fn interp_unchecked<I: Iterator<Item=F>>(t: F, factors: RangeSlice, iter: I) -> F {
        let t1 = F::from_f32(1.0).unwrap() - t;
        let order = factors.len() - 1;
        let mut acc = F::from_f32(0.0).unwrap();
        let mut factor = 0;

        FACTORS.with(|fs| {
            let fs = fs.borrow();
            for point in iter {
                acc = acc + t.powi(factor as i32) *
                            t1.powi((order-factor) as i32) *
                            point *
                            F::from_u64(fs.1[factors.start + factor]).unwrap();
                factor += 1;
            }
        });
        acc
    }

    unsafe fn slope_unchecked<I: Iterator<Item=F>>(t: F, dfactors: RangeSlice, mut iter: I) -> F {
        let t1 = F::from_f32(1.0).unwrap() - t;
        let order = dfactors.len() - 1;
        let mut acc = F::from_f32(0.0).unwrap();
        let mut factor = 0;
        let mut point_next = iter.next().unwrap();

        FACTORS.with(|fs| {
            let fs = fs.borrow();
            for point in iter {
                acc = acc + t.powi(factor as i32) *
                            t1.powi((order-factor) as i32) *
                            (point - point_next) *
                            F::from_u64(fs.1[dfactors.start + factor] * (order + 1) as u64).unwrap();
                point_next = point;
                factor += 1;
            }
        });
        acc
    }
}

impl<F, C> BezCurve<F> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    type Point = F;
    type Vector = F;
    type Elevated = NBezPoly<F>;

    fn from_slice(_: &[F]) -> Option<NBezPoly<F, C>> {
        None
    }

    fn interp_unbounded(&self, t: F) -> F {
        let points = self.points.as_ref();
        if self.factors.get().len() != self.order() + 1 {
            self.factors.set(factors(self.order()))
        }

        unsafe{ NBezPoly::<_, &[_]>::interp_unchecked(t, self.factors.get(), points.iter().map(|f| *f)) }
    }

    fn slope_unbounded(&self, t: F) -> F {
        let points = self.points.as_ref();
        let order = self.order() - 1;
        if self.dfactors.get().len() != order + 1 {
            self.dfactors.set(factors(order))
        }

        unsafe{ NBezPoly::<_, &[_]>::slope_unchecked(t, self.dfactors.get(), points.iter().map(|f| *f)) }
    }

    fn elevate(&self) -> NBezPoly<F> {
        let points = self.points.as_ref();
        let order = self.order() + 1;
        let order_f = F::from_usize(order).unwrap();

        // Elevated points
        let mut el_points = Vec::with_capacity(order + 1);
        el_points.push(points[0]);

        let mut prev_p = points[0];
        for (i, p) in points.iter().map(|p| *p).enumerate().skip(1) {
            el_points.push(lerp(prev_p, p, F::from_usize(i).unwrap()/order_f));

            prev_p = p;
        }

        el_points.push(points[self.order()]);
        NBezPoly::from_container(el_points)
    }

    fn order(&self) -> usize {
        self.points.as_ref().len()-1
    }
}

impl<F, C> AsRef<C> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    fn as_ref(&self) -> &C {
        &self.points
    }
}

impl<F, C> AsMut<C> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    fn as_mut(&mut self) -> &mut C {
        &mut self.points
    }
}

#[derive(Clone)]
pub struct NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    points: C,
    factors: Cell<RangeSlice>,
    dfactors: Cell<RangeSlice>,

    phantom: PhantomData<(F, P, V)>
}

impl<P, V, F, C> From<C> for NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    fn from(container: C) -> NBez<P, V, F, C> {
        NBez::from_container(container)
    }
}

impl<P, V, F, C> NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    /// Create a new `NBez` curve from a container
    pub fn from_container(container: C) -> NBez<P, V, F, C> {
        if container.as_ref().len() >= 22 {
            panic!("Cannot create Bézier curves with an order >= 21")
        }

        NBez {
            points: container,
            factors: Cell::new(RangeSlice::new(0, 0)),
            dfactors: Cell::new(RangeSlice::new(0, 0)),

            phantom: PhantomData,
        }
    }

    /// Get the wrapped container, destroying the `NBez` curve
    pub fn unwrap(self) -> C {
        self.points
    }
}

impl<P, V, F, C> BezCurve<F> for NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P>
{
    type Point = P;
    type Vector = V;
    type Elevated = NBez<P, V, F, Vec<P>>;

    fn from_slice(_: &[P]) -> Option<NBez<P, V, F, C>> {
        None
    }

    fn interp_unbounded(&self, t: F) -> P {
        let points = self.points.as_ref();

        // Initialize a point by cloning one from the point list
        let mut point = points[0].clone();

        // If the factors aren't correct for the current order, recompute factors
        if self.factors.get().len() != self.order() + 1 {
            self.factors.set(factors(self.order()))
        }

        // Iterate over all elements of the point and set them to the interpolated value
        for (i, f) in point.as_mut().iter_mut().enumerate() {
            let iter = points.iter().map(|p| p.as_ref()[i]);
            *f = unsafe{ NBezPoly::<_, &[_]>::interp_unchecked(t, self.factors.get(), iter) };
        }

        point
    }

    fn slope_unbounded(&self, t: F) -> V {
        let points = self.points.as_ref();

        // Initialize a vector by cloning it from the point list and converting it into a vector
        let mut vector: V = points[0].clone().into();
        let order = self.order() - 1;

        if self.dfactors.get().len() != order + 1{
            self.dfactors.set(factors(order))
        }

        // Iterate over all elements of the vector and set them to the interpolated value
        for (i, f) in vector.as_mut().iter_mut().enumerate() {
            let iter = points.iter().map(|p| p.as_ref()[i]);
            *f = unsafe{ NBezPoly::<_, &[_]>::slope_unchecked(t, self.dfactors.get(), iter) };
        }

        vector
    }

    fn elevate(&self) -> NBez<P, V, F, Vec<P>> {
        let points = self.points.as_ref();
        let order = F::from_usize(self.order() + 1).unwrap();

        let mut el_points = Vec::with_capacity(points.len() + 1);
        el_points.push(points[0].clone());

        let mut prev_p = points[0].clone();
        for (i, p) in points.iter().enumerate().skip(1) {
            // Push an arbitrary point onto the vector for modification
            el_points.push(p.clone());

            // Iterate over each dimension of the current (c) and previous (r) point and interpolate
            // between them
            for (d, (c, r)) in p.as_ref().iter().zip(prev_p.as_ref().iter()).map(|(c, r)| (*c, *r)).enumerate() {
                el_points[i].as_mut()[d] = lerp(r, c, F::from_usize(i).unwrap()/order);
            }
            prev_p = p.clone();
        }
        el_points.push(points[points.len()-1].clone());
        NBez::from_container(el_points)
    }

    fn order(&self) -> usize {
        self.points.as_ref().len() - 1
    }
}

impl<P, V, F, C> AsRef<C> for NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    fn as_ref(&self) -> &C {
        &self.points
    }
}

impl<P, V, F, C> AsMut<C> for NBez<P, V, F, C>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    fn as_mut(&mut self) -> &mut C {
        &mut self.points
    }
}<|endoftext|>


<commit_before>use std::ops::Add;
use std::num::{Float, FromPrimitive, ToPrimitive, FromStrRadix};
use std::cmp::min;
use std::fmt;
use std::fmt::Writer;
use std::{f64, isize};
use std::cmp::Ordering;

use num::bigint::{BigInt, ToBigInt};
use num::rational::{Ratio, BigRational};
use num::{Signed, Zero, Integer, CheckedAdd};

#[derive(Debug)]
pub enum Real {
    Fixnum(isize),
    Integer(BigInt),
    Rational(BigRational),
    Flonum(f64)
}

impl fmt::Display for Real {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Real::Fixnum(n) => write!(f, "{}", n),
            &Real::Integer(ref n) => write!(f, "{}", n),
            &Real::Rational(ref n) => write!(f, "{}", n),
            &Real::Flonum(n) => write!(f, "{}", n)
        }
    }
}

#[inline]
pub fn fix2int(n: isize) -> BigInt {
    n.to_bigint().unwrap()
}

#[inline]
pub fn int2rat(n: &BigInt) -> BigRational {
    Ratio::from_integer(n.clone())
}

#[inline]
pub fn fix2rat(n: isize) -> BigRational {
    int2rat(&fix2int(n))
}

#[inline]
pub fn fix2flo(n: isize) -> f64 {
    FromPrimitive::from_int(n).unwrap()
}

pub fn int2flo(n: &BigInt) -> f64 {
    if n.is_zero() {
        return 0f64;
    }

    let neg = *n < Zero::zero();
    let repr = {
        let mut digits = Vec::new();
        let mut m = n.abs();
        let base: BigInt = FromPrimitive::from_u64(1 << 32).unwrap();
        while m >= base {
            let (q, r) = m.div_mod_floor(&base);
            digits.push(r.to_uint().unwrap());
            m = q;
        }
        if !m.is_zero() {
            digits.push(m.to_uint().unwrap());
        }
        let mut s = String::new();
        for &d in digits.iter().rev() {
            write!(&mut s, "{}", fmt::radix(d, 2)).unwrap();
        }
        s
    };
    let mantissa_repr = &repr[0 .. min(f64::MANTISSA_DIGITS, repr.len())];
    let u_mantissa:i64 = FromStrRadix::from_str_radix(mantissa_repr,
                                                        2).unwrap();
    let i_mantissa = if neg {
        -u_mantissa
    } else {
        u_mantissa
    };
    let exp = (repr.len() - mantissa_repr.len()) as isize;
    let m:f64 = i_mantissa.to_f64().unwrap();
    return Float::ldexp(m, exp);
}

pub fn rat2flo(r: &BigRational) -> f64 {
    int2flo(r.numer()) / int2flo(r.denom())
}

pub fn reduce(r: Real) -> Real {
    match r {
        Real::Fixnum(_) =>
            r,
        Real::Integer(n) => {
            let max_fixnum: BigInt = FromPrimitive::from_int(isize::MAX).unwrap();
            let min_fixnum: BigInt = FromPrimitive::from_int(isize::MIN).unwrap();

            if min_fixnum <= n && n <= max_fixnum {
                Real::Fixnum(n.to_int().unwrap())
            } else {
                Real::Integer(n)
            }
        },
        Real::Rational(n) =>
            if n.is_integer() {
                reduce(Real::Integer(n.to_integer()))
            } else {
                Real::Rational(n)
            },
        Real::Flonum(_) =>
            r
    }
}

fn coerce_arith<Fix, Big, Rat, Flo>(lhs: &Real, rhs: &Real,
                                    fix_op: Fix, big_op: Big,
                                    rat_op: Rat, flo_op: Flo)
        -> Real
    where Fix: Fn(isize, isize) -> Option<isize>,
          Big: Fn(&BigInt, &BigInt) -> BigInt,
          Rat: Fn(&BigRational, &BigRational) -> BigRational,
          Flo: Fn(f64, f64) -> f64
{
    coerce(lhs, rhs,
           |x, y| match fix_op(x, y) {
               Some(n) => Real::Fixnum(n),
               None => reduce(Real::Integer(big_op(&fix2int(x), &fix2int(y))))
           },
           |x, y| reduce(Real::Integer(big_op(x, y))),
           |x, y| reduce(Real::Rational(rat_op(x, y))),
           |x, y| Real::Flonum(flo_op(x, y))
    )
}

fn coerce<Fix, Big, Rat, Flo, T>(lhs: &Real, rhs: &Real,
                                 fix_op: Fix, big_op: Big,
                                 rat_op: Rat, flo_op: Flo)
        -> T
    where Fix: Fn(isize, isize) -> T,
          Big: Fn(&BigInt, &BigInt) -> T,
          Rat: Fn(&BigRational, &BigRational) -> T,
          Flo: Fn(f64, f64) -> T
{
    match (lhs, rhs) {
        (&Real::Fixnum(l), &Real::Fixnum(r)) =>
            fix_op(l, r),
        (&Real::Fixnum(l), &Real::Integer(ref r)) =>
            big_op(&fix2int(l), r),
        (&Real::Fixnum(l), &Real::Rational(ref r)) =>
            rat_op(&fix2rat(l), r),
        (&Real::Fixnum(l), &Real::Flonum(r)) =>
            flo_op(fix2flo(l), r),
        (&Real::Integer(ref l), &Real::Fixnum(r)) =>
            big_op(l, &fix2int(r)),
        (&Real::Integer(ref l), &Real::Integer(ref r)) =>
            big_op(l, r),
        (&Real::Integer(ref l), &Real::Rational(ref r)) =>
            rat_op(&int2rat(l), r),
        (&Real::Integer(ref l), &Real::Flonum(r)) =>
            flo_op(int2flo(l), r),
        (&Real::Rational(ref l), &Real::Fixnum(r)) =>
            rat_op(l, &fix2rat(r)),
        (&Real::Rational(ref l), &Real::Integer(ref r)) =>
            rat_op(l, &int2rat(r)),
        (&Real::Rational(ref l), &Real::Rational(ref r)) =>
            rat_op(l, r),
        (&Real::Rational(ref l), &Real::Flonum(r)) =>
            flo_op(rat2flo(l), r),
        (&Real::Flonum(l), &Real::Fixnum(r)) =>
            flo_op(l, fix2flo(r)),
        (&Real::Flonum(l), &Real::Integer(ref r)) =>
            flo_op(l, int2flo(r)),
        (&Real::Flonum(l), &Real::Rational(ref r)) =>
            flo_op(l, rat2flo(r)),
        (&Real::Flonum(l), &Real::Flonum(r)) =>
            flo_op(l, r)
    }
}

impl Add<Real> for Real {
    type Output = Real;

    fn add(self, other: Real) -> Real {
        coerce_arith(&self, &other,
                     |x, y| x.checked_add(&y),
                     |x, y| x + y,
                     |x, y| x + y,
                     |x, y| x + y)
    }
}

impl<'a, 'b> Add<&'a Real> for &'b Real {
    type Output = Real;

    fn add(self, other: &Real) -> Real {
        coerce_arith(self, other,
                     |x, y| x.checked_add(&y),
                     |x, y| x + y,
                     |x, y| x + y,
                     |x, y| x + y)
    }
}

impl PartialEq for Real {
    fn eq(&self, other: &Real) -> bool {
        coerce(self, other,
               |x, y| x == y,
               |x, y| x == y,
               |x, y| x == y,
               |x, y| x == y
        )
    }
}

impl PartialOrd for Real {
    fn partial_cmp(&self, other: &Real) -> Option<Ordering> {
        coerce(self, other,
                    |x, y| x.partial_cmp(&y),
                    |x, y| x.partial_cmp(y),
                    |x, y| x.partial_cmp(y),
                    |x, y| x.partial_cmp(&y)
        )
    }
}

#[cfg(test)]
mod test {
    use super::{Real, int2flo};
    use std::num::FromPrimitive;

    #[test]
    fn test_add() {
        assert_eq!(Real::Fixnum(3), Real::Fixnum(1) + Real::Fixnum(2));
    }

    #[test]
    fn test_reduce() {
        let x = Real::Integer(FromPrimitive::from_int(1).unwrap());
        let y = Real::Integer(FromPrimitive::from_int(2).unwrap());
        assert_eq!(Real::Fixnum(3), x+y);
    }

    #[test]
    fn test_int2flo() {
        let n = FromPrimitive::from_int(3).unwrap();
        assert_eq!(3.0, int2flo(&n));
    }
}
<commit_msg>Macro-ify impl Add for Real<commit_after>use std::ops::Add;
use std::num::{Float, FromPrimitive, ToPrimitive, FromStrRadix};
use std::cmp::min;
use std::fmt;
use std::fmt::Writer;
use std::{f64, isize};
use std::cmp::Ordering;

use num::bigint::{BigInt, ToBigInt};
use num::rational::{Ratio, BigRational};
use num::{Signed, Zero, Integer, CheckedAdd};

#[derive(Debug)]
pub enum Real {
    Fixnum(isize),
    Integer(BigInt),
    Rational(BigRational),
    Flonum(f64)
}

impl fmt::Display for Real {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Real::Fixnum(n) => write!(f, "{}", n),
            &Real::Integer(ref n) => write!(f, "{}", n),
            &Real::Rational(ref n) => write!(f, "{}", n),
            &Real::Flonum(n) => write!(f, "{}", n)
        }
    }
}

#[inline]
pub fn fix2int(n: isize) -> BigInt {
    n.to_bigint().unwrap()
}

#[inline]
pub fn int2rat(n: &BigInt) -> BigRational {
    Ratio::from_integer(n.clone())
}

#[inline]
pub fn fix2rat(n: isize) -> BigRational {
    int2rat(&fix2int(n))
}

#[inline]
pub fn fix2flo(n: isize) -> f64 {
    FromPrimitive::from_int(n).unwrap()
}

pub fn int2flo(n: &BigInt) -> f64 {
    if n.is_zero() {
        return 0f64;
    }

    let neg = *n < Zero::zero();
    let repr = {
        let mut digits = Vec::new();
        let mut m = n.abs();
        let base: BigInt = FromPrimitive::from_u64(1 << 32).unwrap();
        while m >= base {
            let (q, r) = m.div_mod_floor(&base);
            digits.push(r.to_uint().unwrap());
            m = q;
        }
        if !m.is_zero() {
            digits.push(m.to_uint().unwrap());
        }
        let mut s = String::new();
        for &d in digits.iter().rev() {
            write!(&mut s, "{}", fmt::radix(d, 2)).unwrap();
        }
        s
    };
    let mantissa_repr = &repr[0 .. min(f64::MANTISSA_DIGITS, repr.len())];
    let u_mantissa:i64 = FromStrRadix::from_str_radix(mantissa_repr,
                                                        2).unwrap();
    let i_mantissa = if neg {
        -u_mantissa
    } else {
        u_mantissa
    };
    let exp = (repr.len() - mantissa_repr.len()) as isize;
    let m:f64 = i_mantissa.to_f64().unwrap();
    return Float::ldexp(m, exp);
}

pub fn rat2flo(r: &BigRational) -> f64 {
    int2flo(r.numer()) / int2flo(r.denom())
}

pub fn reduce(r: Real) -> Real {
    match r {
        Real::Fixnum(_) =>
            r,
        Real::Integer(n) => {
            let max_fixnum: BigInt = FromPrimitive::from_int(isize::MAX).unwrap();
            let min_fixnum: BigInt = FromPrimitive::from_int(isize::MIN).unwrap();

            if min_fixnum <= n && n <= max_fixnum {
                Real::Fixnum(n.to_int().unwrap())
            } else {
                Real::Integer(n)
            }
        },
        Real::Rational(n) =>
            if n.is_integer() {
                reduce(Real::Integer(n.to_integer()))
            } else {
                Real::Rational(n)
            },
        Real::Flonum(_) =>
            r
    }
}

fn coerce_arith<Fix, Big, Rat, Flo>(lhs: &Real, rhs: &Real,
                                    fix_op: Fix, big_op: Big,
                                    rat_op: Rat, flo_op: Flo)
        -> Real
    where Fix: Fn(isize, isize) -> Option<isize>,
          Big: Fn(&BigInt, &BigInt) -> BigInt,
          Rat: Fn(&BigRational, &BigRational) -> BigRational,
          Flo: Fn(f64, f64) -> f64
{
    coerce(lhs, rhs,
           |x, y| match fix_op(x, y) {
               Some(n) => Real::Fixnum(n),
               None => reduce(Real::Integer(big_op(&fix2int(x), &fix2int(y))))
           },
           |x, y| reduce(Real::Integer(big_op(x, y))),
           |x, y| reduce(Real::Rational(rat_op(x, y))),
           |x, y| Real::Flonum(flo_op(x, y))
    )
}

fn coerce<Fix, Big, Rat, Flo, T>(lhs: &Real, rhs: &Real,
                                 fix_op: Fix, big_op: Big,
                                 rat_op: Rat, flo_op: Flo)
        -> T
    where Fix: Fn(isize, isize) -> T,
          Big: Fn(&BigInt, &BigInt) -> T,
          Rat: Fn(&BigRational, &BigRational) -> T,
          Flo: Fn(f64, f64) -> T
{
    match (lhs, rhs) {
        (&Real::Fixnum(l), &Real::Fixnum(r)) =>
            fix_op(l, r),
        (&Real::Fixnum(l), &Real::Integer(ref r)) =>
            big_op(&fix2int(l), r),
        (&Real::Fixnum(l), &Real::Rational(ref r)) =>
            rat_op(&fix2rat(l), r),
        (&Real::Fixnum(l), &Real::Flonum(r)) =>
            flo_op(fix2flo(l), r),
        (&Real::Integer(ref l), &Real::Fixnum(r)) =>
            big_op(l, &fix2int(r)),
        (&Real::Integer(ref l), &Real::Integer(ref r)) =>
            big_op(l, r),
        (&Real::Integer(ref l), &Real::Rational(ref r)) =>
            rat_op(&int2rat(l), r),
        (&Real::Integer(ref l), &Real::Flonum(r)) =>
            flo_op(int2flo(l), r),
        (&Real::Rational(ref l), &Real::Fixnum(r)) =>
            rat_op(l, &fix2rat(r)),
        (&Real::Rational(ref l), &Real::Integer(ref r)) =>
            rat_op(l, &int2rat(r)),
        (&Real::Rational(ref l), &Real::Rational(ref r)) =>
            rat_op(l, r),
        (&Real::Rational(ref l), &Real::Flonum(r)) =>
            flo_op(rat2flo(l), r),
        (&Real::Flonum(l), &Real::Fixnum(r)) =>
            flo_op(l, fix2flo(r)),
        (&Real::Flonum(l), &Real::Integer(ref r)) =>
            flo_op(l, int2flo(r)),
        (&Real::Flonum(l), &Real::Rational(ref r)) =>
            flo_op(l, rat2flo(r)),
        (&Real::Flonum(l), &Real::Flonum(r)) =>
            flo_op(l, r)
    }
}

macro_rules! impl_arith {
    ($tr:ident, $op:ident, $checked_op:ident) => {
        impl $tr<Real> for Real {
            type Output = Real;

            fn $op(self, other: Real) -> Real {
                coerce_arith(&self, &other,
                             |x, y| x.$checked_op(&y),
                             |x, y| x.$op(y),
                             |x, y| x.$op(y),
                             |x, y| x.$op(&y)
                )
            }
        }

        impl<'a, 'b> $tr<&'a Real> for &'b Real {
            type Output = Real;

            fn $op(self, other: &Real) -> Real {
                coerce_arith(self, other,
                             |x, y| x.$checked_op(&y),
                             |x, y| x.$op(y),
                             |x, y| x.$op(y),
                             |x, y| x.$op(&y)
                )
            }
        }
    }
}

impl_arith!(Add, add, checked_add);

impl PartialEq for Real {
    fn eq(&self, other: &Real) -> bool {
        coerce(self, other,
               |x, y| x == y,
               |x, y| x == y,
               |x, y| x == y,
               |x, y| x == y
        )
    }
}

impl PartialOrd for Real {
    fn partial_cmp(&self, other: &Real) -> Option<Ordering> {
        coerce(self, other,
                    |x, y| x.partial_cmp(&y),
                    |x, y| x.partial_cmp(y),
                    |x, y| x.partial_cmp(y),
                    |x, y| x.partial_cmp(&y)
        )
    }
}

#[cfg(test)]
mod test {
    use super::{Real, int2flo};
    use std::num::FromPrimitive;

    #[test]
    fn test_add() {
        assert_eq!(Real::Fixnum(3), Real::Fixnum(1) + Real::Fixnum(2));
    }

    #[test]
    fn test_reduce() {
        let x = Real::Integer(FromPrimitive::from_int(1).unwrap());
        let y = Real::Integer(FromPrimitive::from_int(2).unwrap());
        assert_eq!(Real::Fixnum(3), x+y);
    }

    #[test]
    fn test_int2flo() {
        let n = FromPrimitive::from_int(3).unwrap();
        assert_eq!(3.0, int2flo(&n));
    }
}
<|endoftext|>