<commit_before>//! The Lea compiler command line frontend

#![feature(core, old_io, io, fs, old_path)]

extern crate lea;

use std::env;
use std::fmt;
use std::default::Default;
use std::old_io::stdio;
use std::io::Read;
use std::fs::File;

use lea::compiler::*;
use lea::program::Program;

macro_rules! printerr {
    ($($arg:tt)*) => {
        print_err_fmt(format_args!($($arg)*));
    }
}

#[inline]
#[allow(unused_must_use)]
fn print_err_fmt(fmt: fmt::Arguments) {
    writeln!(&mut stdio::stderr_raw(), "{}", fmt);
}

fn print_usage() {
    println!("Usage: leac [file]");
    println!("");
    println!("Parses and checks the given file. If an error occurs, outputs it.");
    println!("When the compiler is done, this will actually compile the source code.");
}

fn compile(code: &str, filename: &str) {
    let mut p = Program::new();
    match compile_str(&mut p, code, filename, &CompileConfig::default()) {
        Err(e) => match e {
            ErrParse(err) => {
                printerr!("parse error: {}", err.format(code.as_slice(), filename));
                return;
            },
            ErrCheck(errs) => {
                let mut errstr = String::new();
                let mut i = 1;
                for err in &errs {
                    errstr.push_str("error: ");
                    errstr.push_str(err.format(code.as_slice(), filename).as_slice());
                    if i < errs.len() - 1 { errstr.push_str("\n"); }
                    i += 1;
                }
                printerr!("{}", errstr);
                return;
            },
            ErrLint(warns) => {
                let mut first = true;
                for w in warns {
                    if first { first = false; } else { printerr!("\n"); }
                    printerr!("warning as error: {}", w.format(code.as_slice(), filename).as_slice());
                }
                return;
            },
        },
        Ok(output) => {
            let warns = output.get_warns();
            if warns.len() > 0 {
                println!("{} warnings:", warns.len());
                for w in warns {
                    println!("{}", w.format(code, filename));
                }
            }
        }
    }
}

fn compile_file(filename: &str) {
    match File::open(&Path::new(filename.clone())) {
        Ok(mut file) => {
            let mut code = String::new();
            match file.read_to_string(&mut code) {
                Ok(()) => {
                    compile(code.as_slice(), filename.as_slice());
                },
                Err(err) => {
                    printerr!("error reading file \"{}\": {}", filename, err);
                }
            }
        },
        Err(err) => {
            printerr!("error opening file \"{}\": {}", filename, err);
        }
    };
}

pub fn main() {
    let mut iter = env::args();
    let mut inputarg: Option<String> = None;
    let mut lastarg: Option<String> = None;

    iter.next();    // Consume first argument (exec name)
    for arg in iter {
        if let Some(..) = inputarg {
            printerr!("Invalid argument: {}", lastarg.unwrap());
            print_usage();
            return;
        }

        match arg.as_slice() {
            "--help" | "-h" => {
                print_usage();
                return;
            },
            _ => {
                // Unknown arg, must be input file
                inputarg = Some(arg.clone());
            },
        }

        lastarg = Some(arg);
    }

    if let None = inputarg {
        inputarg = Some("-".to_string());   // read stdin by default
    }

    let f = inputarg.unwrap();
    if f.as_slice() == "-" {
        let code = stdio::stdin_raw().read_to_string().unwrap();
        println!("");   // print newline to seperate leac output from source input
        compile(code.as_slice(), "<stdin>");
    } else {
        compile_file(f.as_slice());
    }
}
<commit_msg>Don't default to stdin in leac<commit_after>//! The Lea compiler command line frontend

#![feature(core, old_io, io, fs, old_path)]

extern crate lea;

use std::env;
use std::fmt;
use std::default::Default;
use std::old_io::stdio;
use std::io::Read;
use std::fs::File;

use lea::compiler::*;
use lea::program::Program;

macro_rules! printerr {
    ($($arg:tt)*) => {
        print_err_fmt(format_args!($($arg)*));
    }
}

#[inline]
#[allow(unused_must_use)]
fn print_err_fmt(fmt: fmt::Arguments) {
    writeln!(&mut stdio::stderr_raw(), "{}", fmt);
}

fn print_usage() {
    println!("Usage: leac [file]");
    println!("");
    println!("Parses and checks the given file. If file is \"-\", reads stdin.");
    println!("When the compiler is done, this will actually compile the source code.");
}

fn compile(code: &str, filename: &str) {
    let mut p = Program::new();
    match compile_str(&mut p, code, filename, &CompileConfig::default()) {
        Err(e) => match e {
            ErrParse(err) => {
                printerr!("parse error: {}", err.format(code.as_slice(), filename));
                return;
            },
            ErrCheck(errs) => {
                let mut errstr = String::new();
                let mut i = 1;
                for err in &errs {
                    errstr.push_str("error: ");
                    errstr.push_str(err.format(code.as_slice(), filename).as_slice());
                    if i < errs.len() - 1 { errstr.push_str("\n"); }
                    i += 1;
                }
                printerr!("{}", errstr);
                return;
            },
            ErrLint(warns) => {
                let mut first = true;
                for w in warns {
                    if first { first = false; } else { printerr!("\n"); }
                    printerr!("warning as error: {}", w.format(code.as_slice(), filename).as_slice());
                }
                return;
            },
        },
        Ok(output) => {
            let warns = output.get_warns();
            if warns.len() > 0 {
                println!("{} warnings:", warns.len());
                for w in warns {
                    println!("{}", w.format(code, filename));
                }
            }
        }
    }
}

fn compile_file(filename: &str) {
    match File::open(&Path::new(filename.clone())) {
        Ok(mut file) => {
            let mut code = String::new();
            match file.read_to_string(&mut code) {
                Ok(()) => {
                    compile(code.as_slice(), filename.as_slice());
                },
                Err(err) => {
                    printerr!("error reading file \"{}\": {}", filename, err);
                }
            }
        },
        Err(err) => {
            printerr!("error opening file \"{}\": {}", filename, err);
        }
    };
}

pub fn main() {
    let mut iter = env::args();
    let mut inputarg: Option<String> = None;
    let mut lastarg: Option<String> = None;

    iter.next();    // Consume first argument (exec name)
    for arg in iter {
        if let Some(..) = inputarg {
            printerr!("Invalid argument: {}", lastarg.unwrap());
            print_usage();
            return;
        }

        match arg.as_slice() {
            "--help" | "-h" => {
                print_usage();
                return;
            },
            _ => {
                // Unknown arg, must be input file
                inputarg = Some(arg.clone());
            },
        }

        lastarg = Some(arg);
    }

    if let None = inputarg {
        printerr!("error: no input file");
        print_usage();
        return;
    }

    let f = inputarg.unwrap();
    if f.as_slice() == "-" {
        let code = stdio::stdin_raw().read_to_string().unwrap();
        println!("");   // print newline to seperate leac output from source input
        compile(code.as_slice(), "<stdin>");
    } else {
        compile_file(f.as_slice());
    }
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![feature(io)]
#![feature(env)]
#![feature(path)]

extern crate document;

use std::env;
use std::cmp::min;
use std::old_io::{File,BufferedWriter,stdio};

use document::parser::Parser;

fn pretty_error(xml: &str, position: usize) -> &str {
    let s = &xml[position..];
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn process_input<R>(input: R)
    where R: Reader
{
    let mut input = input;
    let data = match input.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    let p = Parser::new();

    let package = match p.parse(&data) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(&data, point)),
    };

    let mut out = BufferedWriter::new(stdio::stdout_raw());

    {
        let d = package.as_document();
        document::writer::format_document(&d, &mut out).ok().expect("I can't output");
    }
}

#[allow(dead_code)]
fn main() {
    let mut args: Vec<_> = env::args().collect();

    let filename = args.remove(1);

    if filename == "-" {
        process_input(stdio::stdin_raw());
    } else {
        process_input(File::open(&Path::new(filename)))
    }
}
<commit_msg>Only allow dead executable code when compiling tests<commit_after>#![cfg_attr(test, allow(dead_code))]

#![feature(collections)]
#![feature(io)]
#![feature(env)]
#![feature(path)]

extern crate document;

use std::env;
use std::cmp::min;
use std::old_io::{File,BufferedWriter,stdio};

use document::parser::Parser;

fn pretty_error(xml: &str, position: usize) -> &str {
    let s = &xml[position..];
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn process_input<R>(input: R)
    where R: Reader
{
    let mut input = input;
    let data = match input.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    let p = Parser::new();

    let package = match p.parse(&data) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(&data, point)),
    };

    let mut out = BufferedWriter::new(stdio::stdout_raw());

    {
        let d = package.as_document();
        document::writer::format_document(&d, &mut out).ok().expect("I can't output");
    }
}

fn main() {
    let mut args: Vec<_> = env::args().collect();

    let filename = args.remove(1);

    if filename == "-" {
        process_input(stdio::stdin_raw());
    } else {
        process_input(File::open(&Path::new(filename)))
    }
}
<|endoftext|>


<commit_before>//! [Problem 59](https://projecteuler.net/problem=59) solver.

#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

#![feature(iter_arith, range_inclusive)]

#[macro_use(problem)]
extern crate common;

use std::f64;
use std::fs::File;
use std::io::{self, BufReader};
use std::io::prelude::*;
use std::iter;

const ENGLISH_FREQUENCY: &'static [(char, f64)] = &[('a', 0.08167),
                                                    ('b', 0.01492),
                                                    ('c', 0.02782),
                                                    ('d', 0.04253),
                                                    ('e', 0.12702),
                                                    ('f', 0.02228),
                                                    ('g', 0.02015),
                                                    ('h', 0.06094),
                                                    ('i', 0.06966),
                                                    ('j', 0.00153),
                                                    ('k', 0.00772),
                                                    ('l', 0.04025),
                                                    ('m', 0.02406),
                                                    ('n', 0.06749),
                                                    ('o', 0.07507),
                                                    ('p', 0.01929),
                                                    ('q', 0.00095),
                                                    ('r', 0.05987),
                                                    ('s', 0.06327),
                                                    ('t', 0.09056),
                                                    ('u', 0.02758),
                                                    ('v', 0.00978),
                                                    ('w', 0.02360),
                                                    ('x', 0.00150),
                                                    ('y', 0.01974),
                                                    ('z', 0.00074)];

fn trans_map<T: Clone>(key: u8, src: &[T], dst: &mut [T]) {
    for (i, f) in src.iter().enumerate() {
        dst[((i as u8) ^ key) as usize] = f.clone();
    }
}

fn get_dist(a: &[f64], b: &[f64]) -> f64 {
    let mut sum = 0.0;
    for (&na, &nb) in a.iter().zip(b.iter()) {
        sum += (na - nb) * (na - nb);
    }
    sum
}

fn find_key(count: &[usize], ref_freq: &[f64]) -> u8 {
    let total = count.iter().sum::<usize>();

    let mut freq = &mut [0.0f64; 256];
    for (f, &n) in freq.iter_mut().zip(count.iter()) {
        *f = (n as f64) / (total as f64);
    }

    let mut freq_buf = &mut [0.0; 256];
    let mut min_key = 0;
    let mut min_dist = f64::INFINITY;
    for k in iter::range_inclusive(0, 255) {
        trans_map(k, freq, freq_buf);
        let dist = get_dist(freq_buf, ref_freq);
        if dist < min_dist {
            min_dist = dist;
            min_key = k;
        }
    }
    min_key
}

fn read_file(file: File) -> io::Result<Vec<u8>> {
    let mut code_list = vec![];

    for word in BufReader::new(file).split(b',') {
        let word_str = String::from_utf8(try!(word)).ok().unwrap();
        let word = word_str.trim();
        if word.is_empty() {
            break;
        }
        code_list.push(word.parse::<u8>().unwrap())
    }

    Ok(code_list)
}

fn solve(file: File) -> io::Result<String> {
    const KEY_LEN: usize = 3;
    let code_list = try!(read_file(file));

    let freq_dict = &mut [0.0; 256];
    for &(c, f) in ENGLISH_FREQUENCY {
        freq_dict[(c as u8) as usize] = f;
    }

    let mut freq = [[0; 256]; KEY_LEN];
    for (i, &n) in code_list.iter().enumerate() {
        freq[i % KEY_LEN][n as usize] += 1;
    }

    let key = freq.iter()
                  .map(|f| find_key(f, freq_dict))
                  .collect::<Vec<u8>>();

    let sum = code_list.iter()
                       .zip(key.iter().cycle())
                       .map(|(&n, &key)| (n ^ key) as u32)
                       .sum::<u32>();

    Ok(sum.to_string())
}

problem!("107359", "p059_cipher.txt", solve);
<commit_msg>update to rustc 1.9.0-nightly (998a6720b 2016-03-07)<commit_after>//! [Problem 59](https://projecteuler.net/problem=59) solver.

#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

#![feature(iter_arith, inclusive_range_syntax)]

#[macro_use(problem)]
extern crate common;

use std::f64;
use std::fs::File;
use std::io::{self, BufReader};
use std::io::prelude::*;

const ENGLISH_FREQUENCY: &'static [(char, f64)] = &[('a', 0.08167),
                                                    ('b', 0.01492),
                                                    ('c', 0.02782),
                                                    ('d', 0.04253),
                                                    ('e', 0.12702),
                                                    ('f', 0.02228),
                                                    ('g', 0.02015),
                                                    ('h', 0.06094),
                                                    ('i', 0.06966),
                                                    ('j', 0.00153),
                                                    ('k', 0.00772),
                                                    ('l', 0.04025),
                                                    ('m', 0.02406),
                                                    ('n', 0.06749),
                                                    ('o', 0.07507),
                                                    ('p', 0.01929),
                                                    ('q', 0.00095),
                                                    ('r', 0.05987),
                                                    ('s', 0.06327),
                                                    ('t', 0.09056),
                                                    ('u', 0.02758),
                                                    ('v', 0.00978),
                                                    ('w', 0.02360),
                                                    ('x', 0.00150),
                                                    ('y', 0.01974),
                                                    ('z', 0.00074)];

fn trans_map<T: Clone>(key: u8, src: &[T], dst: &mut [T]) {
    for (i, f) in src.iter().enumerate() {
        dst[((i as u8) ^ key) as usize] = f.clone();
    }
}

fn get_dist(a: &[f64], b: &[f64]) -> f64 {
    let mut sum = 0.0;
    for (&na, &nb) in a.iter().zip(b.iter()) {
        sum += (na - nb) * (na - nb);
    }
    sum
}

fn find_key(count: &[usize], ref_freq: &[f64]) -> u8 {
    let total = count.iter().sum::<usize>();

    let mut freq = &mut [0.0f64; 256];
    for (f, &n) in freq.iter_mut().zip(count.iter()) {
        *f = (n as f64) / (total as f64);
    }

    let mut freq_buf = &mut [0.0; 256];
    let mut min_key = 0;
    let mut min_dist = f64::INFINITY;
    for k in 0...255 {
        trans_map(k, freq, freq_buf);
        let dist = get_dist(freq_buf, ref_freq);
        if dist < min_dist {
            min_dist = dist;
            min_key = k;
        }
    }
    min_key
}

fn read_file(file: File) -> io::Result<Vec<u8>> {
    let mut code_list = vec![];

    for word in BufReader::new(file).split(b',') {
        let word_str = String::from_utf8(try!(word)).ok().unwrap();
        let word = word_str.trim();
        if word.is_empty() {
            break;
        }
        code_list.push(word.parse::<u8>().unwrap())
    }

    Ok(code_list)
}

fn solve(file: File) -> io::Result<String> {
    const KEY_LEN: usize = 3;
    let code_list = try!(read_file(file));

    let freq_dict = &mut [0.0; 256];
    for &(c, f) in ENGLISH_FREQUENCY {
        freq_dict[(c as u8) as usize] = f;
    }

    let mut freq = [[0; 256]; KEY_LEN];
    for (i, &n) in code_list.iter().enumerate() {
        freq[i % KEY_LEN][n as usize] += 1;
    }

    let key = freq.iter()
                  .map(|f| find_key(f, freq_dict))
                  .collect::<Vec<u8>>();

    let sum = code_list.iter()
                       .zip(key.iter().cycle())
                       .map(|(&n, &key)| (n ^ key) as u32)
                       .sum::<u32>();

    Ok(sum.to_string())
}

problem!("107359", "p059_cipher.txt", solve);
<|endoftext|>


<commit_before>use super::*;

pub fn new() -> System {
    System {
        name: "SI", module: "si",
        doc_prelude: "The International System of Units (SI)

Where experimental values are used for constants, the values are obtained from the 2014 values from
[The NIST Reference on Constants, Unit, and Uncertainty](http://physics.nist.gov/cuu/Constants/).

",
        base: base_units!(
            M: Meter, m, Length;
            KG: Kilogram, kg, Mass;
            S: Second, s, Time;
            A: Ampere, A, Current;
            K: Kelvin, K, Temperature;
            CD: Candela, cd, LuminousIntensity;
            MOL: Mole, mol, AmountOfSubstance;
        ),
        derived: derived_units!(
            HZ: Hertz = Unitless / Second, Frequency;
            N: Newton = Kilogram * Meter / Second2, Force;
            PA: Pascal = Newton / Meter2, Pressure;
            J: Joule = Newton * Meter, Energy;
            W: Watt = Joule / Second, Power;
            C: Coulomb = Second * Ampere, Charge;
            V: Volt = Watt / Ampere, ElectricPotential;
            F: Farad = Coulomb / Volt, Capacitance;
            OHM: Ohm = Volt / Ampere, Resistance;
            SIE: Siemens = Ampere / Volt, Conductance;
            WB: Weber = Joule / Ampere, MagneticFlux;
            T: Tesla = Weber / Meter2;
            H: Henry = Ohm * Second, Inductance;
            LM: Lumen = Candela;
            LX: Lux = Candela / Meter2;
            BQ: Becquerel = Hertz;
            GY: Gray = Joule / Kilogram;
            SV: Sievert = Gray;
            KAT: Katal = Mole / Second;

            M2: Meter2 = Meter * Meter, Area;
            M3: Meter3 = Meter2 * Meter, Volume;

            PM: PerMeter = Unitless / Meter, ReciprocalLength;
            PM2: PerMeter2 = PerMeter / Meter;
            PM3: PerMeter3 = PerMeter2 / Meter;

            S2: Second2 = Second * Second;
            S3: Second3 = Second2 * Second;
            S4: Second4 = Second3 * Second;

            PS2: PerSecond2 = Unitless / Second2;
            PS3: PerSecond3 = Unitless / Second3;
            PS4: PerSecond4 = Unitless / Second4;

            MPS: MeterPerSecond = Meter / Second, Velocity;
            MPS2: MeterPerSecond2 = Meter / Second2, Acceleration;
            MPS3: MeterPerSecond3 = Meter / Second3, Jerk;
            MPS4: MeterPerSecond4 = Meter / Second4;

            M2PS: Meter2PerSecond = Meter2 / Second;
            M2PS2: Meter2PerSecond2 = Meter2 / Second2;
            M2PS3: Meter2PerSecond3 = Meter2 / Second3;

            M3PS: Meter3PerSecond = Meter3 / Second;
            M3PS2: Meter3PerSecond2 = Meter3 / Second2;
            M3PS3: Meter3PerSecond3 = Meter3 / Second3;

            NS: NewtonSecond = Newton * Second;
            JS: JouleSecond = Joule * Second;
            NPS: NewtonPerSecond = Newton / Second;

            KGPM: KilogramPerMeter = Kilogram / Meter;
            KGPM2: KilogramPerMeter2 = Kilogram / Meter2;
            KGPM3: KilogramPerMeter3 = Kilogram / Meter3;

            MPKG: MeterPerKilogram = Meter / Kilogram;
            M2PKG: Meter2PerKilogram = Meter2 / Kilogram;
            M3PKG: Meter3PerKilogram = Meter3 / Kilogram;

            MOLPM: MolePerMeter = Mole / Meter;
            MOLPM2: MolePerMeter2 = Mole / Meter2;
            MOLPM3: MolePerMeter3 = Mole / Meter3;

            MPMOL: MeterPerMole = Meter / Mole;
            M2PMOL: Meter2PerMole = Meter2 / Mole;
            M3PMOL: Meter3PerMole = Meter3 / Mole;

            JPK: JoulePerKelvin = Joule / Kelvin;
            JPKMOL: JoulePerKelvinMole = JoulePerKelvin / Mole;
            JPKGK: JoulePerKilogramKelvin = JoulePerKelvin / Kilogram;
            JPMOL: JoulePerMole = Joule / Mole;
            JPKG: JoulePerKilogram = Joule / Kilogram;
            JPM2: JoulePerMeter2 = Joule / Meter2;
            JPM3: JoulePerMeter3 = Joule / Meter3;

            NPM: NewtonPerMeter = JoulePerMeter2;
            WPM2: WattPerMeter2 = Watt / Meter2;
            WPMK: WattPerMeterKelvin = Watt / Meter / Kelvin;

            PAS: PascalSecond = Pascal * Second;

            CPM2: CoulombPerMeter2 = Coulomb / Meter2;
            CPM3: CoulombPerMeter3 = Coulomb / Meter3;
            APM2: AmperePerMeter2 = Ampere / Meter2;
            SIEPM: SiemensPerMeter = Siemens / Meter;
            SIEM2PMOL: SiemensMeter2PerMole = Siemens * Meter2 / Mole;
            FPM: FaradPerMeter = Farad / Meter;
            HPM: HenryPerMeter = Henry / Meter;
            VPM: VoltPerMeter = Volt / Meter;
            APM: AmperePerMeter = Ampere / Meter;
            CDPM2: CandelaPerMeter2 = Candela / Meter2;
            LMS: LumenSecond = Lumen * Second;
            LXS: LuxSecond = Lux * Second;
            CPKG: CoulombPerKilogram = Coulomb / Kilogram;
            GYPS: GrayPerSecond = Gray / Second;
            OHMM: OhmMeter = Ohm * Meter;
            CPM: CoulombPerMeter = Coulomb / Meter;
            MOLPKG: MolePerKilogram = Mole / Kilogram;
            KGPMOL: KilogramPerMole = Kilogram / Mole;
            KGPS: KilogramPerSecomd = Kilogram / Second;
            JPT: JoulePerTesla = Joule / Tesla;
            WPM3: WattPerMeter3 = Watt / Meter3;
            KPW: KelvinPerWatt = Kelvin / Watt;
            PK: PerKelvin = Unitless / Kelvin;
            KPM: KelvinPerMeter = Kelvin / Meter;
            M2PVS: Meter2PerVoltSecond = Meter2 / Volt / Second;
            JPM2S: JoulePerMeter2Second = JoulePerMeter2 / Second;
            PPA: PerPascal = Unitless / Pascal;
            PH: PerHenry = Unitless / Henry;
            WBPM: WeberPerMeter = Weber / Meter;
            WBM: WeberMeter = Weber * Meter;
            TM: TeslaMeter = Tesla * Meter;
            M3PMOLS: Meter3PerMoleSecond = Meter3 / Mole / Second;
            NMSPKG: NewtonMeterSecondPerKilogram = Newton * Meter * Second / Kilogram;
            LMPW: LumenPerWatt = Lumen / Watt;
            MPH: MeterPerHenry = Meter / Henry;
            WPM: WattPerMeter = Watt / Meter;
        ),
        constants: constants!(
            RAD: Unitless = 1.0 * ONE.value_unsafe, "Radian";
            SR: Unitless = 1.0 * ONE.value_unsafe, "Steradian";

            MIN: Second = 60.0 * S.value_unsafe, "Minute";
            HR: Second = 60.0 * MIN.value_unsafe, "Hour";
            DAY: Second = 24.0 * HR.value_unsafe, "Day";

            DEG: Unitless = consts::PI / 180.0 * RAD.value_unsafe, "Degree";
            HA: Meter2 = 10000.0 * M2.value_unsafe, "Hectare";
            L: Meter3 = 0.001 * M3.value_unsafe, "Liter";
            TNE: Kilogram = 1.0e3 * KG.value_unsafe, "Tonne";
            AU: Meter = 149_597_870_700.0 * M.value_unsafe, "Astronomical unit";

            E: Coulomb = 1.6021766208e-19 * C.value_unsafe, "Elementary charge";
            EV: Joule = E.value_unsafe * V.value_unsafe, "Electronvolt";
            U: Kilogram = 1.660539040e-27 * KG.value_unsafe, "Unified atomic mass unit; dalton";

            C0: MeterPerSecond = 299792458.0 * MPS.value_unsafe, "Speed of light in a vacuum";

            HBAR: JouleSecond = 1.054571800e-34 * JS.value_unsafe, "Reduced Planck constant";
            M_E: Kilogram = 9.10938356e-31 * KG.value_unsafe, "Electron mass";
            R_BOHR: Meter = 0.52917721067e-10 * M.value_unsafe, "Bohr radius";
            EH: Joule = 4.359744650e-18 * J.value_unsafe, "Hartree energy";
            AO: Meter = 1e-10 * M.value_unsafe, "Ångström";
            ARE: Meter2 = 100.0 * M2.value_unsafe, "Are";
            BARN: Meter2 = 1e-28 * M2.value_unsafe, "Barn";
            BAR: Pascal = 1e5 * PA.value_unsafe, "Bar";
            MBAR: Pascal = 100.0 * PA.value_unsafe, "Millibar";
            ATM: Pascal = 101325.0 * PA.value_unsafe, "Atmosphere";
            BA: Pascal = 0.1 * PA.value_unsafe, "Barye";
            MMHG: Pascal = 133.322387415 * PA.value_unsafe, "Millimeter of mercury";
            TORR: Pascal = ATM.value_unsafe / 760.0, "Torr";

            DYN: Newton = 1.0e-5 * N.value_unsafe, "Dyne";

            FT: Meter = 0.3048 * M.value_unsafe, "Foot";
            IN: Meter = FT.value_unsafe / 12.0, "Inch";
            YD: Meter = 3.0 * FT.value_unsafe, "Yard";
            MI: Meter = 5280.0 * FT.value_unsafe, "Mile";

            LB: Kilogram = 0.45359237 * KG.value_unsafe, "Pound mass";
            OZ: Kilogram = LB.value_unsafe / 16.0, "Ounce";

            LBF: Newton = 4.4482216152605 * N.value_unsafe, "Pound force";
        ),
        fmt: true,
        from: vec![
            "UCUM",
        ],
        refl_blacklist: vec!
            ["MOL", "KAT", "MOLPM", "MPMOL", "MOLPKG", "KGPMOL", "M2PMOL", "M3PMOL",
             "SIEM2PMOL", "JPKMOL", "JPMOL", "MOLPM2", "MOLPM3", "M3PMOLS"],
    }
}
<commit_msg>Fix derived unit typo.<commit_after>use super::*;

pub fn new() -> System {
    System {
        name: "SI", module: "si",
        doc_prelude: "The International System of Units (SI)

Where experimental values are used for constants, the values are obtained from the 2014 values from
[The NIST Reference on Constants, Unit, and Uncertainty](http://physics.nist.gov/cuu/Constants/).

",
        base: base_units!(
            M: Meter, m, Length;
            KG: Kilogram, kg, Mass;
            S: Second, s, Time;
            A: Ampere, A, Current;
            K: Kelvin, K, Temperature;
            CD: Candela, cd, LuminousIntensity;
            MOL: Mole, mol, AmountOfSubstance;
        ),
        derived: derived_units!(
            HZ: Hertz = Unitless / Second, Frequency;
            N: Newton = Kilogram * Meter / Second2, Force;
            PA: Pascal = Newton / Meter2, Pressure;
            J: Joule = Newton * Meter, Energy;
            W: Watt = Joule / Second, Power;
            C: Coulomb = Second * Ampere, Charge;
            V: Volt = Watt / Ampere, ElectricPotential;
            F: Farad = Coulomb / Volt, Capacitance;
            OHM: Ohm = Volt / Ampere, Resistance;
            SIE: Siemens = Ampere / Volt, Conductance;
            WB: Weber = Joule / Ampere, MagneticFlux;
            T: Tesla = Weber / Meter2;
            H: Henry = Ohm * Second, Inductance;
            LM: Lumen = Candela;
            LX: Lux = Candela / Meter2;
            BQ: Becquerel = Hertz;
            GY: Gray = Joule / Kilogram;
            SV: Sievert = Gray;
            KAT: Katal = Mole / Second;

            M2: Meter2 = Meter * Meter, Area;
            M3: Meter3 = Meter2 * Meter, Volume;

            PM: PerMeter = Unitless / Meter, ReciprocalLength;
            PM2: PerMeter2 = PerMeter / Meter;
            PM3: PerMeter3 = PerMeter2 / Meter;

            S2: Second2 = Second * Second;
            S3: Second3 = Second2 * Second;
            S4: Second4 = Second3 * Second;

            PS2: PerSecond2 = Unitless / Second2;
            PS3: PerSecond3 = Unitless / Second3;
            PS4: PerSecond4 = Unitless / Second4;

            MPS: MeterPerSecond = Meter / Second, Velocity;
            MPS2: MeterPerSecond2 = Meter / Second2, Acceleration;
            MPS3: MeterPerSecond3 = Meter / Second3, Jerk;
            MPS4: MeterPerSecond4 = Meter / Second4;

            M2PS: Meter2PerSecond = Meter2 / Second;
            M2PS2: Meter2PerSecond2 = Meter2 / Second2;
            M2PS3: Meter2PerSecond3 = Meter2 / Second3;

            M3PS: Meter3PerSecond = Meter3 / Second;
            M3PS2: Meter3PerSecond2 = Meter3 / Second2;
            M3PS3: Meter3PerSecond3 = Meter3 / Second3;

            NS: NewtonSecond = Newton * Second;
            JS: JouleSecond = Joule * Second;
            NPS: NewtonPerSecond = Newton / Second;

            KGPM: KilogramPerMeter = Kilogram / Meter;
            KGPM2: KilogramPerMeter2 = Kilogram / Meter2;
            KGPM3: KilogramPerMeter3 = Kilogram / Meter3;

            MPKG: MeterPerKilogram = Meter / Kilogram;
            M2PKG: Meter2PerKilogram = Meter2 / Kilogram;
            M3PKG: Meter3PerKilogram = Meter3 / Kilogram;

            MOLPM: MolePerMeter = Mole / Meter;
            MOLPM2: MolePerMeter2 = Mole / Meter2;
            MOLPM3: MolePerMeter3 = Mole / Meter3;

            MPMOL: MeterPerMole = Meter / Mole;
            M2PMOL: Meter2PerMole = Meter2 / Mole;
            M3PMOL: Meter3PerMole = Meter3 / Mole;

            JPK: JoulePerKelvin = Joule / Kelvin;
            JPKMOL: JoulePerKelvinMole = JoulePerKelvin / Mole;
            JPKGK: JoulePerKilogramKelvin = JoulePerKelvin / Kilogram;
            JPMOL: JoulePerMole = Joule / Mole;
            JPKG: JoulePerKilogram = Joule / Kilogram;
            JPM2: JoulePerMeter2 = Joule / Meter2;
            JPM3: JoulePerMeter3 = Joule / Meter3;

            NPM: NewtonPerMeter = JoulePerMeter2;
            WPM2: WattPerMeter2 = Watt / Meter2;
            WPMK: WattPerMeterKelvin = Watt / Meter / Kelvin;

            PAS: PascalSecond = Pascal * Second;

            CPM2: CoulombPerMeter2 = Coulomb / Meter2;
            CPM3: CoulombPerMeter3 = Coulomb / Meter3;
            APM2: AmperePerMeter2 = Ampere / Meter2;
            SIEPM: SiemensPerMeter = Siemens / Meter;
            SIEM2PMOL: SiemensMeter2PerMole = Siemens * Meter2 / Mole;
            FPM: FaradPerMeter = Farad / Meter;
            HPM: HenryPerMeter = Henry / Meter;
            VPM: VoltPerMeter = Volt / Meter;
            APM: AmperePerMeter = Ampere / Meter;
            CDPM2: CandelaPerMeter2 = Candela / Meter2;
            LMS: LumenSecond = Lumen * Second;
            LXS: LuxSecond = Lux * Second;
            CPKG: CoulombPerKilogram = Coulomb / Kilogram;
            GYPS: GrayPerSecond = Gray / Second;
            OHMM: OhmMeter = Ohm * Meter;
            CPM: CoulombPerMeter = Coulomb / Meter;
            MOLPKG: MolePerKilogram = Mole / Kilogram;
            KGPMOL: KilogramPerMole = Kilogram / Mole;
            KGPS: KilogramPerSecond = Kilogram / Second;
            JPT: JoulePerTesla = Joule / Tesla;
            WPM3: WattPerMeter3 = Watt / Meter3;
            KPW: KelvinPerWatt = Kelvin / Watt;
            PK: PerKelvin = Unitless / Kelvin;
            KPM: KelvinPerMeter = Kelvin / Meter;
            M2PVS: Meter2PerVoltSecond = Meter2 / Volt / Second;
            JPM2S: JoulePerMeter2Second = JoulePerMeter2 / Second;
            PPA: PerPascal = Unitless / Pascal;
            PH: PerHenry = Unitless / Henry;
            WBPM: WeberPerMeter = Weber / Meter;
            WBM: WeberMeter = Weber * Meter;
            TM: TeslaMeter = Tesla * Meter;
            M3PMOLS: Meter3PerMoleSecond = Meter3 / Mole / Second;
            NMSPKG: NewtonMeterSecondPerKilogram = Newton * Meter * Second / Kilogram;
            LMPW: LumenPerWatt = Lumen / Watt;
            MPH: MeterPerHenry = Meter / Henry;
            WPM: WattPerMeter = Watt / Meter;
        ),
        constants: constants!(
            RAD: Unitless = 1.0 * ONE.value_unsafe, "Radian";
            SR: Unitless = 1.0 * ONE.value_unsafe, "Steradian";

            MIN: Second = 60.0 * S.value_unsafe, "Minute";
            HR: Second = 60.0 * MIN.value_unsafe, "Hour";
            DAY: Second = 24.0 * HR.value_unsafe, "Day";

            DEG: Unitless = consts::PI / 180.0 * RAD.value_unsafe, "Degree";
            HA: Meter2 = 10000.0 * M2.value_unsafe, "Hectare";
            L: Meter3 = 0.001 * M3.value_unsafe, "Liter";
            TNE: Kilogram = 1.0e3 * KG.value_unsafe, "Tonne";
            AU: Meter = 149_597_870_700.0 * M.value_unsafe, "Astronomical unit";

            E: Coulomb = 1.6021766208e-19 * C.value_unsafe, "Elementary charge";
            EV: Joule = E.value_unsafe * V.value_unsafe, "Electronvolt";
            U: Kilogram = 1.660539040e-27 * KG.value_unsafe, "Unified atomic mass unit; dalton";

            C0: MeterPerSecond = 299792458.0 * MPS.value_unsafe, "Speed of light in a vacuum";

            HBAR: JouleSecond = 1.054571800e-34 * JS.value_unsafe, "Reduced Planck constant";
            M_E: Kilogram = 9.10938356e-31 * KG.value_unsafe, "Electron mass";
            R_BOHR: Meter = 0.52917721067e-10 * M.value_unsafe, "Bohr radius";
            EH: Joule = 4.359744650e-18 * J.value_unsafe, "Hartree energy";
            AO: Meter = 1e-10 * M.value_unsafe, "Ångström";
            ARE: Meter2 = 100.0 * M2.value_unsafe, "Are";
            BARN: Meter2 = 1e-28 * M2.value_unsafe, "Barn";
            BAR: Pascal = 1e5 * PA.value_unsafe, "Bar";
            MBAR: Pascal = 100.0 * PA.value_unsafe, "Millibar";
            ATM: Pascal = 101325.0 * PA.value_unsafe, "Atmosphere";
            BA: Pascal = 0.1 * PA.value_unsafe, "Barye";
            MMHG: Pascal = 133.322387415 * PA.value_unsafe, "Millimeter of mercury";
            TORR: Pascal = ATM.value_unsafe / 760.0, "Torr";

            DYN: Newton = 1.0e-5 * N.value_unsafe, "Dyne";

            FT: Meter = 0.3048 * M.value_unsafe, "Foot";
            IN: Meter = FT.value_unsafe / 12.0, "Inch";
            YD: Meter = 3.0 * FT.value_unsafe, "Yard";
            MI: Meter = 5280.0 * FT.value_unsafe, "Mile";

            LB: Kilogram = 0.45359237 * KG.value_unsafe, "Pound mass";
            OZ: Kilogram = LB.value_unsafe / 16.0, "Ounce";

            LBF: Newton = 4.4482216152605 * N.value_unsafe, "Pound force";
        ),
        fmt: true,
        from: vec![
            "UCUM",
        ],
        refl_blacklist: vec!
            ["MOL", "KAT", "MOLPM", "MPMOL", "MOLPKG", "KGPMOL", "M2PMOL", "M3PMOL",
             "SIEM2PMOL", "JPKMOL", "JPMOL", "MOLPM2", "MOLPM3", "M3PMOLS"],
    }
}
<|endoftext|>


<commit_before>
// silence warnings while still a WIP
#![allow(unused_variables)]
#![allow(dead_code)]
#![allow(unused_assignments)]
#![allow(unused_imports)]

#[allow(non_snake_case)]
pub mod ExecutionEngine {

    type FnRefs = HashMap<FuncId, u32>;
    type FnDependencies = HashMap<FuncId, FnRefs>;
    use autograd::{Variable, Function, FuncId, FuncIntf, RootKind};
    use tensor::{Tensor, TensorKind, TensorKindList};
    use std::collections::{HashSet, HashMap, VecDeque};
    use itertools;

    fn _compute_dependencies(function: &Function) -> FnDependencies {
        unimplemented!()
    }
    fn _free_backward_dependency(dependencies: &FnDependencies,
                                 prev_func: &Function,
                                 func: &Function,
                                 arg_id: i32)
                                 -> usize {
        unimplemented!();
    }
    fn _is_ready_for_backward(dependencies: &FnDependencies, function: &Function) -> bool {
        for ref deps in dependencies[&function.id].iter() {
            if deps.1 > &0 {
                return false;
            }
        }
        return true;
    }
    fn _add_grad(need_copy: &mut HashSet<TensorKind>,
                 prev_grad: &mut Vec<Option<TensorKind>>,
                 output_nr: usize,
                 d_prev_func: &TensorKind) {
        // We can't match and operate on the vector at
        // the same time because that would be performing
        // a mutable borrow in the middle of an immutable
        // borrow so we use a boolean
        // d_prev_func is just used as a placeholder so that
        // both arms match
        let (mut grad_tensor, matched) = match prev_grad[output_nr] {
            Some(ref t) => (t.clone(), true),
            None => (d_prev_func.clone(), false),
        };
        if matched {
            if need_copy.contains(&grad_tensor) {
                need_copy.remove(&grad_tensor);
                grad_tensor = grad_tensor.copy();
                // we perform the add before the assignment
                // in order to avoid an extra clone since
                // creation of the Option and subsequent
                // assignment moves the grad_tensor
                grad_tensor.add_(d_prev_func);
                prev_grad[output_nr] = Some(grad_tensor);
            } else {
                grad_tensor.add_(d_prev_func);
            }
        } else {
            // We need to clone twice here as the compiler
            // can't determine the lifetime dependency
            // between the two
            need_copy.insert(d_prev_func.clone());
            prev_grad[output_nr] = Some(d_prev_func.clone());
        }

    }
    pub fn run_backward<T: Copy>(var: &mut Variable<T>, grad: TensorKind, retain_variables: bool) {
        let grad_fn;
        match var.grad_fn() {
            Some(v) => grad_fn = v,
            None => {
                let grad_tensor = Tensor::<T>::from(grad);
                var._do_backward(&grad_tensor);
                return;
            }
        }
        let mut ready = VecDeque::new();
        ready.push_back((grad_fn.clone(), vec![grad]));
        let mut need_copy: HashSet<TensorKind> = HashSet::new();
        let mut not_ready: HashMap<FuncId, Vec<Option<TensorKind>>> = HashMap::new();

        let dependencies = _compute_dependencies(&grad_fn);
        while !ready.is_empty() {
            let (mut func, grad) = ready.pop_front().unwrap();
            let grad_input = func._do_backward(&grad, retain_variables);
            for (&(ref prev_func_, ref arg_id), ref d_prev_func) in
                itertools::zip(func.previous_functions(), grad_input) {
                if !prev_func_.requires_grad() {
                    continue;
                }
                let prev_func = match prev_func_ {
                    &RootKind::RootVar(ref v) => {
                        v.clone()._do_backward(&d_prev_func);
                        return;
                    }
                    &RootKind::RootFunc(ref f) => f,
                };
                let output_nr = _free_backward_dependency(&dependencies, prev_func, &func, *arg_id);
                let is_ready = _is_ready_for_backward(&dependencies, prev_func);
                if is_ready {
                    let prev_grad = if not_ready.contains_key(&prev_func.id) {
                        let mut prev_grad = not_ready[&prev_func.id].clone();
                        _add_grad(&mut need_copy, &mut prev_grad, output_nr, &d_prev_func);
                        prev_grad
                            .iter()
                            .map(|sv| if let &Some(ref v) = sv {
                                     v.clone()
                                 } else {
                                     panic!("found None")
                                 })
                            .collect()
                    } else {
                        vec![d_prev_func.clone()]
                    };
                    ready.push_front((prev_func.clone(), prev_grad))
                } else {
                    let mut prev_grad = if not_ready.contains_key(&prev_func.id) {
                        not_ready[&prev_func.id].clone()
                    } else {
                        prev_func.output_ids().iter().map(|_| None).collect()
                    };
                    _add_grad(&mut need_copy, &mut prev_grad, output_nr, &d_prev_func);
                    not_ready.insert(prev_func.id, prev_grad.clone());
                }
            }
        }
    }
}
<commit_msg>implement remaining autograd engine functions and a (misplaced) Counter<commit_after>
// silence warnings while still a WIP
#![allow(unused_variables)]
#![allow(dead_code)]
#![allow(unused_assignments)]
#![allow(unused_imports)]

use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::cell::{Cell, RefCell};
use std::ops::{Index, IndexMut};

// Pythonesque Counter implementation
// XXX Move to a separate module
static ZERO: usize = 0;
pub struct Counter<T: Hash + Eq + Clone> {
    pub map: RefCell<HashMap<T, Cell<usize>>>,
}
impl<T: Hash + Eq + Clone> Counter<T> {
    pub fn new() -> Self {
        Counter { map: RefCell::new(HashMap::new()) }
    }
    pub fn len(&self) -> usize {
        self.map.borrow().len()
    }
    pub fn remove(&self, idx: &T) {
        self.map.borrow_mut().remove(idx);
    }
}
impl<T: Hash + Eq + Clone> Index<T> for Counter<T> {
    type Output = usize;
    fn index(&self, idx: T) -> &Self::Output {
        let mapp = self.map.as_ptr();
        let map = unsafe { &mut *mapp };
        if map.contains_key(&idx) {
            let cntp = map[&idx].as_ptr();
            unsafe { &*cntp }
        } else {
            //map.insert(idx, Cell::new(0));
            //let mut cntp = map[&idx].as_ptr();
            //unsafe {& *cntp}
            &ZERO
        }
    }
}
impl<T: Hash + Eq + Clone> IndexMut<T> for Counter<T> {
    fn index_mut(&mut self, idx: T) -> &mut Self::Output {
        let mapp = self.map.as_ptr();
        let mut map = unsafe { &mut *mapp };
        if map.contains_key(&idx) {
            let cntp = map[&idx].as_ptr();
            unsafe { &mut *cntp }
        } else {
            map.insert(idx.clone(), Cell::new(0));
            let cntp = map[&idx].as_ptr();
            unsafe { &mut *cntp }
        }
    }
}

#[allow(non_snake_case)]
pub mod ExecutionEngine {
    use autograd::{Variable, Function, FuncId, FuncIntf, RootKind, VarId};
    use tensor::{Tensor, TensorKind, TensorKindList};
    use std::collections::{HashSet, HashMap, VecDeque};
    use std::cell::RefCell;
    use itertools;
    use super::Counter;

    type FnRefs = RefCell<Vec<Counter<FuncId>>>;
    type FnDependencies = HashMap<FuncId, FnRefs>;

    fn fn_ref_init(count: usize) -> FnRefs {
        let mut v = Vec::new();
        for _ in 0..count {
            v.push(Counter::new())
        }
        RefCell::new(v)
    }

    fn _compute_dependencies(function: &Function) -> FnDependencies {
        let mut dependencies = FnDependencies::new();
        let mut seen: HashSet<FuncId> = HashSet::new();
        let mut queue = VecDeque::new();
        seen.insert(function.id);
        queue.push_back(function);
        while !queue.is_empty() {
            let func = queue.pop_front().unwrap();
            for &(ref prev_func_, ref arg_id) in func.previous_functions().iter() {
                let prev_func = match prev_func_ {
                    &RootKind::RootVar(_) => continue,
                    &RootKind::RootFunc(ref f) => f,
                };
                if !dependencies.contains_key(&prev_func.id) {
                    dependencies.insert(prev_func.id, fn_ref_init(prev_func.output_ids().len()));
                }
                let output_idx = prev_func.output_ids()[arg_id];
                let mut fnrefs = dependencies[&prev_func.id].borrow_mut();
                fnrefs[output_idx][func.id] += 1;
                if !seen.contains(&prev_func.id) {
                    queue.push_back(prev_func);
                    seen.insert(prev_func.id);
                }
            }
        }
        dependencies
    }
    fn _free_backward_dependency(dependencies: &FnDependencies,
                                 prev_func: &Function,
                                 func: &Function,
                                 arg_id: i32)
                                 -> usize {
        let mut deps = dependencies[&prev_func.id].borrow_mut();
        let output_idx = prev_func.output_ids()[&arg_id];
        let mut output_deps = &mut deps[output_idx];
        output_deps[func.id] -= 1;
        if output_deps[func.id] == 0 {
            output_deps.remove(&func.id)
        }
        output_idx
    }
    fn _is_ready_for_backward(dependencies: &FnDependencies, function: &Function) -> bool {
        for ref deps in dependencies[&function.id].borrow().iter() {
            if deps.len() > 0 {
                return false;
            }
        }
        return true;
    }
    fn _add_grad(need_copy: &mut HashSet<TensorKind>,
                 prev_grad: &mut Vec<Option<TensorKind>>,
                 output_nr: usize,
                 d_prev_func: &TensorKind) {
        // We can't match and operate on the vector at
        // the same time because that would be performing
        // a mutable borrow in the middle of an immutable
        // borrow so we use a boolean
        // d_prev_func is just used as a placeholder so that
        // both arms match
        let (mut grad_tensor, matched) = match prev_grad[output_nr] {
            Some(ref t) => (t.clone(), true),
            None => (d_prev_func.clone(), false),
        };
        if matched {
            if need_copy.contains(&grad_tensor) {
                need_copy.remove(&grad_tensor);
                grad_tensor = grad_tensor.copy();
                // we perform the add before the assignment
                // in order to avoid an extra clone since
                // creation of the Option and subsequent
                // assignment moves the grad_tensor
                grad_tensor.add_(d_prev_func);
                prev_grad[output_nr] = Some(grad_tensor);
            } else {
                grad_tensor.add_(d_prev_func);
            }
        } else {
            // We need to clone twice here as the compiler
            // can't determine the lifetime dependency
            // between the two
            need_copy.insert(d_prev_func.clone());
            prev_grad[output_nr] = Some(d_prev_func.clone());
        }

    }
    pub fn run_backward<T: Copy>(var: &mut Variable<T>, grad: TensorKind, retain_variables: bool) {
        let grad_fn;
        match var.grad_fn() {
            Some(v) => grad_fn = v,
            None => {
                let grad_tensor = Tensor::<T>::from(grad);
                var._do_backward(&grad_tensor);
                return;
            }
        }
        let mut ready = VecDeque::new();
        ready.push_back((grad_fn.clone(), vec![grad]));
        let mut need_copy: HashSet<TensorKind> = HashSet::new();
        let mut not_ready: HashMap<FuncId, Vec<Option<TensorKind>>> = HashMap::new();

        let dependencies = _compute_dependencies(&grad_fn);
        while !ready.is_empty() {
            let (mut func, grad) = ready.pop_front().unwrap();
            let grad_input = func._do_backward(&grad, retain_variables);
            for (&(ref prev_func_, ref arg_id), ref d_prev_func) in
                itertools::zip(func.previous_functions(), grad_input) {
                if !prev_func_.requires_grad() {
                    continue;
                }
                let prev_func = match prev_func_ {
                    &RootKind::RootVar(ref v) => {
                        v.clone()._do_backward(&d_prev_func);
                        return;
                    }
                    &RootKind::RootFunc(ref f) => f,
                };
                let output_nr = _free_backward_dependency(&dependencies, prev_func, &func, *arg_id);
                let is_ready = _is_ready_for_backward(&dependencies, prev_func);
                if is_ready {
                    let prev_grad = if not_ready.contains_key(&prev_func.id) {
                        let mut prev_grad = not_ready[&prev_func.id].clone();
                        _add_grad(&mut need_copy, &mut prev_grad, output_nr, &d_prev_func);
                        prev_grad
                            .iter()
                            .map(|sv| if let &Some(ref v) = sv {
                                     v.clone()
                                 } else {
                                     panic!("found None")
                                 })
                            .collect()
                    } else {
                        vec![d_prev_func.clone()]
                    };
                    ready.push_front((prev_func.clone(), prev_grad))
                } else {
                    let mut prev_grad = if not_ready.contains_key(&prev_func.id) {
                        not_ready[&prev_func.id].clone()
                    } else {
                        prev_func.output_ids().iter().map(|_| None).collect()
                    };
                    _add_grad(&mut need_copy, &mut prev_grad, output_nr, &d_prev_func);
                    not_ready.insert(prev_func.id, prev_grad.clone());
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate idola;
extern crate crypto;
extern crate psocrypto;
extern crate byteorder;
extern crate rand;
#[macro_use] extern crate log;
extern crate env_logger;

use std::thread;
use std::io;
use std::io::{Write, Read};
use std::net::{TcpListener, TcpStream};
use std::fmt::Debug;

use idola::message::{MessageEncode, MessageDecode};
use idola::message::patch::Message;

use psocrypto::PcCipher;

use crypto::symmetriccipher::Decryptor;

#[derive(Clone, Copy)]
enum ClientState {
    Connected,
    Welcomed
}

struct ClientContext {
    pub stream: TcpStream,
    pub state: ClientState,
    pub client_cipher: PcCipher,
    pub server_cipher: PcCipher
}

impl ClientContext {
    /// Send a message struct.
    fn send_msg<T: MessageEncode + Debug>(&mut self, msg: &T, encrypt: bool) -> io::Result<()> {
        if encrypt {
            debug!("msg send: {:?}", msg);
            try!(msg.encode_msg(&mut self.stream as &mut Write, Some(&mut self.server_cipher)));
            self.stream.flush()
        } else {
            debug!("msg send (unenc): {:?}", msg);
            try!(msg.encode_msg(&mut self.stream as &mut Write, None));
            self.stream.flush()
        }
    }

    /// Receive a message enum.
    fn recv_msg(&mut self, decrypt: bool) -> io::Result<Message> {
        if decrypt {
            let m = Message::decode_msg(&mut self.stream as &mut Read, Some(&mut self.client_cipher as &mut Decryptor));
            match m {
                Ok(m) => {debug!("msg recv: {:?}", m); Ok(m)},
                e => e
            }
        } else {
            let m = Message::decode_msg(&mut self.stream as &mut Read, None);
            match m {
                Ok(m) => {debug!("msg recv (unenc): {:?}", m); Ok(m)},
                e => e
            }
        }
    }
}

unsafe impl Send for ClientState {}
unsafe impl Send for ClientContext {}

fn handle_client(mut ctx: ClientContext) {
    use idola::message::patch::*;

    let peer_addr = ctx.stream.peer_addr().unwrap();

    info!("client {} connected", peer_addr);

    let w = Welcome {
        server_vector: ctx.server_cipher.seed(),
        client_vector: ctx.client_cipher.seed()
    };
    if let Err(e) = ctx.send_msg(&w, false) {
        error!("unable to send welcome message to {}: {}", peer_addr, e);
        return
    }
    info!("client {} welcomed", peer_addr);

    ctx.state = ClientState::Welcomed;

    // Client will send a Welcome message as an ack. We reply with a Login ack.
    if let Ok(s) = ctx.recv_msg(true) {
        info!("received a message after being welcomed");
        if let Message::Welcome(None) = s {
            info!("sending login ack");
            match ctx.send_msg(&Message::Login(None), true) { Err(_) => return, _ => () }
        }
    }

    loop {
        use std::net::Ipv4Addr;
        use std::str::FromStr;
        // Read message
        if let Ok(s) = ctx.recv_msg(true) {match s {
            Message::Login(Some(_)) => {
                let motd = Motd {
                    message: "how am I gonna feed all these little... BABS\nhey there\n\nrust is cool".to_string()
                };
                ctx.send_msg(&motd, true).unwrap();
                let red = Redirect { ip_addr: Ipv4Addr::from_str("127.0.0.1").unwrap(), port: 11001 };
                ctx.send_msg(&red, true).unwrap();
                // Now we break out of this connection.
                return;
            },
            _ => println!("uhhh")
        }}
    };
}

fn main() {
    if let Err(_) = std::env::var("RUST_LOG") {
        std::env::set_var("RUST_LOG", "DEBUG");
        std::env::set_var("RUST_BACKTRACE", "1");
    }
    env_logger::init().unwrap();

    info!("IDOLA Phantasy Star Online Patch Server");
    info!("Version 0.1.0");

    let tcp_listener = TcpListener::bind("127.0.0.1:11000").unwrap();
    for stream in tcp_listener.incoming() {
        match stream {
            Ok(s) => {
                let ctx = ClientContext {
                    stream: s,
                    state: ClientState::Connected,
                    client_cipher: PcCipher::new(0),
                    server_cipher: PcCipher::new(0)
                };
                thread::spawn(move|| handle_client(ctx));
            },
            Err(e) => {println!("Error: could not accept connection from {}", e);}
        };
    }
    println!("Placeholders");
}
<commit_msg>Should probably randomize those patch server keys.<commit_after>extern crate idola;
extern crate crypto;
extern crate psocrypto;
extern crate byteorder;
extern crate rand;
#[macro_use] extern crate log;
extern crate env_logger;

use std::thread;
use std::io;
use std::io::{Write, Read};
use std::net::{TcpListener, TcpStream};
use std::fmt::Debug;

use idola::message::{MessageEncode, MessageDecode};
use idola::message::patch::Message;

use psocrypto::PcCipher;

use crypto::symmetriccipher::Decryptor;

use rand::random;

#[derive(Clone, Copy)]
enum ClientState {
    Connected,
    Welcomed
}

struct ClientContext {
    pub stream: TcpStream,
    pub state: ClientState,
    pub client_cipher: PcCipher,
    pub server_cipher: PcCipher
}

impl ClientContext {
    /// Send a message struct.
    fn send_msg<T: MessageEncode + Debug>(&mut self, msg: &T, encrypt: bool) -> io::Result<()> {
        if encrypt {
            debug!("msg send: {:?}", msg);
            try!(msg.encode_msg(&mut self.stream as &mut Write, Some(&mut self.server_cipher)));
            self.stream.flush()
        } else {
            debug!("msg send (unenc): {:?}", msg);
            try!(msg.encode_msg(&mut self.stream as &mut Write, None));
            self.stream.flush()
        }
    }

    /// Receive a message enum.
    fn recv_msg(&mut self, decrypt: bool) -> io::Result<Message> {
        if decrypt {
            let m = Message::decode_msg(&mut self.stream as &mut Read, Some(&mut self.client_cipher as &mut Decryptor));
            match m {
                Ok(m) => {debug!("msg recv: {:?}", m); Ok(m)},
                e => e
            }
        } else {
            let m = Message::decode_msg(&mut self.stream as &mut Read, None);
            match m {
                Ok(m) => {debug!("msg recv (unenc): {:?}", m); Ok(m)},
                e => e
            }
        }
    }
}

unsafe impl Send for ClientState {}
unsafe impl Send for ClientContext {}

fn handle_client(mut ctx: ClientContext) {
    use idola::message::patch::*;

    let peer_addr = ctx.stream.peer_addr().unwrap();

    info!("client {} connected", peer_addr);

    let w = Welcome {
        server_vector: ctx.server_cipher.seed(),
        client_vector: ctx.client_cipher.seed()
    };
    if let Err(e) = ctx.send_msg(&w, false) {
        error!("unable to send welcome message to {}: {}", peer_addr, e);
        return
    }
    info!("client {} welcomed", peer_addr);

    ctx.state = ClientState::Welcomed;

    // Client will send a Welcome message as an ack. We reply with a Login ack.
    if let Ok(s) = ctx.recv_msg(true) {
        info!("received a message after being welcomed");
        if let Message::Welcome(None) = s {
            info!("sending login ack");
            match ctx.send_msg(&Message::Login(None), true) { Err(_) => return, _ => () }
        }
    }

    loop {
        use std::net::Ipv4Addr;
        use std::str::FromStr;
        // Read message
        if let Ok(s) = ctx.recv_msg(true) {match s {
            Message::Login(Some(_)) => {
                let motd = Motd {
                    message: "how am I gonna feed all these little... BABS\nhey there\n\nrust is cool".to_string()
                };
                ctx.send_msg(&motd, true).unwrap();
                let red = Redirect { ip_addr: Ipv4Addr::from_str("127.0.0.1").unwrap(), port: 11001 };
                ctx.send_msg(&red, true).unwrap();
                // Now we break out of this connection.
                return;
            },
            _ => println!("uhhh")
        }}
    };
}

fn main() {
    if let Err(_) = std::env::var("RUST_LOG") {
        std::env::set_var("RUST_LOG", "DEBUG");
        std::env::set_var("RUST_BACKTRACE", "1");
    }
    env_logger::init().unwrap();

    info!("IDOLA Phantasy Star Online Patch Server");
    info!("Version 0.1.0");

    let tcp_listener = TcpListener::bind("127.0.0.1:11000").unwrap();
    for stream in tcp_listener.incoming() {
        match stream {
            Ok(s) => {
                let ctx = ClientContext {
                    stream: s,
                    state: ClientState::Connected,
                    client_cipher: PcCipher::new(random()),
                    server_cipher: PcCipher::new(random())
                };
                thread::spawn(move|| handle_client(ctx));
            },
            Err(e) => {println!("Error: could not accept connection from {}", e);}
        };
    }
    println!("Placeholders");
}
<|endoftext|>


<commit_before>//#![allow(dead_code)]

use std::fmt;
use std::fmt::Display;

#[derive(Debug, PartialEq)]
enum FileState {
    Open,
    Closed,
}

#[derive(Debug)]
struct File {
    name: String,
    data: Vec<u8>,
    state: FileState,
}

impl Display for FileState {
    fn fmt(self: &FileState, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            FileState::Open => write!(f, "OPEN"),
            FileState::Closed => write!(f, "CLOSED"),
        }
    }
}

impl Display for File {
    fn fmt(self: &File, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<{} ({})>", self.name, self.state)
    }
}

impl File {
    fn new(name: &str) -> File {
        File {
            name: String::from(name),
            data: Vec::new(),
            state: FileState::Closed,
        }
    }

    fn new_with_data(name: &str, data: &Vec<u8>) -> File {
        let mut f = File::new(name);
        f.data = data.clone();
        f
    }

    fn read(self: &File, save_to: &mut Vec<u8>) -> Result<usize, String> {
        if self.state != FileState::Open {
            return Err(String::from("File must be open for reading"));
        }
        let mut tmp = self.data.clone();
        let read_length = tmp.len();
        save_to.reserve(read_length);
        save_to.append(&mut tmp);
        Ok(read_length)
    }
}

fn open(mut f: File) -> Result<File, String> {
    f.state = FileState::Open;
    Ok(f)
}

fn close(mut f: File) -> Result<File, String> {
    f.state = FileState::Closed;
    Ok(f)
}

fn main() {
    let f6_data: Vec<u8> = vec![114, 117, 115, 116, 33];
    let mut f6 = File::new_with_data("6.txt", &f6_data);

    let mut buffer: Vec<u8> = vec![];

    if f6.read(&mut buffer).is_err() {
        println!("Error checking is working");
    }

    f6 = open(f6).unwrap();
    let f6_length = f6.read(&mut buffer).unwrap();
    f6 = close(f6).unwrap();

    let text = String::from_utf8_lossy(&buffer);

    println!("{:?}", f6);
    println!("{}", f6);
    println!("{} is {} bytes long", f6.name, f6_length);
    println!("{}", text);
}
<commit_msg>use &self shortcut<commit_after>//#![allow(dead_code)]

use std::fmt;
use std::fmt::Display;

#[derive(Debug, PartialEq)]
enum FileState {
    Open,
    Closed,
}

#[derive(Debug)]
struct File {
    name: String,
    data: Vec<u8>,
    state: FileState,
}

impl Display for FileState {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            FileState::Open => write!(f, "OPEN"),
            FileState::Closed => write!(f, "CLOSED"),
        }
    }
}

impl Display for File {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<{} ({})>", self.name, self.state)
    }
}

impl File {
    fn new(name: &str) -> File {
        File {
            name: String::from(name),
            data: Vec::new(),
            state: FileState::Closed,
        }
    }

    fn new_with_data(name: &str, data: &Vec<u8>) -> File {
        let mut f = File::new(name);
        f.data = data.clone();
        f
    }

    fn read(&self, save_to: &mut Vec<u8>) -> Result<usize, String> {
        if self.state != FileState::Open {
            return Err(String::from("File must be open for reading"));
        }
        let mut tmp = self.data.clone();
        let read_length = tmp.len();
        save_to.reserve(read_length);
        save_to.append(&mut tmp);
        Ok(read_length)
    }
}

fn open(mut f: File) -> Result<File, String> {
    f.state = FileState::Open;
    Ok(f)
}

fn close(mut f: File) -> Result<File, String> {
    f.state = FileState::Closed;
    Ok(f)
}

fn main() {
    let f6_data: Vec<u8> = vec![114, 117, 115, 116, 33];
    let mut f6 = File::new_with_data("6.txt", &f6_data);

    let mut buffer: Vec<u8> = vec![];

    if f6.read(&mut buffer).is_err() {
        println!("Error checking is working");
    }

    f6 = open(f6).unwrap();
    let f6_length = f6.read(&mut buffer).unwrap();
    f6 = close(f6).unwrap();

    let text = String::from_utf8_lossy(&buffer);

    println!("{:?}", f6);
    println!("{}", f6);
    println!("{} is {} bytes long", f6.name, f6_length);
    println!("{}", text);
}
<|endoftext|>


<commit_before>//#![allow(dead_code)]

//extern crate rand;
//use rand::Rng;
//
//fn one_in(n: f64) -> bool {
//    rand::thread_rng().gen_bool(n)
//}

#[derive(Debug, PartialEq)]
enum FileState {
    Open,
    Closed,
}

#[derive(Debug)]
struct File {
    name: String,
    data: Vec<u8>,
    state: FileState,
}

impl File {
    fn new(name: &str) -> File {
        File {
            name: String::from(name),
            data: Vec::new(),
            state: FileState::Closed,
        }
    }

    fn new_with_data(name: &str, data: &Vec<u8>) -> File {
        let mut f = File::new(name);
        f.data = data.clone();
        f
    }

    fn read(self: &File, save_to: &mut Vec<u8>) -> Result<usize, String> {
        if self.state != FileState::Open {
            return Err(String::from("File must be open for reading"));
        }
        let mut tmp = self.data.clone();
        let read_length = tmp.len();
        save_to.reserve(read_length);
        save_to.append(&mut tmp);
        Ok(read_length)
    }
}

fn open(mut f: File) -> Result<File, String> {
    f.state = FileState::Open;
    Ok(f)
}

fn close(mut f: File) -> Result<File, String> {
    f.state = FileState::Closed;
    Ok(f)
}

fn main() {
    let f5_data: Vec<u8> = vec![114, 117, 115, 116, 33];
    let mut f5 = File::new_with_data("5.txt", &f5_data);

    let mut buffer: Vec<u8> = vec![];

    if f5.read(&mut buffer).is_err() {
        println!("Error checking is working");
    }

    f5 = open(f5).unwrap();
    let f5_length = f5.read(&mut buffer).unwrap();
    f5 = close(f5).unwrap();

    let text = String::from_utf8_lossy(&buffer);

    println!("{:?}", f5);
    println!("{} is {} bytes long", f5.name, f5_length);
    println!("{}", text);
}
<commit_msg>implement Display trait<commit_after>//#![allow(dead_code)]

use std::fmt;
use std::fmt::Display;

#[derive(Debug, PartialEq)]
enum FileState {
    Open,
    Closed,
}

#[derive(Debug)]
struct File {
    name: String,
    data: Vec<u8>,
    state: FileState,
}

impl Display for FileState {
    fn fmt(self: &FileState, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            FileState::Open => write!(f, "OPEN"),
            FileState::Closed => write!(f, "CLOSED"),
        }
    }
}

impl Display for File {
    fn fmt(self: &File, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<{} ({})>", self.name, self.state)
    }
}

impl File {
    fn new(name: &str) -> File {
        File {
            name: String::from(name),
            data: Vec::new(),
            state: FileState::Closed,
        }
    }

    fn new_with_data(name: &str, data: &Vec<u8>) -> File {
        let mut f = File::new(name);
        f.data = data.clone();
        f
    }

    fn read(self: &File, save_to: &mut Vec<u8>) -> Result<usize, String> {
        if self.state != FileState::Open {
            return Err(String::from("File must be open for reading"));
        }
        let mut tmp = self.data.clone();
        let read_length = tmp.len();
        save_to.reserve(read_length);
        save_to.append(&mut tmp);
        Ok(read_length)
    }
}

fn open(mut f: File) -> Result<File, String> {
    f.state = FileState::Open;
    Ok(f)
}

fn close(mut f: File) -> Result<File, String> {
    f.state = FileState::Closed;
    Ok(f)
}

fn main() {
    let f6_data: Vec<u8> = vec![114, 117, 115, 116, 33];
    let mut f6 = File::new_with_data("6.txt", &f6_data);

    let mut buffer: Vec<u8> = vec![];

    if f6.read(&mut buffer).is_err() {
        println!("Error checking is working");
    }

    f6 = open(f6).unwrap();
    let f6_length = f6.read(&mut buffer).unwrap();
    f6 = close(f6).unwrap();

    let text = String::from_utf8_lossy(&buffer);

    println!("{:?}", f6);
    println!("{}", f6);
    println!("{} is {} bytes long", f6.name, f6_length);
    println!("{}", text);
}
<|endoftext|>


<commit_before>use futures::{Async, Poll, Stream};
use futures::sync::{mpsc, oneshot};
use want;

use common::Never;

pub type RetryPromise<T, U> = oneshot::Receiver<Result<U, (::Error, Option<T>)>>;
pub type Promise<T> = oneshot::Receiver<Result<T, ::Error>>;

pub fn channel<T, U>() -> (Sender<T, U>, Receiver<T, U>) {
    let (tx, rx) = mpsc::unbounded();
    let (giver, taker) = want::new();
    let tx = Sender {
        buffered_once: false,
        giver: giver,
        inner: tx,
    };
    let rx = Receiver {
        inner: rx,
        taker: taker,
    };
    (tx, rx)
}

/// A bounded sender of requests and callbacks for when responses are ready.
///
/// While the inner sender is unbounded, the Giver is used to determine
/// if the Receiver is ready for another request.
pub struct Sender<T, U> {
    /// One message is always allowed, even if the Receiver hasn't asked
    /// for it yet. This boolean keeps track of whether we've sent one
    /// without notice.
    buffered_once: bool,
    /// The Giver helps watch that the the Receiver side has been polled
    /// when the queue is empty. This helps us know when a request and
    /// response have been fully processed, and a connection is ready
    /// for more.
    giver: want::Giver,
    /// Actually bounded by the Giver, plus `buffered_once`.
    inner: mpsc::UnboundedSender<Envelope<T, U>>,
}

/// An unbounded version.
///
/// Cannot poll the Giver, but can still use it to determine if the Receiver
/// has been dropped. However, this version can be cloned.
pub struct UnboundedSender<T, U> {
    /// Only used for `is_closed`, since mpsc::UnboundedSender cannot be checked.
    giver: want::SharedGiver,
    inner: mpsc::UnboundedSender<Envelope<T, U>>,
}

impl<T, U> Sender<T, U> {
    pub fn poll_ready(&mut self) -> Poll<(), ::Error> {
        self.giver.poll_want()
            .map_err(|_| ::Error::new_closed())
    }

    pub fn is_ready(&self) -> bool {
        self.giver.is_wanting()
    }

    pub fn is_closed(&self) -> bool {
        self.giver.is_canceled()
    }

    fn can_send(&mut self) -> bool {
        if self.giver.give() || !self.buffered_once {
            // If the receiver is ready *now*, then of course we can send.
            //
            // If the receiver isn't ready yet, but we don't have anything
            // in the channel yet, then allow one message.
            self.buffered_once = true;
            true
        } else {
            false
        }
    }

    pub fn try_send(&mut self, val: T) -> Result<RetryPromise<T, U>, T> {
        if !self.can_send() {
            return Err(val);
        }
        let (tx, rx) = oneshot::channel();
        self.inner.unbounded_send(Envelope(Some((val, Callback::Retry(tx)))))
            .map(move |_| rx)
            .map_err(|e| e.into_inner().0.take().expect("envelope not dropped").0)
    }

    pub fn send(&mut self, val: T) -> Result<Promise<U>, T> {
        if !self.can_send() {
            return Err(val);
        }
        let (tx, rx) = oneshot::channel();
        self.inner.unbounded_send(Envelope(Some((val, Callback::NoRetry(tx)))))
            .map(move |_| rx)
            .map_err(|e| e.into_inner().0.take().expect("envelope not dropped").0)
    }

    pub fn unbound(self) -> UnboundedSender<T, U> {
        UnboundedSender {
            giver: self.giver.shared(),
            inner: self.inner,
        }
    }
}

impl<T, U> UnboundedSender<T, U> {
    pub fn is_ready(&self) -> bool {
        !self.giver.is_canceled()
    }

    pub fn is_closed(&self) -> bool {
        self.giver.is_canceled()
    }

    pub fn try_send(&mut self, val: T) -> Result<RetryPromise<T, U>, T> {
        let (tx, rx) = oneshot::channel();
        self.inner.unbounded_send(Envelope(Some((val, Callback::Retry(tx)))))
            .map(move |_| rx)
            .map_err(|e| e.into_inner().0.take().expect("envelope not dropped").0)
    }
}

impl<T, U> Clone for UnboundedSender<T, U> {
    fn clone(&self) -> Self {
        UnboundedSender {
            giver: self.giver.clone(),
            inner: self.inner.clone(),
        }
    }
}

pub struct Receiver<T, U> {
    inner: mpsc::UnboundedReceiver<Envelope<T, U>>,
    taker: want::Taker,
}

impl<T, U> Stream for Receiver<T, U> {
    type Item = (T, Callback<T, U>);
    type Error = Never;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        match self.inner.poll() {
            Ok(Async::Ready(item)) => Ok(Async::Ready(item.map(|mut env| {
                env.0.take().expect("envelope not dropped")
            }))),
            Ok(Async::NotReady) => {
                self.taker.want();
                Ok(Async::NotReady)
            }
            Err(()) => unreachable!("mpsc never errors"),
        }
    }
}

impl<T, U> Drop for Receiver<T, U> {
    fn drop(&mut self) {
        // Notify the giver about the closure first, before dropping
        // the mpsc::Receiver.
        self.taker.cancel();
    }
}

struct Envelope<T, U>(Option<(T, Callback<T, U>)>);

impl<T, U> Drop for Envelope<T, U> {
    fn drop(&mut self) {
        if let Some((val, cb)) = self.0.take() {
            let _ = cb.send(Err((::Error::new_canceled(None::<::Error>), Some(val))));
        }
    }
}

pub enum Callback<T, U> {
    Retry(oneshot::Sender<Result<U, (::Error, Option<T>)>>),
    NoRetry(oneshot::Sender<Result<U, ::Error>>),
}

impl<T, U> Callback<T, U> {
    pub(crate) fn is_canceled(&self) -> bool {
        match *self {
            Callback::Retry(ref tx) => tx.is_canceled(),
            Callback::NoRetry(ref tx) => tx.is_canceled(),
        }
    }

    pub(crate) fn poll_cancel(&mut self) -> Poll<(), ()> {
        match *self {
            Callback::Retry(ref mut tx) => tx.poll_cancel(),
            Callback::NoRetry(ref mut tx) => tx.poll_cancel(),
        }
    }

    pub(crate) fn send(self, val: Result<U, (::Error, Option<T>)>) {
        match self {
            Callback::Retry(tx) => {
                let _ = tx.send(val);
            },
            Callback::NoRetry(tx) => {
                let _ = tx.send(val.map_err(|e| e.0));
            }
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate pretty_env_logger;
    #[cfg(feature = "nightly")]
    extern crate test;

    use futures::{future, Future, Stream};

    #[derive(Debug)]
    struct Custom(i32);

    #[test]
    fn drop_receiver_sends_cancel_errors() {
        let _ = pretty_env_logger::try_init();

        future::lazy(|| {
            let (mut tx, mut rx) = super::channel::<Custom, ()>();

            // must poll once for try_send to succeed
            assert!(rx.poll().expect("rx empty").is_not_ready());

            let promise = tx.try_send(Custom(43)).unwrap();
            drop(rx);

            promise.then(|fulfilled| {
                let err = fulfilled
                    .expect("fulfilled")
                    .expect_err("promise should error");

                match (err.0.kind(), err.1) {
                    (&::error::Kind::Canceled, Some(_)) => (),
                    e => panic!("expected Error::Cancel(_), found {:?}", e),
                }

                Ok::<(), ()>(())
            })
        }).wait().unwrap();
    }

    #[test]
    fn sender_checks_for_want_on_send() {
        future::lazy(|| {
            let (mut tx, mut rx) = super::channel::<Custom, ()>();
            // one is allowed to buffer, second is rejected
            let _ = tx.try_send(Custom(1)).expect("1 buffered");
            tx.try_send(Custom(2)).expect_err("2 not ready");

            assert!(rx.poll().expect("rx 1").is_ready());
            // Even though 1 has been popped, only 1 could be buffered for the
            // lifetime of the channel.
            tx.try_send(Custom(2)).expect_err("2 still not ready");

            assert!(rx.poll().expect("rx empty").is_not_ready());
            let _ = tx.try_send(Custom(2)).expect("2 ready");

            Ok::<(), ()>(())
        }).wait().unwrap();
    }

    #[test]
    fn unbounded_sender_doesnt_bound_on_want() {
        let (tx, rx) = super::channel::<Custom, ()>();
        let mut tx = tx.unbound();

        let _ = tx.try_send(Custom(1)).unwrap();
        let _ = tx.try_send(Custom(2)).unwrap();
        let _ = tx.try_send(Custom(3)).unwrap();

        drop(rx);

        let _ = tx.try_send(Custom(4)).unwrap_err();
    }

    #[cfg(feature = "nightly")]
    #[bench]
    fn giver_queue_throughput(b: &mut test::Bencher) {
        let (mut tx, mut rx) = super::channel::<i32, ()>();

        b.iter(move || {
            ::futures::future::lazy(|| {
                let _ = tx.send(1).unwrap();
                loop {
                    let async = rx.poll().unwrap();
                    if async.is_not_ready() {
                        break;
                    }
                }

                Ok::<(), ()>(())
            }).wait().unwrap();
        })
    }

    #[cfg(feature = "nightly")]
    #[bench]
    fn giver_queue_not_ready(b: &mut test::Bencher) {
        let (_tx, mut rx) = super::channel::<i32, ()>();

        b.iter(move || {
            ::futures::future::lazy(|| {
                assert!(rx.poll().unwrap().is_not_ready());

                Ok::<(), ()>(())
            }).wait().unwrap();
        })
    }

    #[cfg(feature = "nightly")]
    #[bench]
    fn giver_queue_cancel(b: &mut test::Bencher) {
        let (_tx, mut rx) = super::channel::<i32, ()>();

        b.iter(move || {
            rx.taker.cancel();
        })
    }
}
<commit_msg>chore(client): adjust dispatch giver throughput benchmark generics<commit_after>use futures::{Async, Poll, Stream};
use futures::sync::{mpsc, oneshot};
use want;

use common::Never;

pub type RetryPromise<T, U> = oneshot::Receiver<Result<U, (::Error, Option<T>)>>;
pub type Promise<T> = oneshot::Receiver<Result<T, ::Error>>;

pub fn channel<T, U>() -> (Sender<T, U>, Receiver<T, U>) {
    let (tx, rx) = mpsc::unbounded();
    let (giver, taker) = want::new();
    let tx = Sender {
        buffered_once: false,
        giver: giver,
        inner: tx,
    };
    let rx = Receiver {
        inner: rx,
        taker: taker,
    };
    (tx, rx)
}

/// A bounded sender of requests and callbacks for when responses are ready.
///
/// While the inner sender is unbounded, the Giver is used to determine
/// if the Receiver is ready for another request.
pub struct Sender<T, U> {
    /// One message is always allowed, even if the Receiver hasn't asked
    /// for it yet. This boolean keeps track of whether we've sent one
    /// without notice.
    buffered_once: bool,
    /// The Giver helps watch that the the Receiver side has been polled
    /// when the queue is empty. This helps us know when a request and
    /// response have been fully processed, and a connection is ready
    /// for more.
    giver: want::Giver,
    /// Actually bounded by the Giver, plus `buffered_once`.
    inner: mpsc::UnboundedSender<Envelope<T, U>>,
}

/// An unbounded version.
///
/// Cannot poll the Giver, but can still use it to determine if the Receiver
/// has been dropped. However, this version can be cloned.
pub struct UnboundedSender<T, U> {
    /// Only used for `is_closed`, since mpsc::UnboundedSender cannot be checked.
    giver: want::SharedGiver,
    inner: mpsc::UnboundedSender<Envelope<T, U>>,
}

impl<T, U> Sender<T, U> {
    pub fn poll_ready(&mut self) -> Poll<(), ::Error> {
        self.giver.poll_want()
            .map_err(|_| ::Error::new_closed())
    }

    pub fn is_ready(&self) -> bool {
        self.giver.is_wanting()
    }

    pub fn is_closed(&self) -> bool {
        self.giver.is_canceled()
    }

    fn can_send(&mut self) -> bool {
        if self.giver.give() || !self.buffered_once {
            // If the receiver is ready *now*, then of course we can send.
            //
            // If the receiver isn't ready yet, but we don't have anything
            // in the channel yet, then allow one message.
            self.buffered_once = true;
            true
        } else {
            false
        }
    }

    pub fn try_send(&mut self, val: T) -> Result<RetryPromise<T, U>, T> {
        if !self.can_send() {
            return Err(val);
        }
        let (tx, rx) = oneshot::channel();
        self.inner.unbounded_send(Envelope(Some((val, Callback::Retry(tx)))))
            .map(move |_| rx)
            .map_err(|e| e.into_inner().0.take().expect("envelope not dropped").0)
    }

    pub fn send(&mut self, val: T) -> Result<Promise<U>, T> {
        if !self.can_send() {
            return Err(val);
        }
        let (tx, rx) = oneshot::channel();
        self.inner.unbounded_send(Envelope(Some((val, Callback::NoRetry(tx)))))
            .map(move |_| rx)
            .map_err(|e| e.into_inner().0.take().expect("envelope not dropped").0)
    }

    pub fn unbound(self) -> UnboundedSender<T, U> {
        UnboundedSender {
            giver: self.giver.shared(),
            inner: self.inner,
        }
    }
}

impl<T, U> UnboundedSender<T, U> {
    pub fn is_ready(&self) -> bool {
        !self.giver.is_canceled()
    }

    pub fn is_closed(&self) -> bool {
        self.giver.is_canceled()
    }

    pub fn try_send(&mut self, val: T) -> Result<RetryPromise<T, U>, T> {
        let (tx, rx) = oneshot::channel();
        self.inner.unbounded_send(Envelope(Some((val, Callback::Retry(tx)))))
            .map(move |_| rx)
            .map_err(|e| e.into_inner().0.take().expect("envelope not dropped").0)
    }
}

impl<T, U> Clone for UnboundedSender<T, U> {
    fn clone(&self) -> Self {
        UnboundedSender {
            giver: self.giver.clone(),
            inner: self.inner.clone(),
        }
    }
}

pub struct Receiver<T, U> {
    inner: mpsc::UnboundedReceiver<Envelope<T, U>>,
    taker: want::Taker,
}

impl<T, U> Stream for Receiver<T, U> {
    type Item = (T, Callback<T, U>);
    type Error = Never;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        match self.inner.poll() {
            Ok(Async::Ready(item)) => Ok(Async::Ready(item.map(|mut env| {
                env.0.take().expect("envelope not dropped")
            }))),
            Ok(Async::NotReady) => {
                self.taker.want();
                Ok(Async::NotReady)
            }
            Err(()) => unreachable!("mpsc never errors"),
        }
    }
}

impl<T, U> Drop for Receiver<T, U> {
    fn drop(&mut self) {
        // Notify the giver about the closure first, before dropping
        // the mpsc::Receiver.
        self.taker.cancel();
    }
}

struct Envelope<T, U>(Option<(T, Callback<T, U>)>);

impl<T, U> Drop for Envelope<T, U> {
    fn drop(&mut self) {
        if let Some((val, cb)) = self.0.take() {
            let _ = cb.send(Err((::Error::new_canceled(None::<::Error>), Some(val))));
        }
    }
}

pub enum Callback<T, U> {
    Retry(oneshot::Sender<Result<U, (::Error, Option<T>)>>),
    NoRetry(oneshot::Sender<Result<U, ::Error>>),
}

impl<T, U> Callback<T, U> {
    pub(crate) fn is_canceled(&self) -> bool {
        match *self {
            Callback::Retry(ref tx) => tx.is_canceled(),
            Callback::NoRetry(ref tx) => tx.is_canceled(),
        }
    }

    pub(crate) fn poll_cancel(&mut self) -> Poll<(), ()> {
        match *self {
            Callback::Retry(ref mut tx) => tx.poll_cancel(),
            Callback::NoRetry(ref mut tx) => tx.poll_cancel(),
        }
    }

    pub(crate) fn send(self, val: Result<U, (::Error, Option<T>)>) {
        match self {
            Callback::Retry(tx) => {
                let _ = tx.send(val);
            },
            Callback::NoRetry(tx) => {
                let _ = tx.send(val.map_err(|e| e.0));
            }
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate pretty_env_logger;
    #[cfg(feature = "nightly")]
    extern crate test;

    use futures::{future, Future, Stream};

    #[derive(Debug)]
    struct Custom(i32);

    #[test]
    fn drop_receiver_sends_cancel_errors() {
        let _ = pretty_env_logger::try_init();

        future::lazy(|| {
            let (mut tx, mut rx) = super::channel::<Custom, ()>();

            // must poll once for try_send to succeed
            assert!(rx.poll().expect("rx empty").is_not_ready());

            let promise = tx.try_send(Custom(43)).unwrap();
            drop(rx);

            promise.then(|fulfilled| {
                let err = fulfilled
                    .expect("fulfilled")
                    .expect_err("promise should error");

                match (err.0.kind(), err.1) {
                    (&::error::Kind::Canceled, Some(_)) => (),
                    e => panic!("expected Error::Cancel(_), found {:?}", e),
                }

                Ok::<(), ()>(())
            })
        }).wait().unwrap();
    }

    #[test]
    fn sender_checks_for_want_on_send() {
        future::lazy(|| {
            let (mut tx, mut rx) = super::channel::<Custom, ()>();
            // one is allowed to buffer, second is rejected
            let _ = tx.try_send(Custom(1)).expect("1 buffered");
            tx.try_send(Custom(2)).expect_err("2 not ready");

            assert!(rx.poll().expect("rx 1").is_ready());
            // Even though 1 has been popped, only 1 could be buffered for the
            // lifetime of the channel.
            tx.try_send(Custom(2)).expect_err("2 still not ready");

            assert!(rx.poll().expect("rx empty").is_not_ready());
            let _ = tx.try_send(Custom(2)).expect("2 ready");

            Ok::<(), ()>(())
        }).wait().unwrap();
    }

    #[test]
    fn unbounded_sender_doesnt_bound_on_want() {
        let (tx, rx) = super::channel::<Custom, ()>();
        let mut tx = tx.unbound();

        let _ = tx.try_send(Custom(1)).unwrap();
        let _ = tx.try_send(Custom(2)).unwrap();
        let _ = tx.try_send(Custom(3)).unwrap();

        drop(rx);

        let _ = tx.try_send(Custom(4)).unwrap_err();
    }

    #[cfg(feature = "nightly")]
    #[bench]
    fn giver_queue_throughput(b: &mut test::Bencher) {
        use {Body, Request, Response};
        let (mut tx, mut rx) = super::channel::<Request<Body>, Response<Body>>();

        b.iter(move || {
            ::futures::future::lazy(|| {
                let _ = tx.send(Request::default()).unwrap();
                loop {
                    let ok = rx.poll().unwrap();
                    if ok.is_not_ready() {
                        break;
                    }
                }

                Ok::<_, ()>(())
            }).wait().unwrap();
        })
    }

    #[cfg(feature = "nightly")]
    #[bench]
    fn giver_queue_not_ready(b: &mut test::Bencher) {
        let (_tx, mut rx) = super::channel::<i32, ()>();

        b.iter(move || {
            ::futures::future::lazy(|| {
                assert!(rx.poll().unwrap().is_not_ready());

                Ok::<(), ()>(())
            }).wait().unwrap();
        })
    }

    #[cfg(feature = "nightly")]
    #[bench]
    fn giver_queue_cancel(b: &mut test::Bencher) {
        let (_tx, mut rx) = super::channel::<i32, ()>();

        b.iter(move || {
            rx.taker.cancel();
        })
    }
}
<|endoftext|>