<commit_before>use std::marker::PhantomData;

use Construct;
use Data;
use Count;
use Of;
use ToIndex;
use ToPos;
use Zero;

/// Dimension is a list of numbers, position is a list of numbers.
pub struct DimensionN<T = Data>(PhantomData<T>);

impl<T> Construct for DimensionN<T> {
    fn new() -> DimensionN<T> { DimensionN(PhantomData) }
}

impl Count<Vec<usize>> for DimensionN<Data> {
    type N = usize;
    fn count(&self, dim: &Vec<usize>) -> usize {
        let mut prod = 1;
        for i in 0..dim.len() {
            prod *= dim[i];
        }
        prod
    }
}

impl<T, U>
Count<Vec<U>> for DimensionN<Of<T>>
    where
        T: Construct + Count<U, N = usize>
{
    type N = usize;
    fn count(&self, dim: &Vec<U>) -> usize {
        let of: T = Construct::new();
        let mut prod = 1;
        for i in 0..dim.len() {
            prod *= of.count(&dim[i]);
        }
        prod
    }
}

impl Zero<Vec<usize>, Vec<usize>> for DimensionN<Data> {
    fn zero(&self, dim: &Vec<usize>) -> Vec<usize> {
        vec![0, dim.len()]
    }
}

impl<T, U, V>
Zero<Vec<U>, Vec<V>>
for DimensionN<Of<T>>
    where T: Construct + Count<U> + ToPos<U, V> + Zero<U, V>
{
    fn zero(&self, dim: &Vec<U>) -> Vec<V> {
        let of: T = Construct::new();
        let mut v = Vec::with_capacity(dim.len());
        for i in 0..dim.len() {
            v.push(of.zero(&dim[i]));
        }
        v
    }
}

impl ToIndex<Vec<usize>, Vec<usize>> for DimensionN<Data> {
    fn to_index(&self, dim: &Vec<usize>, pos: &Vec<usize>) -> usize {
        let mut dim_index = 0;
        for i in (0..dim.len()).rev() {
            dim_index = dim_index * dim[i] + pos[i];
        }
        dim_index
    }
}

impl<T, U, V>
ToIndex<Vec<U>, Vec<V>> for DimensionN<Of<T>>
    where T: Construct + Count<U, N = usize> + ToIndex<U, V>
{
    fn to_index(
        &self,
        dim: &Vec<U>,
        pos: &Vec<V>
    ) -> usize {
        let of: T = Construct::new();
        let mut dim_index = 0;
        for i in (0..dim.len()).rev() {
            dim_index = dim_index * of.count(&dim[i])
                      + of.to_index(&dim[i], &pos[i]);
        }
        dim_index
    }
}

impl ToPos<Vec<usize>, Vec<usize>> for DimensionN<Data> {
    fn to_pos(&self, dim: &Vec<usize>, index: usize, pos: &mut Vec<usize>) {
        unsafe { pos.set_len(0); }
        let mut prod = self.count(dim);
        for _ in 0..dim.len() {
            pos.push(0);
        }
        let mut dim_index = index;
        for i in (0..dim.len()).rev() {
            prod /= dim[i];
            let p_i = dim_index / prod;
            *pos.get_mut(i).unwrap() = p_i;
            dim_index -= p_i * prod;
        }
    }
}

impl<T, U, V>
ToPos<Vec<U>, Vec<V>>
for DimensionN<Of<T>>
    where T: Construct + Count<U, N = usize> + ToPos<U, V>
{
    fn to_pos(
        &self,
        dim: &Vec<U>,
        index: usize,
        pos: &mut Vec<V>
    ) {
        let of: T = Construct::new();
        let mut prod = self.count(dim);
        let mut dim_index = index;
        for (i, p) in pos.iter_mut().enumerate().rev() {
            prod /= of.count(&dim[i]);
            let p_i = dim_index / prod;
            of.to_pos(&dim[i], p_i, p);
            dim_index -= p_i * prod;
        }
    }
}

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

    #[test]
    fn features() {
        is_complete::<DimensionN, Vec<usize>, Vec<usize>>();
        is_complete::<DimensionN<Of<Pair>>, Vec<usize>,
            Vec<(usize, usize)>>();
    }

    #[test]
    fn data() {
        let x: DimensionN = Construct::new();
        let ref dim = vec![3, 3];
        assert_eq!(x.count(dim), 9);
        assert_eq!(x.to_index(dim, &vec![0, 0]), 0);
        assert_eq!(x.to_index(dim, &vec![1, 0]), 1);
        assert_eq!(x.to_index(dim, &vec![0, 1]), 3);
        let mut new_pos = vec![0, 0];
        x.to_pos(dim, 3, &mut new_pos);
        assert_eq!(&new_pos, &[0, 1]);
    }

    #[test]
    fn of() {
        let x: DimensionN<Of<Pair>> = Construct::new();
        let ref dim = vec![3, 4];
        assert_eq!(x.count(dim), 18);
        assert_eq!(x.to_index(dim, &vec![(0, 1), (0, 1)]), 0);
        assert_eq!(x.to_index(dim, &vec![(0, 2), (0, 1)]), 1);
        assert_eq!(x.to_index(dim, &vec![(1, 2), (0, 1)]), 2);
        assert_eq!(x.to_index(dim, &vec![(0, 1), (0, 2)]), 3);
        let mut pos = vec![(0, 0), (0, 0)];
        x.to_pos(dim, 3, &mut pos);
        assert_eq!(pos[0], (0, 1));
        assert_eq!(pos[1], (0, 2));
    }
}
<commit_msg>Impl `Count<Vec<BigUint>>` for `DimensionN`<commit_after>use std::marker::PhantomData;
use std::ops::MulAssign;

use num::BigUint;

use Construct;
use Data;
use Count;
use Of;
use ToIndex;
use ToPos;
use Zero;

/// Dimension is a list of numbers, position is a list of numbers.
pub struct DimensionN<T = Data>(PhantomData<T>);

impl<T> Construct for DimensionN<T> {
    fn new() -> DimensionN<T> { DimensionN(PhantomData) }
}

impl Count<Vec<usize>> for DimensionN<Data> {
    type N = usize;
    fn count(&self, dim: &Vec<usize>) -> usize {
        let mut prod = 1;
        for i in 0..dim.len() {
            prod *= dim[i];
        }
        prod
    }
}

impl Count<Vec<BigUint>> for DimensionN<Data> {
    type N = BigUint;
    fn count(&self, dim: &Vec<BigUint>) -> BigUint {
        let mut prod: BigUint = 1u64.into();
        for i in 0..dim.len() {
            prod *= &dim[i];
        }
        prod
    }
}

impl<T, U>
Count<Vec<U>> for DimensionN<Of<T>>
    where
        T: Construct + Count<U>,
        <T as Count<U>>::N: From<usize> + MulAssign,
{
    type N = <T as Count<U>>::N;
    fn count(&self, dim: &Vec<U>) -> Self::N {
        let of: T = Construct::new();
        let mut prod: Self::N = 1usize.into();
        for i in 0..dim.len() {
            prod *= of.count(&dim[i]);
        }
        prod
    }
}

impl Zero<Vec<usize>, Vec<usize>> for DimensionN<Data> {
    fn zero(&self, dim: &Vec<usize>) -> Vec<usize> {
        vec![0, dim.len()]
    }
}

impl<T, U, V>
Zero<Vec<U>, Vec<V>>
for DimensionN<Of<T>>
    where T: Construct + Count<U> + ToPos<U, V> + Zero<U, V>
{
    fn zero(&self, dim: &Vec<U>) -> Vec<V> {
        let of: T = Construct::new();
        let mut v = Vec::with_capacity(dim.len());
        for i in 0..dim.len() {
            v.push(of.zero(&dim[i]));
        }
        v
    }
}

impl ToIndex<Vec<usize>, Vec<usize>> for DimensionN<Data> {
    fn to_index(&self, dim: &Vec<usize>, pos: &Vec<usize>) -> usize {
        let mut dim_index = 0;
        for i in (0..dim.len()).rev() {
            dim_index = dim_index * dim[i] + pos[i];
        }
        dim_index
    }
}

impl<T, U, V>
ToIndex<Vec<U>, Vec<V>> for DimensionN<Of<T>>
    where T: Construct + Count<U, N = usize> + ToIndex<U, V>
{
    fn to_index(
        &self,
        dim: &Vec<U>,
        pos: &Vec<V>
    ) -> usize {
        let of: T = Construct::new();
        let mut dim_index = 0;
        for i in (0..dim.len()).rev() {
            dim_index = dim_index * of.count(&dim[i])
                      + of.to_index(&dim[i], &pos[i]);
        }
        dim_index
    }
}

impl ToPos<Vec<usize>, Vec<usize>> for DimensionN<Data> {
    fn to_pos(&self, dim: &Vec<usize>, index: usize, pos: &mut Vec<usize>) {
        unsafe { pos.set_len(0); }
        let mut prod = self.count(dim);
        for _ in 0..dim.len() {
            pos.push(0);
        }
        let mut dim_index = index;
        for i in (0..dim.len()).rev() {
            prod /= dim[i];
            let p_i = dim_index / prod;
            *pos.get_mut(i).unwrap() = p_i;
            dim_index -= p_i * prod;
        }
    }
}

impl<T, U, V>
ToPos<Vec<U>, Vec<V>>
for DimensionN<Of<T>>
    where T: Construct + Count<U, N = usize> + ToPos<U, V>
{
    fn to_pos(
        &self,
        dim: &Vec<U>,
        index: usize,
        pos: &mut Vec<V>
    ) {
        let of: T = Construct::new();
        let mut prod = self.count(dim);
        let mut dim_index = index;
        for (i, p) in pos.iter_mut().enumerate().rev() {
            prod /= of.count(&dim[i]);
            let p_i = dim_index / prod;
            of.to_pos(&dim[i], p_i, p);
            dim_index -= p_i * prod;
        }
    }
}

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

    #[test]
    fn features() {
        is_complete::<DimensionN, Vec<usize>, Vec<usize>>();
        is_complete::<DimensionN<Of<Pair>>, Vec<usize>,
            Vec<(usize, usize)>>();
    }

    #[test]
    fn data() {
        let x: DimensionN = Construct::new();
        let ref dim = vec![3, 3];
        assert_eq!(x.count(dim), 9);
        assert_eq!(x.to_index(dim, &vec![0, 0]), 0);
        assert_eq!(x.to_index(dim, &vec![1, 0]), 1);
        assert_eq!(x.to_index(dim, &vec![0, 1]), 3);
        let mut new_pos = vec![0, 0];
        x.to_pos(dim, 3, &mut new_pos);
        assert_eq!(&new_pos, &[0, 1]);
    }

    #[test]
    fn of() {
        let x: DimensionN<Of<Pair>> = Construct::new();
        let ref dim = vec![3, 4];
        assert_eq!(x.count(dim), 18);
        assert_eq!(x.to_index(dim, &vec![(0, 1), (0, 1)]), 0);
        assert_eq!(x.to_index(dim, &vec![(0, 2), (0, 1)]), 1);
        assert_eq!(x.to_index(dim, &vec![(1, 2), (0, 1)]), 2);
        assert_eq!(x.to_index(dim, &vec![(0, 1), (0, 2)]), 3);
        let mut pos = vec![(0, 0), (0, 0)];
        x.to_pos(dim, 3, &mut pos);
        assert_eq!(pos[0], (0, 1));
        assert_eq!(pos[1], (0, 2));
    }
}
<|endoftext|>


<commit_before>// Simon Whitehead, 2016

use byteorder::{ByteOrder, LittleEndian};

use gameboy::registers;

pub struct Cpu {
    rom: Vec<u8>,
    pub registers: registers::Registers,
}

impl Cpu {
    pub fn new(gameboy_color: bool, rom: Vec<u8>) -> Cpu {
        Cpu {
            rom: rom,
            registers: registers::Registers::new(gameboy_color),
        }
    }

    pub fn step(&mut self) {
        let opcode = self.rom[self.registers.pc];
        self.registers.pc += 1;

        match opcode {
            0b00110001 => {
                // LD SP, <u16>
                let val = LittleEndian::read_u16(&self.rom[self.registers.pc..]);
                self.registers.sp = val as usize;

                // Increment program counter
                self.registers.pc += 0x03;
                println!("Stack pointer: {:#X}", self.registers.sp);
            }
            0b00100001 => {
                // LD HL, <u16>
                let val = LittleEndian::read_u16(&self.rom[self.registers.pc..]);
                self.registers.l = (val & 0xFF) as u8;
                self.registers.h = ((val >> 8) & 0xFF) as u8;

                // Increment program counter
                self.registers.pc += 0x03;
            }
            0b10101111 => {
                // XOR A
                self.registers.a = self.registers.a ^ self.registers.a;
                self.registers.flags.zero = self.registers.a == 0;

                // Increment program counter
                self.registers.pc += 0x01;
            }
            _ => panic!("Unknown opcode: {:#X}", opcode),
        }
    }
}

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

    #[test]
    pub fn xor_a_zeros_a_and_sets_zero_flag() {
        let xor_a = vec![0xAF];
        let mut cpu = Cpu::new(true, xor_a);
        cpu.step();

        // A == 0, Z == 1
        assert_eq!(0, cpu.registers.a);
        assert_eq!(true, cpu.registers.flags.zero);
    }

    #[test]
    pub fn ld_hl_u16_should_split_between_h_and_l_registers() {
        let ldhlu16 = vec![0x21, 0xFF, 0x9F];
        let mut cpu = Cpu::new(true, ldhlu16);
        cpu.step();

        // H == 0x9F, L == 0xFF
        assert_eq!(0x9F, cpu.registers.h);
        assert_eq!(0xFF, cpu.registers.l);
    }
}
<commit_msg>Removed debug print in favour of SP unit test<commit_after>// Simon Whitehead, 2016

use byteorder::{ByteOrder, LittleEndian};

use gameboy::registers;

pub struct Cpu {
    rom: Vec<u8>,
    pub registers: registers::Registers,
}

impl Cpu {
    pub fn new(gameboy_color: bool, rom: Vec<u8>) -> Cpu {
        Cpu {
            rom: rom,
            registers: registers::Registers::new(gameboy_color),
        }
    }

    pub fn step(&mut self) {
        let opcode = self.rom[self.registers.pc];
        self.registers.pc += 1;

        match opcode {
            0b00110001 => {
                // LD SP, <u16>
                let val = LittleEndian::read_u16(&self.rom[self.registers.pc..]);
                self.registers.sp = val as usize;

                // Increment program counter
                self.registers.pc += 0x03;
            }
            0b00100001 => {
                // LD HL, <u16>
                let val = LittleEndian::read_u16(&self.rom[self.registers.pc..]);
                self.registers.l = (val & 0xFF) as u8;
                self.registers.h = ((val >> 8) & 0xFF) as u8;

                // Increment program counter
                self.registers.pc += 0x03;
            }
            0b10101111 => {
                // XOR A
                self.registers.a = self.registers.a ^ self.registers.a;
                self.registers.flags.zero = self.registers.a == 0;

                // Increment program counter
                self.registers.pc += 0x01;
            }
            _ => panic!("Unknown opcode: {:#X}", opcode),
        }
    }
}

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

    #[test]
    pub fn ld_sp_u16_should_set_stack_pointer() {
        let ldspu16 = vec![0x31, 0xFE, 0xFF];
        let mut cpu = Cpu::new(true, ldspu16);
        cpu.step();

        // SP == 0xFFFE
        assert_eq!(0xFFFE, cpu.registers.sp);
    }

    #[test]
    pub fn xor_a_zeros_a_and_sets_zero_flag() {
        let xor_a = vec![0xAF];
        let mut cpu = Cpu::new(true, xor_a);
        cpu.step();

        // A == 0, Z == 1
        assert_eq!(0, cpu.registers.a);
        assert_eq!(true, cpu.registers.flags.zero);
    }

    #[test]
    pub fn ld_hl_u16_should_split_between_h_and_l_registers() {
        let ldhlu16 = vec![0x21, 0xFF, 0x9F];
        let mut cpu = Cpu::new(true, ldhlu16);
        cpu.step();

        // H == 0x9F, L == 0xFF
        assert_eq!(0x9F, cpu.registers.h);
        assert_eq!(0xFF, cpu.registers.l);
    }
}
<|endoftext|>


<commit_before>extern crate cmake;
extern crate pkg_config;

use std::env;
use std::env::consts;
use std::path::PathBuf;

fn build_dos(cmake_cfg: &mut cmake::Config) {
    let use_dos_dylib = option_env!("DyLib_DOtherSide").is_some();
    let dst = cmake_cfg.build();

    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());

    if cfg!(windows) {
        println!("cargo:rustc-link-search=native={}", dst.join("build").join("lib").join("Release").display());
    } else {
        println!("cargo:rustc-link-search=native={}", dst.join("build").join("lib").display());
    }

    if use_dos_dylib {
        println!("cargo:rustc-link-lib=dylib=DOtherSide");
    } else {
        println!("cargo:rustc-link-lib=static=DOtherSideStatic");
    }
}

fn find_qt5(_: &mut cmake::Config) {
    /*
     * Support Qt installed via the Ports system on BSD-like systems.
     *
     * The native libs are in `/usr/local/lib`, which is not linked against by default.
     * This means that either the user or every package has to add this if they want to link
     * against something that is not part of the core distribution in `/usr/lib`.
     *
     * See https://wiki.freebsd.org/WarnerLosh/UsrLocal for the line of reasoning & how this will
     * change in the future.
     */
    if cfg!(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd",
                target_os = "dragonfly", target_os = "bitrig")) {
        println!("cargo:rustc-link-search=native=/usr/local/lib");
    }

    /*
     * Parameters for supporting QT on OS X
     *
     * Because QT5 conflicts with QT4 the homebrew package manager won't link
     * the QT5 package into the default search paths for libraries, to deal
     * with this we need to give pkg-config and cmake a nudge in the right
     * direction.
     */
    if cfg!(target_os = "macos") {
        // We use the QTDIR or QTDIR64 env variables to find the location of
        // Qt5. If these are not set, we use the default homebrew install
        // location.
        let qtdir_variable = match consts::ARCH {
            "x86_64" => "QTDIR64",
            _ => "QTDIR",
        };
        let mut qt5_lib_path = PathBuf::new();
        qt5_lib_path.push(env::var(qtdir_variable).unwrap_or(String::from("/usr/local/opt/qt5")));
        qt5_lib_path.push("lib");

        if qt5_lib_path.exists() {
            // First nudge cmake in the direction of the .cmake files added by
            // homebrew. This clobbers the existing value if present, it's
            // unlikely to be present though.
            env::set_var("CMAKE_PREFIX_PATH", qt5_lib_path.join("cmake"));

            // Nudge pkg-config in the direction of the brewed QT to ensure the
            // correct compiler flags get found for the project.
            env::set_var("PKG_CONFIG_PATH", qt5_lib_path.join("pkgconfig"));
        } else {
            panic!("QT5 was not found at the expected location ({}) please install it via homebrew, or set the {} env variable.",
            qt5_lib_path.display(), qtdir_variable);
        }
    }

    if cfg!(windows) {
        let mut qt5_lib_path = PathBuf::new();
        qt5_lib_path.push(env::var("QTDIR").unwrap_or(String::from("C:\\Qt\\5.7\\msvc2015_64")));

        if qt5_lib_path.exists() {
            env::set_var("CMAKE_PREFIX_PATH", &qt5_lib_path);

            qt5_lib_path.push("lib");

            println!("cargo:rustc-link-search=native={}\\system32",env::var("WINDIR").unwrap());
            println!("cargo:rustc-link-search=native={}",qt5_lib_path.display());

            println!("cargo:rustc-link-lib=dylib=Qt5Core");
            println!("cargo:rustc-link-lib=dylib=Qt5Gui");
            println!("cargo:rustc-link-lib=dylib=Qt5Qml");
            println!("cargo:rustc-link-lib=dylib=Qt5Quick");
            println!("cargo:rustc-link-lib=dylib=Qt5Svg");
            println!("cargo:rustc-link-lib=dylib=Qt5Widgets");
        } else {
            panic!("QT5 was not found at the expected location ({}) please install the SDK or set the QTDIR env variable.",
            qt5_lib_path.display());
        }
    } else {
        use pkg_config;

        if cfg!(any(target_os = "macos", target_os = "freebsd", target_os = "bitrig")) {
            println!("cargo:rustc-link-lib=dylib=c++");
        } else {
            println!("cargo:rustc-link-lib=dylib=stdc++");
        }

        match pkg_config::find_library("Qt5Core Qt5Gui Qt5Qml Qt5Quick Qt5Svg") {
            Ok(lib) => {
                for p in lib.link_paths { println!("cargo:rustc-link-search=native={}",p.display()); }
                for p in lib.libs { println!("cargo:rustc-link-lib=dylib={}",p); }
                if cfg!(target_os = "macos") {
                    for p in lib.frameworks { println!("cargo:rustc-link-lib=framework={}",p); }
                }
                for p in lib.include_paths { println!("cargo:include={}",p.display()); }
            }
            Err(e) => panic!("QT5 was not found using pkg-config: {}",e)
        }
    }
}

fn main() {
    let mut cmake_cfg = cmake::Config::new("DOtherSide");
    let dos_path = PathBuf::from("DOtherSide").join("CMakeLists.txt");

    if !dos_path.exists() {
        panic!("DOtherSide submodule not checked out. Please run 'git submodule init' followed by 'git submodule update'.");
    }

    if let Ok(gen) = env::var("CMAKE_GENERATOR") {
        cmake_cfg.generator(gen);
    }

    find_qt5(&mut cmake_cfg);
    build_dos(&mut cmake_cfg);
}
<commit_msg>build.rs: Add pkgconfig's provided framework_paths for Qt frameworks<commit_after>extern crate cmake;
extern crate pkg_config;

use std::env;
use std::env::consts;
use std::path::PathBuf;

fn build_dos(cmake_cfg: &mut cmake::Config) {
    let use_dos_dylib = option_env!("DyLib_DOtherSide").is_some();
    let dst = cmake_cfg.build();

    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());

    if cfg!(windows) {
        println!("cargo:rustc-link-search=native={}", dst.join("build").join("lib").join("Release").display());
    } else {
        println!("cargo:rustc-link-search=native={}", dst.join("build").join("lib").display());
    }

    if use_dos_dylib {
        println!("cargo:rustc-link-lib=dylib=DOtherSide");
    } else {
        println!("cargo:rustc-link-lib=static=DOtherSideStatic");
    }
}

fn find_qt5(_: &mut cmake::Config) {
    /*
     * Support Qt installed via the Ports system on BSD-like systems.
     *
     * The native libs are in `/usr/local/lib`, which is not linked against by default.
     * This means that either the user or every package has to add this if they want to link
     * against something that is not part of the core distribution in `/usr/lib`.
     *
     * See https://wiki.freebsd.org/WarnerLosh/UsrLocal for the line of reasoning & how this will
     * change in the future.
     */
    if cfg!(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd",
                target_os = "dragonfly", target_os = "bitrig")) {
        println!("cargo:rustc-link-search=native=/usr/local/lib");
    }

    /*
     * Parameters for supporting QT on OS X
     *
     * Because QT5 conflicts with QT4 the homebrew package manager won't link
     * the QT5 package into the default search paths for libraries, to deal
     * with this we need to give pkg-config and cmake a nudge in the right
     * direction.
     */
    if cfg!(target_os = "macos") {
        // We use the QTDIR or QTDIR64 env variables to find the location of
        // Qt5. If these are not set, we use the default homebrew install
        // location.
        let qtdir_variable = match consts::ARCH {
            "x86_64" => "QTDIR64",
            _ => "QTDIR",
        };
        let mut qt5_lib_path = PathBuf::new();
        qt5_lib_path.push(env::var(qtdir_variable).unwrap_or(String::from("/usr/local/opt/qt5")));
        qt5_lib_path.push("lib");

        if qt5_lib_path.exists() {
            // First nudge cmake in the direction of the .cmake files added by
            // homebrew. This clobbers the existing value if present, it's
            // unlikely to be present though.
            env::set_var("CMAKE_PREFIX_PATH", qt5_lib_path.join("cmake"));

            // Nudge pkg-config in the direction of the brewed QT to ensure the
            // correct compiler flags get found for the project.
            env::set_var("PKG_CONFIG_PATH", qt5_lib_path.join("pkgconfig"));
        } else {
            panic!("QT5 was not found at the expected location ({}) please install it via homebrew, or set the {} env variable.",
            qt5_lib_path.display(), qtdir_variable);
        }
    }

    if cfg!(windows) {
        let mut qt5_lib_path = PathBuf::new();
        qt5_lib_path.push(env::var("QTDIR").unwrap_or(String::from("C:\\Qt\\5.7\\msvc2015_64")));

        if qt5_lib_path.exists() {
            env::set_var("CMAKE_PREFIX_PATH", &qt5_lib_path);

            qt5_lib_path.push("lib");

            println!("cargo:rustc-link-search=native={}\\system32",env::var("WINDIR").unwrap());
            println!("cargo:rustc-link-search=native={}",qt5_lib_path.display());

            println!("cargo:rustc-link-lib=dylib=Qt5Core");
            println!("cargo:rustc-link-lib=dylib=Qt5Gui");
            println!("cargo:rustc-link-lib=dylib=Qt5Qml");
            println!("cargo:rustc-link-lib=dylib=Qt5Quick");
            println!("cargo:rustc-link-lib=dylib=Qt5Svg");
            println!("cargo:rustc-link-lib=dylib=Qt5Widgets");
        } else {
            panic!("QT5 was not found at the expected location ({}) please install the SDK or set the QTDIR env variable.",
            qt5_lib_path.display());
        }
    } else {
        use pkg_config;

        if cfg!(any(target_os = "macos", target_os = "freebsd", target_os = "bitrig")) {
            println!("cargo:rustc-link-lib=dylib=c++");
        } else {
            println!("cargo:rustc-link-lib=dylib=stdc++");
        }

        match pkg_config::find_library("Qt5Core Qt5Gui Qt5Qml Qt5Quick Qt5Svg") {
            Ok(lib) => {
                for p in lib.link_paths { println!("cargo:rustc-link-search=native={}",p.display()); }
                for p in lib.libs { println!("cargo:rustc-link-lib=dylib={}",p); }
                if cfg!(target_os = "macos") {
                    for p in lib.framework_paths { println!("cargo:rustc-link-search=framework={}",p.display()); }
                    for p in lib.frameworks { println!("cargo:rustc-link-lib=framework={}",p); }
                }
                for p in lib.include_paths { println!("cargo:include={}",p.display()); }
            }
            Err(e) => panic!("QT5 was not found using pkg-config: {}",e)
        }
    }
}

fn main() {
    let mut cmake_cfg = cmake::Config::new("DOtherSide");
    let dos_path = PathBuf::from("DOtherSide").join("CMakeLists.txt");

    if !dos_path.exists() {
        panic!("DOtherSide submodule not checked out. Please run 'git submodule init' followed by 'git submodule update'.");
    }

    if let Ok(gen) = env::var("CMAKE_GENERATOR") {
        cmake_cfg.generator(gen);
    }

    find_qt5(&mut cmake_cfg);
    build_dos(&mut cmake_cfg);
}
<|endoftext|>


<commit_before>use std::env;
use std::process::Command;
use std::fs::File;
use std::io::Write;
use std::path::Path;

fn main() {
    dump_git_version();
}

/// Writes the current git hash to a file that is read by Way Cooler
///
/// If this is a release build, the file will be empty.
fn dump_git_version() {
    if let Some(git_version) = git_version() {
        let out_dir = env::var("OUT_DIR")
            .expect("Could not find out directory!");
        let dest_path = Path::new(&out_dir).join("git-version.txt");
        let mut f = File::create(&dest_path)
            .expect("Could not write git version to out directory");

        f.write_all(git_version.as_ref())
            .expect("Could not write to git version file");
    }
}

/// Gets the current hash of HEAD. Returns None if for some reason
/// that could not be retrieved (e.g not in a git repository)
fn git_version() -> Option<String> {
    Command::new("git")
        .arg("rev-parse")
        .arg("HEAD")
        .output()
        .ok()
        .map(|output| output.stdout)
        .map(|hash| String::from_utf8_lossy(&hash).trim().into())
}
<commit_msg>Only generate hash if commit not tagged<commit_after>use std::env;
use std::process::Command;
use std::fs::File;
use std::io::Write;
use std::path::Path;

fn main() {
    dump_git_version();
}

/// Writes the current git hash to a file that is read by Way Cooler
///
/// If this is a release build, the file will be empty.
fn dump_git_version() {
    let out_dir = env::var("OUT_DIR")
        .expect("Could not find out directory!");
    let dest_path = Path::new(&out_dir).join("git-version.txt");
    let mut f = File::create(&dest_path)
        .expect("Could not write git version to out directory");
    if let Some(git_version) = git_version() {
        f.write_all(git_version.as_ref())
            .expect("Could not write to git version file");
    }
}

/// Gets the current hash of HEAD. Returns None if for some reason
/// that could not be retrieved (e.g not in a git repository)
fn git_version() -> Option<String> {
    if !in_release_commit() {
        Command::new("git")
            .arg("rev-parse")
            .arg("HEAD")
            .output()
            .ok()
            .map(|output| output.stdout)
            .map(|hash| String::from_utf8_lossy(&hash).trim().into())
    } else {
        None
    }
}

/// Determines if the current HEAD is tagged with a release
fn in_release_commit() -> bool {
    let result = Command::new("git")
        .arg("describe")
        .arg("--exact-match")
        .arg("--tags")
        .arg("HEAD")
        .output().unwrap();
    result.status.success()
}
<|endoftext|>


<commit_before>use std::env;
use std::io::Write;

const CFG_KEY: &'static str = "py_sys_config";

#[cfg(feature = "python27-sys")]
const PYTHONSYS_ENV_VAR: &'static str = "DEP_PYTHON27_PYTHON_FLAGS";

#[cfg(feature = "python3-sys")]
const PYTHONSYS_ENV_VAR: &'static str = "DEP_PYTHON3_PYTHON_FLAGS";

fn main() {
    if cfg!(feature = "python27-sys") {
        if env::var_os("CARGO_FEATURE_PY_LINK_MODE_DEFAULT").is_some()
            || env::var_os("CARGO_FEATURE_PY_LINK_MODE_UNRESOLVED_STATIC").is_some()
        {
            writeln!(
                std::io::stderr(),
                "Cannot use link mode control with Python 2.7"
            );
            std::process::exit(1);
        }
    }

    // python{27,3.x}-sys/build.rs passes python interpreter compile flags via
    // environment variable (using the 'links' mechanism in the cargo.toml).
    let flags = match env::var(PYTHONSYS_ENV_VAR) {
        Ok(flags) => flags,
        Err(_) => {
            writeln!(
                std::io::stderr(),
                "Environment variable {} not found - this is supposed to be \
                 exported from the pythonXX-sys dependency, so the build chain is broken",
                PYTHONSYS_ENV_VAR
            )
            .unwrap();
            std::process::exit(1);
        }
    };

    if flags.len() > 0 {
        for f in flags.split(",") {
            // write out flags as --cfg so that the same #cfg blocks can be used
            // in rust-cpython as in the -sys libs
            let key_and_val: Vec<&str> = f.split("=").collect();
            let key = key_and_val[0];
            let val = key_and_val[1];
            if key.starts_with("FLAG") {
                println!("cargo:rustc-cfg={}=\"{}\"", CFG_KEY, &key[5..])
            } else {
                println!("cargo:rustc-cfg={}=\"{}_{}\"", CFG_KEY, &key[4..], val);
            }
        }
    }
}
<commit_msg>Fix warning in build.rs<commit_after>use std::env;
use std::io::Write;

const CFG_KEY: &'static str = "py_sys_config";

#[cfg(feature = "python27-sys")]
const PYTHONSYS_ENV_VAR: &'static str = "DEP_PYTHON27_PYTHON_FLAGS";

#[cfg(feature = "python3-sys")]
const PYTHONSYS_ENV_VAR: &'static str = "DEP_PYTHON3_PYTHON_FLAGS";

fn main() {
    if cfg!(feature = "python27-sys") {
        if env::var_os("CARGO_FEATURE_PY_LINK_MODE_DEFAULT").is_some()
            || env::var_os("CARGO_FEATURE_PY_LINK_MODE_UNRESOLVED_STATIC").is_some()
        {
            writeln!(
                std::io::stderr(),
                "Cannot use link mode control with Python 2.7"
            )
            .unwrap();
            std::process::exit(1);
        }
    }

    // python{27,3.x}-sys/build.rs passes python interpreter compile flags via
    // environment variable (using the 'links' mechanism in the cargo.toml).
    let flags = match env::var(PYTHONSYS_ENV_VAR) {
        Ok(flags) => flags,
        Err(_) => {
            writeln!(
                std::io::stderr(),
                "Environment variable {} not found - this is supposed to be \
                 exported from the pythonXX-sys dependency, so the build chain is broken",
                PYTHONSYS_ENV_VAR
            )
            .unwrap();
            std::process::exit(1);
        }
    };

    if flags.len() > 0 {
        for f in flags.split(",") {
            // write out flags as --cfg so that the same #cfg blocks can be used
            // in rust-cpython as in the -sys libs
            let key_and_val: Vec<&str> = f.split("=").collect();
            let key = key_and_val[0];
            let val = key_and_val[1];
            if key.starts_with("FLAG") {
                println!("cargo:rustc-cfg={}=\"{}\"", CFG_KEY, &key[5..])
            } else {
                println!("cargo:rustc-cfg={}=\"{}_{}\"", CFG_KEY, &key[4..], val);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::path::{Path, PathBuf};
use std::process;
use std::process::{Command, Stdio};
use std::fs;

fn main() {
    let target = env::var("TARGET").unwrap();
    if target.contains("android") {
        android_main()
    } else {
        println!("Android target supported only");
    }
}

fn android_main() {
    let ndk_path = env::var("ANDROID_NDK").ok().expect("Please set the ANDROID_NDK environment variable");
    let ndk_path = Path::new(&ndk_path);
    let sdk_path = env::var("ANDROID_SDK").ok().expect("Please set the ANDROID_SDK environment variable");
    let sdk_path = Path::new(&sdk_path);

    let target = env::var("TARGET").unwrap();
    let abi = if target.contains("armv7") {
        "armeabi-v7a"
    } else if target.contains("aarch64") {
        "arm64-v8a"
    } else if target.contains("arm") {
        "armeabi"
    } else if target.contains("x86") || target.contains("i686") {
        "x86"
    } else {
        panic!("Invalid target architecture {}", target);
    };

    if Command::new(ndk_path.join("ndk-build"))
        .arg(format!("APP_ABI={}", abi))
        .arg("-C")
        .arg("src/jni/")
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing ndk-build");
        process::exit(1)
    }

    let out_dir = env::var("OUT_DIR").ok().expect("Cargo should have set the OUT_DIR environment variable");

    if Command::new("cp")
        .arg(format!("src/obj/local/{}/libblurdroid.a", abi))
        .arg(&format!("{}", out_dir))
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing cp");
        process::exit(1)
    }

    if Command::new("mkdir")
        .arg("-p")
        .arg("target/java/classes/")
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing cp");
        process::exit(1)
    }

    let java_files = fs::read_dir("src/java/hu/uszeged/bluetooth").unwrap().map(|p| p.unwrap().path()).collect::<Vec<_>>();
    let java_files = java_files.iter().map(|p| p.as_os_str().to_str().unwrap()).collect::<Vec<_>>();

    if Command::new("javac")
        .arg("-d")
        .arg("target/java/classes/")
        .arg("-cp")
        .arg(find_android_platform(sdk_path))
        .args(java_files.as_slice())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing javac");
        process::exit(1)
    }

    if Command::new("jar")
        .arg("cvf")
        .arg(&format!("{}/blurdroid.jar", out_dir))
        .arg("-C")
        .arg("target/java/classes/")
        .arg("hu")
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing jar");
        process::exit(1)
    }

    println!("cargo:rustc-link-lib=static=blurdroid");
    println!("cargo:rustc-link-search=native={}", out_dir);
}

fn find_android_platform(sdk_path: &Path) -> PathBuf {
    // Sorted android platforms by priority
    let mut platforms = Vec::new();
    // Allow configuration using env variable
    if let Ok(platform) =  env::var("ANDROID_SDK_PLATFORM") {
        platforms.push(platform);
    }
    // Fallback to other platforms
    for v in (18..27).rev() {
        platforms.push(v.to_string());
    }

    for platfom in platforms {
        let path = sdk_path.join("platforms").join(format!("android-{}", platfom)).join("android.jar");
        if path.exists() {
            return path;
        }
    }

    panic!("Couldn't find a correct android SDK platform. Please set ANDROID_SDK_PLATFORM env variable");
}
<commit_msg>Set NDK_PROJECT_PATH and use absolute paths.<commit_after>use std::env;
use std::path::{Path, PathBuf};
use std::process;
use std::process::{Command, Stdio};
use std::fs;

fn main() {
    let target = env::var("TARGET").unwrap();
    if target.contains("android") {
        android_main()
    } else {
        println!("Android target supported only");
    }
}

fn android_main() {
    let ndk_path = env::var("ANDROID_NDK").ok().expect("Please set the ANDROID_NDK environment variable");
    let ndk_path = Path::new(&ndk_path);
    let sdk_path = env::var("ANDROID_SDK").ok().expect("Please set the ANDROID_SDK environment variable");
    let sdk_path = Path::new(&sdk_path);

    let target = env::var("TARGET").unwrap();
    let abi = if target.contains("armv7") {
        "armeabi-v7a"
    } else if target.contains("aarch64") {
        "arm64-v8a"
    } else if target.contains("arm") {
        "armeabi"
    } else if target.contains("x86") || target.contains("i686") {
        "x86"
    } else {
        panic!("Invalid target architecture {}", target);
    };

    let src_path = env::var("CARGO_MANIFEST_DIR").unwrap();

    if Command::new(ndk_path.join("ndk-build"))
        .arg(format!("APP_ABI={}", abi))
        .env("NDK_PROJECT_PATH", format!("{}/src", src_path))
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing ndk-build");
        process::exit(1)
    }

    let out_dir = env::var("OUT_DIR").ok().expect("Cargo should have set the OUT_DIR environment variable");

    if Command::new("cp")
        .arg(format!("{}/src/obj/local/{}/libblurdroid.a", src_path, abi))
        .arg(&format!("{}", out_dir))
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing cp");
        process::exit(1)
    }

    if Command::new("mkdir")
        .arg("-p")
        .arg(&format!("{}/target/java/classes/", out_dir))
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing cp");
        process::exit(1)
    }

    let java_files = fs::read_dir(format!("{}/src/java/hu/uszeged/bluetooth", src_path)).unwrap().map(|p| p.unwrap().path()).collect::<Vec<_>>();
    let java_files = java_files.iter().map(|p| p.as_os_str().to_str().unwrap()).collect::<Vec<_>>();

    if Command::new("javac")
        .arg("-d")
        .arg(&format!("{}/target/java/classes/", out_dir))
        .arg("-cp")
        .arg(find_android_platform(sdk_path))
        .args(java_files.as_slice())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing javac");
        process::exit(1)
    }

    if Command::new("jar")
        .arg("cvf")
        .arg(&format!("{}/blurdroid.jar", out_dir))
        .arg("-C")
        .arg(&format!("{}/target/java/classes/", out_dir))
        .arg("hu")
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing jar");
        process::exit(1)
    }

    println!("cargo:rustc-link-lib=static=blurdroid");
    println!("cargo:rustc-link-search=native={}", out_dir);
}

fn find_android_platform(sdk_path: &Path) -> PathBuf {
    // Sorted android platforms by priority
    let mut platforms = Vec::new();
    // Allow configuration using env variable
    if let Ok(platform) =  env::var("ANDROID_SDK_PLATFORM") {
        platforms.push(platform);
    }
    // Fallback to other platforms
    for v in (18..27).rev() {
        platforms.push(v.to_string());
    }

    for platfom in platforms {
        let path = sdk_path.join("platforms").join(format!("android-{}", platfom)).join("android.jar");
        if path.exists() {
            return path;
        }
    }

    panic!("Couldn't find a correct android SDK platform. Please set ANDROID_SDK_PLATFORM env variable");
}
<|endoftext|>


<commit_before>
fn main() {

}
<commit_msg>Avoid recompile when running `cargo test`<commit_after>
fn main() {
    println!("cargo:rerun-if-changed=src/");
    println!("cargo:rerun-if-changed=tests/");
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use common::config::load_es_config_for;
use futures::stream::StreamExt;
use mimir2::adapters::secondary::elasticsearch;
use mimir2::domain::ports::primary::list_documents::ListDocuments;
use mimir2::domain::ports::secondary::remote::Remote;
use mimirsbrunn::bano::Bano;
use mimirsbrunn::settings::bano2mimir as settings;
use places::addr::Addr;
use places::admin::Admin;
use slog_scope::{info, warn};
use snafu::{ResultExt, Snafu};
use std::sync::Arc;
use structopt::StructOpt;

#[derive(Debug, Snafu)]
pub enum Error {
    #[snafu(display("Settings (Configuration or CLI) Error: {}", source))]
    Settings { source: settings::Error },

    #[snafu(display("Elasticsearch Connection Pool {}", source))]
    ElasticsearchPool {
        source: elasticsearch::remote::Error,
    },

    #[snafu(display("Elasticsearch Connection Pool {}", source))]
    ElasticsearchConnection {
        source: mimir2::domain::ports::secondary::remote::Error,
    },

    #[snafu(display("Execution Error {}", source))]
    Execution { source: Box<dyn std::error::Error> },

    #[snafu(display("Configuration Error {}", source))]
    Configuration { source: common::config::Error },

    #[snafu(display("Import Error {}", source))]
    Import {
        source: mimirsbrunn::addr_reader::Error,
    },
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let opts = settings::Opts::from_args();
    match opts.cmd {
        settings::Command::Run => mimirsbrunn::utils::launch::wrapped_launch_async(Box::new(run))
            .await
            .context(Execution),
        settings::Command::Config => {
            mimirsbrunn::utils::launch::wrapped_launch_async(Box::new(config))
                .await
                .context(Execution)
        }
    }
}

async fn config(opts: settings::Opts) -> Result<(), Box<dyn std::error::Error>> {
    let settings = settings::Settings::new(&opts).map_err(Box::new)?;
    println!("{}", serde_json::to_string_pretty(&settings).unwrap());
    Ok(())
}

async fn run(opts: settings::Opts) -> Result<(), Box<dyn std::error::Error>> {
    info!("importing BANO into Mimir");
    let input = opts.input.clone(); // we save the input, because opts will be consumed by settings.

    let settings = &settings::Settings::new(&opts)
        .context(Settings)
        .map_err(Box::new)?;

    let pool = elasticsearch::remote::connection_pool_url(&settings.elasticsearch.url)
        .await
        .context(ElasticsearchPool)
        .map_err(Box::new)?;

    let client = pool
        .conn(
            settings.elasticsearch.timeout,
            &settings.elasticsearch.version_req,
        )
        .await
        .context(ElasticsearchConnection)
        .map_err(Box::new)?;

    // TODO There might be an opportunity for optimization here:
    // Lets say we're indexing a single bano department.... we don't need to retrieve
    // the admins for other regions!
    let into_addr = {
        let admins: Vec<Admin> = match client.list_documents().await {
            Ok(admins) => {
                admins
                    .map(|admin| admin.expect("could not parse admin"))
                    .collect()
                    .await
            }
            Err(err) => {
                warn!("administratives regions not found in es db. {:?}", err);
                Vec::new()
            }
        };

        let admins_by_insee = admins
            .iter()
            .cloned()
            .filter(|a| !a.insee.is_empty())
            .map(|mut a| {
                a.boundary = None; // to save some space we remove the admin boundary
                (a.insee.clone(), Arc::new(a))
            })
            .collect();

        let admins_geofinder = admins.into_iter().collect();
        move |b: Bano| b.into_addr(&admins_by_insee, &admins_geofinder)
    };

    let config = load_es_config_for::<Addr>(
        opts.settings
            .iter()
            .filter_map(|s| {
                if s.starts_with("elasticsearch.addr") {
                    Some(s.to_string())
                } else {
                    None
                }
            })
            .collect(),
        settings.container.dataset.clone(),
    )
    .context(Configuration)
    .map_err(Box::new)?;

    mimirsbrunn::addr_reader::import_addresses_from_input_path(&client, config, input, into_addr)
        .await
        .context(Import)
        .map_err(|err| Box::new(err) as Box<dyn snafu::Error>) // TODO Investigate why the need to cast?
}

// #[cfg(test)]
// mod tests {
//     use super::*;
//     use futures::TryStreamExt;
//     use mimir2::domain::ports::primary::list_documents::ListDocuments;
//     use mimir2::{adapters::secondary::elasticsearch::remote, utils::docker};
//     use places::addr::Addr;
//     use serial_test::serial;
//
//     fn elasticsearch_test_url() -> String {
//         std::env::var(elasticsearch::remote::ES_TEST_KEY).expect("env var")
//     }
//
//     #[tokio::test]
//     #[serial]
//     async fn should_correctly_index_bano_file() {
//         docker::initialize()
//             .await
//             .expect("elasticsearch docker initialization");
//
//         let args = Args {
//             input: Some("./tests/fixtures/sample-bano.csv".into()),
//             connection_string: elasticsearch_test_url(),
//             dataset: String::from("test"),
//             mappings: Some("./config/elasticsearch/addr/mappings.json".into()),
//             settings: Some("./config/elasticsearch/addr/settings.json".into()),
//             use_old_index_format: false,
//             nb_threads: 2,
//             nb_insert_threads: 2,
//             override_settings: vec![],
//         };
//
//         let _res = mimirsbrunn::utils::launch_async_args(run, args).await;
//
//         // Now we query the index we just created. Since it's a small cosmogony file with few entries,
//         // we'll just list all the documents in the index, and check them.
//         let pool = remote::connection_test_pool()
//             .await
//             .expect("Elasticsearch Connection Pool");
//
//         let client = pool
//             .conn(ES_DEFAULT_TIMEOUT, ES_DEFAULT_VERSION_REQ)
//             .await
//             .expect("Elasticsearch Connection Established");
//
//         let addresses: Vec<Addr> = client
//             .list_documents()
//             .await
//             .unwrap()
//             .try_collect()
//             .await
//             .unwrap();
//
//         assert_eq!(addresses.len(), 35);
//
//         let addr1 = addresses
//             .iter()
//             .find(|&addr| addr.name == "10 Place de la Mairie")
//             .unwrap();
//
//         assert_eq!(addr1.id, "addr:1.378886;43.668175:10");
//
//         let addr2 = addresses
//             .iter()
//             .find(|&addr| addr.name == "999 Rue Foncet")
//             .unwrap();
//
//         assert_eq!(addr2.zip_codes, vec!["06000", "06100", "06200", "06300"]);
//     }
// }
<commit_msg>Add simple unit test<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use common::config::load_es_config_for;
use futures::stream::StreamExt;
use mimir2::adapters::secondary::elasticsearch;
use mimir2::domain::ports::primary::list_documents::ListDocuments;
use mimir2::domain::ports::secondary::remote::Remote;
use mimirsbrunn::bano::Bano;
use mimirsbrunn::settings::bano2mimir as settings;
use places::addr::Addr;
use places::admin::Admin;
use slog_scope::{info, warn};
use snafu::{ResultExt, Snafu};
use std::sync::Arc;
use structopt::StructOpt;

#[derive(Debug, Snafu)]
pub enum Error {
    #[snafu(display("Settings (Configuration or CLI) Error: {}", source))]
    Settings { source: settings::Error },

    #[snafu(display("Elasticsearch Connection Pool {}", source))]
    ElasticsearchPool {
        source: elasticsearch::remote::Error,
    },

    #[snafu(display("Elasticsearch Connection Pool {}", source))]
    ElasticsearchConnection {
        source: mimir2::domain::ports::secondary::remote::Error,
    },

    #[snafu(display("Execution Error {}", source))]
    Execution { source: Box<dyn std::error::Error> },

    #[snafu(display("Configuration Error {}", source))]
    Configuration { source: common::config::Error },

    #[snafu(display("Import Error {}", source))]
    Import {
        source: mimirsbrunn::addr_reader::Error,
    },
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let opts = settings::Opts::from_args();
    match opts.cmd {
        settings::Command::Run => mimirsbrunn::utils::launch::wrapped_launch_async(Box::new(run))
            .await
            .context(Execution),
        settings::Command::Config => {
            mimirsbrunn::utils::launch::wrapped_launch_async(Box::new(config))
                .await
                .context(Execution)
        }
    }
}

async fn config(opts: settings::Opts) -> Result<(), Box<dyn std::error::Error>> {
    let settings = settings::Settings::new(&opts).map_err(Box::new)?;
    println!("{}", serde_json::to_string_pretty(&settings).unwrap());
    Ok(())
}

async fn run(opts: settings::Opts) -> Result<(), Box<dyn std::error::Error>> {
    info!("importing BANO into Mimir");
    let input = opts.input.clone(); // we save the input, because opts will be consumed by settings.

    let settings = &settings::Settings::new(&opts)
        .context(Settings)
        .map_err(Box::new)?;

    let pool = elasticsearch::remote::connection_pool_url(&settings.elasticsearch.url)
        .await
        .context(ElasticsearchPool)
        .map_err(Box::new)?;

    let client = pool
        .conn(
            settings.elasticsearch.timeout,
            &settings.elasticsearch.version_req,
        )
        .await
        .context(ElasticsearchConnection)
        .map_err(Box::new)?;

    // TODO There might be an opportunity for optimization here:
    // Lets say we're indexing a single bano department.... we don't need to retrieve
    // the admins for other regions!
    let into_addr = {
        let admins: Vec<Admin> = match client.list_documents().await {
            Ok(admins) => {
                admins
                    .map(|admin| admin.expect("could not parse admin"))
                    .collect()
                    .await
            }
            Err(err) => {
                warn!("administratives regions not found in es db. {:?}", err);
                Vec::new()
            }
        };

        let admins_by_insee = admins
            .iter()
            .cloned()
            .filter(|a| !a.insee.is_empty())
            .map(|mut a| {
                a.boundary = None; // to save some space we remove the admin boundary
                (a.insee.clone(), Arc::new(a))
            })
            .collect();

        let admins_geofinder = admins.into_iter().collect();
        move |b: Bano| b.into_addr(&admins_by_insee, &admins_geofinder)
    };

    let config = load_es_config_for::<Addr>(
        opts.settings
            .iter()
            .filter_map(|s| {
                if s.starts_with("elasticsearch.addr") {
                    Some(s.to_string())
                } else {
                    None
                }
            })
            .collect(),
        settings.container.dataset.clone(),
    )
    .context(Configuration)
    .map_err(Box::new)?;

    mimirsbrunn::addr_reader::import_addresses_from_input_path(&client, config, input, into_addr)
        .await
        .context(Import)
        .map_err(|err| Box::new(err) as Box<dyn snafu::Error>) // TODO Investigate why the need to cast?
}

#[cfg(test)]
mod tests {
    use super::*;
    use futures::TryStreamExt;
    use mimir2::domain::ports::primary::list_documents::ListDocuments;
    use mimir2::{adapters::secondary::elasticsearch::remote, utils::docker};
    use mimirsbrunn::settings::bano2mimir as settings;
    use places::addr::Addr;
    use serial_test::serial;

    #[tokio::test]
    #[serial]
    async fn should_correctly_index_bano_file() {
        docker::initialize()
            .await
            .expect("elasticsearch docker initialization");
        let opts = settings::Opts {
            config_dir: [env!("CARGO_MANIFEST_DIR"), "config"].iter().collect(),
            run_mode: Some("testing".to_string()),
            settings: vec![],
            input: [
                env!("CARGO_MANIFEST_DIR"),
                "tests",
                "fixtures",
                "sample-bano.csv",
            ]
            .iter()
            .collect(),
            cmd: settings::Command::Run,
        };

        let _res = mimirsbrunn::utils::launch::launch_async_args(run, opts).await;

        // Now we query the index we just created. Since it's a small cosmogony file with few entries,
        // we'll just list all the documents in the index, and check them.
        let config = docker::ConfigElasticsearchTesting::default();
        let pool = remote::connection_pool_url(&config.url)
            .await
            .expect("Elasticsearch Connection Pool");

        let client = pool
            .conn(config.timeout, &config.version_req)
            .await
            .expect("Elasticsearch Connection Established");

        let addresses: Vec<Addr> = client
            .list_documents()
            .await
            .unwrap()
            .try_collect()
            .await
            .unwrap();

        assert_eq!(addresses.len(), 35);

        let addr1 = addresses
            .iter()
            .find(|&addr| addr.name == "10 Place de la Mairie")
            .unwrap();

        assert_eq!(addr1.id, "addr:1.378886;43.668175:10");

        let addr2 = addresses
            .iter()
            .find(|&addr| addr.name == "999 Rue Foncet")
            .unwrap();

        assert_eq!(addr2.zip_codes, vec!["06000", "06100", "06200", "06300"]);
    }
}
<|endoftext|>


<commit_before>use assembler::label_parsers::label_usage;
use assembler::register_parsers::register;
use assembler::Token;
use nom::digit;
use nom::types::CompleteStr;

/// Parser for all numbers, which have to be prefaced with `#` in our assembly language:
/// #100
named!(integer_operand<CompleteStr, Token>,
    ws!(
        do_parse!(
            tag!("#") >>
            sign: opt!(tag!("-")) >>
            reg_num: digit >>
            (
                {
                    let mut tmp = String::from("");
                    if sign.is_some() {
                        tmp.push_str("-");
                    }
                    tmp.push_str(&reg_num.to_string());
                    Token::IntegerOperand{value: reg_num.parse::<i32>().unwrap()}
                }
            )
        )
    )
);

named!(float_operand<CompleteStr, Token>,
    ws!(
        do_parse!(
            tag!("#") >>
            sign: opt!(tag!("-")) >>
            left_nums: digit >>
            tag!(".") >>
            right_nums: digit >>
            (
                {
                    let mut tmp = String::from("");
                    if sign.is_some() {
                        tmp.push_str("-");
                    }
                    tmp.push_str(&left_nums.to_string());
                    tmp.push_str(".");
                    tmp.push_str(&right_nums.to_string());
                    Token::FloatOperand{value: tmp.parse::<f64>().unwrap()}
                }
            )
        )
    )
);

named!(irstring<CompleteStr, Token>,
    do_parse!(
        tag!("'") >>
        content: take_until!("'") >>
        tag!("'") >>
        (
            Token::IrString{ name: content.to_string() }
        )
    )
);

named!(pub operand<CompleteStr, Token>,
    alt!(
        integer_operand |
        float_operand |
        label_usage |
        register |
        irstring
    )
);

mod tests {
    #![allow(unused_imports)]

    use assembler::Token;
    use nom::types::CompleteStr;
    use super::{float_operand, integer_operand, irstring};

    #[test]
    fn test_parse_integer_operand() {
        let result = integer_operand(CompleteStr("#10"));
        assert_eq!(result.is_ok(), true);
        let (rest, value) = result.unwrap();
        assert_eq!(rest, CompleteStr(""));
        assert_eq!(value, Token::IntegerOperand { value: 10 });
        let result = integer_operand(CompleteStr("10"));
        assert_eq!(result.is_ok(), false);
    }

    #[test]
    fn test_parse_string_operand() {
        let result = irstring(CompleteStr("'This is a test'"));
        assert_eq!(result.is_ok(), true);
    }

    #[test]
    fn test_parse_float_operand() {
        let test = vec!["#100.3", "#-100.3", "#1.0", "#0.0"];
        for i in &test {
            assert_eq!(float_operand(CompleteStr(i)).is_ok(), true);
        }
    }
}
<commit_msg>Fixed a comment<commit_after>use assembler::label_parsers::label_usage;
use assembler::register_parsers::register;
use assembler::Token;
use nom::digit;
use nom::types::CompleteStr;

/// Parser for all numbers, which have to be prefaced with `#` in our assembly language:
/// #100
named!(integer_operand<CompleteStr, Token>,
    ws!(
        do_parse!(
            tag!("#") >>
            sign: opt!(tag!("-")) >>
            reg_num: digit >>
            (
                {
                    let mut tmp = String::from("");
                    if sign.is_some() {
                        tmp.push_str("-");
                    }
                    tmp.push_str(&reg_num.to_string());
                    Token::IntegerOperand{value: reg_num.parse::<i32>().unwrap()}
                }
            )
        )
    )
);

/// Parser for all floats, which have to be prefaced with `#` in our assembly language:
/// #100.0
named!(float_operand<CompleteStr, Token>,
    ws!(
        do_parse!(
            tag!("#") >>
            sign: opt!(tag!("-")) >>
            left_nums: digit >>
            tag!(".") >>
            right_nums: digit >>
            (
                {
                    let mut tmp = String::from("");
                    if sign.is_some() {
                        tmp.push_str("-");
                    }
                    tmp.push_str(&left_nums.to_string());
                    tmp.push_str(".");
                    tmp.push_str(&right_nums.to_string());
                    Token::FloatOperand{value: tmp.parse::<f64>().unwrap()}
                }
            )
        )
    )
);

named!(irstring<CompleteStr, Token>,
    do_parse!(
        tag!("'") >>
        content: take_until!("'") >>
        tag!("'") >>
        (
            Token::IrString{ name: content.to_string() }
        )
    )
);

named!(pub operand<CompleteStr, Token>,
    alt!(
        integer_operand |
        float_operand |
        label_usage |
        register |
        irstring
    )
);

mod tests {
    #![allow(unused_imports)]

    use assembler::Token;
    use nom::types::CompleteStr;
    use super::{float_operand, integer_operand, irstring};

    #[test]
    fn test_parse_integer_operand() {
        let result = integer_operand(CompleteStr("#10"));
        assert_eq!(result.is_ok(), true);
        let (rest, value) = result.unwrap();
        assert_eq!(rest, CompleteStr(""));
        assert_eq!(value, Token::IntegerOperand { value: 10 });
        let result = integer_operand(CompleteStr("10"));
        assert_eq!(result.is_ok(), false);
    }

    #[test]
    fn test_parse_string_operand() {
        let result = irstring(CompleteStr("'This is a test'"));
        assert_eq!(result.is_ok(), true);
    }

    #[test]
    fn test_parse_float_operand() {
        let test = vec!["#100.3", "#-100.3", "#1.0", "#0.0"];
        for i in &test {
            assert_eq!(float_operand(CompleteStr(i)).is_ok(), true);
        }
    }
}
<|endoftext|>


<commit_before>//! Endpoints for server-side key backups.

pub mod add_backup_keys;
pub mod create_backup;
pub mod get_backup;
pub mod get_backup_keys;
pub mod get_latest_backup;
pub mod update_backup;

use js_int::UInt;
use ruma_identifiers::{DeviceKeyId, UserId};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

// TODO: remove
/// A wrapper around a mapping of session IDs to key data.
#[cfg(feature = "unstable-synapse-quirks")]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Sessions {
    ///  A map of session IDs to key data.
    pub sessions: BTreeMap<String, KeyData>,
}

/// The algorithm used for storing backups.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(tag = "algorithm", content = "auth_data")]
pub enum BackupAlgorithm {
    /// `m.megolm_backup.v1.curve25519-aes-sha2` backup algorithm.
    #[serde(rename = "m.megolm_backup.v1.curve25519-aes-sha2")]
    MegolmBackupV1Curve25519AesSha2 {
        /// The curve25519 public key used to encrypt the backups, encoded in unpadded base64.
        public_key: String,
        /// Signatures of the auth_data as Signed JSON.
        signatures: BTreeMap<UserId, BTreeMap<DeviceKeyId, String>>,
    },
}

/// The key data.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct KeyData {
    /// The index of the first message in the session that the key can decrypt.
    first_message_index: UInt,
    /// The number of times this key has been forwarded via key-sharing between devices.
    forwarded_count: UInt,
    /// Whether the device backing up the key verified the device that the key is from.
    is_verified: bool,
    /// Data about the session.
    session_data: SessionData,
}

/// The algorithm used for storing backups.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SessionData {
    /// Unpadded base64-encoded public half of the ephemeral key.
    ephemeral: String,
    /// Ciphertext, encrypted using AES-CBC-256 with PKCS#7 padding, encoded in base64.
    ciphertext: String,
    /// First 8 bytes of MAC key, encoded in base64.
    mac: String,
}
<commit_msg>Make accidentally private fields public<commit_after>//! Endpoints for server-side key backups.

pub mod add_backup_keys;
pub mod create_backup;
pub mod get_backup;
pub mod get_backup_keys;
pub mod get_latest_backup;
pub mod update_backup;

use js_int::UInt;
use ruma_identifiers::{DeviceKeyId, UserId};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

// TODO: remove
/// A wrapper around a mapping of session IDs to key data.
#[cfg(feature = "unstable-synapse-quirks")]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Sessions {
    ///  A map of session IDs to key data.
    pub sessions: BTreeMap<String, KeyData>,
}

/// The algorithm used for storing backups.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(tag = "algorithm", content = "auth_data")]
pub enum BackupAlgorithm {
    /// `m.megolm_backup.v1.curve25519-aes-sha2` backup algorithm.
    #[serde(rename = "m.megolm_backup.v1.curve25519-aes-sha2")]
    MegolmBackupV1Curve25519AesSha2 {
        /// The curve25519 public key used to encrypt the backups, encoded in unpadded base64.
        public_key: String,
        /// Signatures of the auth_data as Signed JSON.
        signatures: BTreeMap<UserId, BTreeMap<DeviceKeyId, String>>,
    },
}

/// The key data.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct KeyData {
    /// The index of the first message in the session that the key can decrypt.
    pub first_message_index: UInt,
    /// The number of times this key has been forwarded via key-sharing between devices.
    pub forwarded_count: UInt,
    /// Whether the device backing up the key verified the device that the key is from.
    pub is_verified: bool,
    /// Data about the session.
    pub session_data: SessionData,
}

/// The algorithm used for storing backups.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SessionData {
    /// Unpadded base64-encoded public half of the ephemeral key.
    pub ephemeral: String,
    /// Ciphertext, encrypted using AES-CBC-256 with PKCS#7 padding, encoded in base64.
    pub ciphertext: String,
    /// First 8 bytes of MAC key, encoded in base64.
    pub mac: String,
}
<|endoftext|>


<commit_before>use clap::{App, AppSettings, Arg, SubCommand};

pub fn build_cli() -> App<'static, 'static> {
    let database_arg = Arg::with_name("DATABASE_URL")
        .long("database-url")
        .help("Specifies the database URL to connect to. Falls back to \
               the DATABASE_URL environment variable if unspecified.")
        .global(true)
        .takes_value(true);

    let migration_subcommand = SubCommand::with_name("migration")
        .about("A group of commands for generating, running, and reverting \
                migrations.")
        .setting(AppSettings::VersionlessSubcommands)
        .arg(Arg::with_name("MIGRATION_DIRECTORY")
            .long("migration-dir")
            .help("The location of your migration directory. By default this \
                   will look for a directory called `migrations` in the \
                   current directory and its parents.")
            .takes_value(true)
            .global(true)
        ).subcommand(SubCommand::with_name("run")
            .about("Runs all pending migrations")
        ).subcommand(SubCommand::with_name("revert")
            .about("Reverts the latest run migration")
        ).subcommand(SubCommand::with_name("redo")
            .about("Reverts and re-runs the latest migration. Useful \
                    for testing that a migration can in fact be reverted.")
        ).subcommand(SubCommand::with_name("generate")
            .about("Generate a new migration with the given name, and \
                    the current timestamp as the version"
             ).arg(Arg::with_name("MIGRATION_NAME")
                 .help("The name of the migration to create")
                 .required(true)
             ).arg(Arg::with_name("MIGRATION_VERSION")
                 .long("version")
                 .help("The version number to use when generating the migration. \
                        Defaults to the current timestamp, which should suffice \
                        for most use cases.")
                 .takes_value(true)
            )
        ).setting(AppSettings::SubcommandRequiredElseHelp);

    let setup_subcommand = SubCommand::with_name("setup")
        .about("Creates the migrations directory, creates the database \
                specified in your DATABASE_URL, and runs existing migrations.");

    let database_subcommand = SubCommand::with_name("database")
        .about("A group of commands for setting up and resetting your database.")
        .setting(AppSettings::VersionlessSubcommands)
        .subcommand(SubCommand::with_name("setup")
            .about("Creates the database specified in your DATABASE_URL, \
                    and then runs any existing migrations.")
        ).subcommand(SubCommand::with_name("reset")
            .about("Resets your database by dropping the database specified \
                    in your DATABASE_URL and then running `diesel database setup`.")
        ).subcommand(SubCommand::with_name("drop")
            .about("Drops the database specified in your DATABASE_URL.")
            .setting(AppSettings::Hidden)
        ).setting(AppSettings::SubcommandRequiredElseHelp);

    let generate_bash_completion_subcommand = SubCommand::with_name("bash-completion")
        .about("Generate bash completion script for the diesel command.");

    let infer_schema_subcommand = SubCommand::with_name("print-schema")
        .setting(AppSettings::VersionlessSubcommands)
        .about("Print table definitions for database schema.")
        .arg(Arg::with_name("schema")
             .long("schema")
             .short("s")
             .takes_value(true)
             .help("The name of the schema."))
        .arg(Arg::with_name("table-name")
             .index(1)
             .takes_value(true)
             .multiple(true)
             .help("Table names to filter (default whitelist if not empty)"))
        .arg(Arg::with_name("whitelist")
             .short("w")
             .long("whitelist")
             .help("Use table list as whitelist")
             .conflicts_with("blacklist"))
        .arg(Arg::with_name("blacklist")
             .short("b")
             .long("blacklist")
             .help("Use table list as blacklist")
             .conflicts_with("whitelist"));

    App::new("diesel")
        .version(env!("CARGO_PKG_VERSION"))
        .setting(AppSettings::VersionlessSubcommands)
        .after_help("You can also run `diesel SUBCOMMAND -h` to get more information about that subcommand.")
        .arg(database_arg)
        .subcommand(migration_subcommand)
        .subcommand(setup_subcommand)
        .subcommand(database_subcommand)
        .subcommand(generate_bash_completion_subcommand)
        .subcommand(infer_schema_subcommand)
        .setting(AppSettings::SubcommandRequiredElseHelp)
}
<commit_msg>cli: Add "db" as alias for "database" subcommand<commit_after>use clap::{App, AppSettings, Arg, SubCommand};

pub fn build_cli() -> App<'static, 'static> {
    let database_arg = Arg::with_name("DATABASE_URL")
        .long("database-url")
        .help("Specifies the database URL to connect to. Falls back to \
               the DATABASE_URL environment variable if unspecified.")
        .global(true)
        .takes_value(true);

    let migration_subcommand = SubCommand::with_name("migration")
        .about("A group of commands for generating, running, and reverting \
                migrations.")
        .setting(AppSettings::VersionlessSubcommands)
        .arg(Arg::with_name("MIGRATION_DIRECTORY")
            .long("migration-dir")
            .help("The location of your migration directory. By default this \
                   will look for a directory called `migrations` in the \
                   current directory and its parents.")
            .takes_value(true)
            .global(true)
        ).subcommand(SubCommand::with_name("run")
            .about("Runs all pending migrations")
        ).subcommand(SubCommand::with_name("revert")
            .about("Reverts the latest run migration")
        ).subcommand(SubCommand::with_name("redo")
            .about("Reverts and re-runs the latest migration. Useful \
                    for testing that a migration can in fact be reverted.")
        ).subcommand(SubCommand::with_name("generate")
            .about("Generate a new migration with the given name, and \
                    the current timestamp as the version"
             ).arg(Arg::with_name("MIGRATION_NAME")
                 .help("The name of the migration to create")
                 .required(true)
             ).arg(Arg::with_name("MIGRATION_VERSION")
                 .long("version")
                 .help("The version number to use when generating the migration. \
                        Defaults to the current timestamp, which should suffice \
                        for most use cases.")
                 .takes_value(true)
            )
        ).setting(AppSettings::SubcommandRequiredElseHelp);

    let setup_subcommand = SubCommand::with_name("setup")
        .about("Creates the migrations directory, creates the database \
                specified in your DATABASE_URL, and runs existing migrations.");

    let database_subcommand = SubCommand::with_name("database")
        .alias("db")
        .about("A group of commands for setting up and resetting your database.")
        .setting(AppSettings::VersionlessSubcommands)
        .subcommand(SubCommand::with_name("setup")
            .about("Creates the database specified in your DATABASE_URL, \
                    and then runs any existing migrations.")
        ).subcommand(SubCommand::with_name("reset")
            .about("Resets your database by dropping the database specified \
                    in your DATABASE_URL and then running `diesel database setup`.")
        ).subcommand(SubCommand::with_name("drop")
            .about("Drops the database specified in your DATABASE_URL.")
            .setting(AppSettings::Hidden)
        ).setting(AppSettings::SubcommandRequiredElseHelp);

    let generate_bash_completion_subcommand = SubCommand::with_name("bash-completion")
        .about("Generate bash completion script for the diesel command.");

    let infer_schema_subcommand = SubCommand::with_name("print-schema")
        .setting(AppSettings::VersionlessSubcommands)
        .about("Print table definitions for database schema.")
        .arg(Arg::with_name("schema")
             .long("schema")
             .short("s")
             .takes_value(true)
             .help("The name of the schema."))
        .arg(Arg::with_name("table-name")
             .index(1)
             .takes_value(true)
             .multiple(true)
             .help("Table names to filter (default whitelist if not empty)"))
        .arg(Arg::with_name("whitelist")
             .short("w")
             .long("whitelist")
             .help("Use table list as whitelist")
             .conflicts_with("blacklist"))
        .arg(Arg::with_name("blacklist")
             .short("b")
             .long("blacklist")
             .help("Use table list as blacklist")
             .conflicts_with("whitelist"));

    App::new("diesel")
        .version(env!("CARGO_PKG_VERSION"))
        .setting(AppSettings::VersionlessSubcommands)
        .after_help("You can also run `diesel SUBCOMMAND -h` to get more information about that subcommand.")
        .arg(database_arg)
        .subcommand(migration_subcommand)
        .subcommand(setup_subcommand)
        .subcommand(database_subcommand)
        .subcommand(generate_bash_completion_subcommand)
        .subcommand(infer_schema_subcommand)
        .setting(AppSettings::SubcommandRequiredElseHelp)
}
<|endoftext|>


<commit_before><commit_msg>Clean up, example and Readme edit<commit_after><|endoftext|>


<commit_before>//! general purpose combinators

#![allow(unused_imports)]

#[cfg(feature = "alloc")]
use lib::std::boxed::Box;

#[cfg(feature = "std")]
use lib::std::fmt::Debug;
use internal::*;
use error::ParseError;
use traits::{AsChar, InputIter, InputLength, InputTakeAtPosition};
use traits::{need_more, need_more_err, AtEof, ParseTo};
use lib::std::ops::{Range, RangeFrom, RangeTo};
use traits::{Compare, CompareResult, Offset, Slice};
use error::ErrorKind;
use lib::std::mem::transmute;

#[macro_use]
mod macros;

#[cfg(feature = "alloc")]
#[inline]
pub fn tag_cl<'a, 'b>(rec: &'a [u8]) -> Box<Fn(&'b [u8]) -> IResult<&'b [u8], &'b [u8]> + 'a> {
  Box::new(move |i: &'b [u8]| -> IResult<&'b [u8], &'b [u8]> {
    if i.len() >= rec.len() && &i[0..rec.len()] == rec {
      Ok((&i[rec.len()..], &i[0..rec.len()]))
    } else {
      let e: ErrorKind = ErrorKind::TagClosure;
      Err(Err::Error(error_position!(i, e)))
    }
  })
}

#[cfg(feature = "std")]
#[inline]
pub fn print<T: Debug>(input: T) -> IResult<T, ()> {
  println!("{:?}", input);
  Ok((input, ()))
}

#[inline]
pub fn begin(input: &[u8]) -> IResult<(), &[u8]> {
  Ok(((), input))
}

pub fn sized_buffer<'a, E: ParseError<&'a[u8]>>(input: &'a[u8]) -> IResult<&'a[u8], &'a[u8], E> {
  if input.is_empty() {
    return need_more(input, Needed::Unknown);
  }

  let len = input[0] as usize;

  if input.len() >= len + 1 {
    Ok((&input[len + 1..], &input[1..len + 1]))
  } else {
    need_more(input, Needed::Size(1 + len))
  }
}

/// Recognizes non empty buffers
#[inline]
pub fn non_empty<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength + AtEof,
{
  if input.input_len() == 0 {
    return need_more_err(input, Needed::Unknown, ErrorKind::NonEmpty);
  } else {
    Ok((input.slice(input.input_len()..), input))
  }
}

/// Return the remaining input.
#[inline]
pub fn rest<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength,
{
  Ok((input.slice(input.input_len()..), input))
}

/// Return the length of the remaining input.
#[inline]
pub fn rest_len<T, E: ParseError<T>>(input: T) -> IResult<T, usize, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength,
{
  let len = input.input_len();
  Ok((input, len))
}

/// Return the remaining input, for strings.
#[inline]
pub fn rest_s<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, &'a str, E> {
  Ok((&input[input.len()..], input))
}

pub fn map<I, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> O2,
{
  move |input: I| {
    let (input, o1) = first(input)?;
    Ok((input, second(o1)))
  }
}

pub fn map_res<I: Clone, O1, O2, E: ParseError<I>, E2, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> Result<O2, E2>,
{
  move |input: I| {
    let i = input.clone();
    let (input, o1) = first(input)?;
    match second(o1) {
      Ok(o2) => Ok((input, o2)),
      Err(_) => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapRes))),
    }
  }
}

pub fn flat_map<I, O1, O2, E: ParseError<I>, F, G, H>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> H,
  H: Fn(I) -> IResult<I, O2, E>
{
  move |input: I| {
    let (input, o1) = first(input)?;
    second(o1)(input)
  }
}

pub fn opt<I:Clone, O, E: ParseError<I>, F>(f: F) -> impl Fn(I) -> IResult<I, Option<O>, E>
where
  F: Fn(I) -> IResult<I, O, E>,
{
  move |input: I| {
    let i = input.clone();
    match f(input) {
      Ok((i, o)) => Ok((i, Some(o))),
      Err(Err::Error(_)) => Ok((i, None)),
      Err(e) => Err(e),
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use internal::{Err, IResult, Needed};
  use error::ParseError;

  macro_rules! assert_parse(
    ($left: expr, $right: expr) => {
      let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
      assert_eq!(res, $right);
    };
  );

  #[test]
  #[cfg(feature = "alloc")]
  fn tag_closure() {
    let x = tag_cl(&b"abcd"[..]);
    let r = x(&b"abcdabcdefgh"[..]);
    assert_eq!(r, Ok((&b"abcdefgh"[..], &b"abcd"[..])));

    let r2 = x(&b"abcefgh"[..]);
    assert_eq!(
      r2,
      Err(Err::Error(error_position!(
        &b"abcefgh"[..],
        ErrorKind::TagClosure
      ),))
    );
  }

  #[test]
  #[cfg(feature = "alloc")]
  fn buffer_with_size() {
    use lib::std::vec::Vec;
    let i: Vec<u8> = vec![7, 8];
    let o: Vec<u8> = vec![4, 5, 6];
    //let arr:[u8; 6usize] = [3, 4, 5, 6, 7, 8];
    let arr: [u8; 6usize] = [3, 4, 5, 6, 7, 8];
    let res = sized_buffer::<(_, ErrorKind)>(&arr[..]);
    assert_eq!(res, Ok((&i[..], &o[..])))
  }

  /*#[test]
  fn t1() {
    let v1:Vec<u8> = vec![1,2,3];
    let v2:Vec<u8> = vec![4,5,6];
    let d = Ok((&v1[..], &v2[..]));
    let res = d.flat_map(print);
    assert_eq!(res, Ok((&v2[..], ())));
  }*/

  /*
    #[test]
    fn end_of_input() {
        let not_over = &b"Hello, world!"[..];
        let is_over = &b""[..];
        named!(eof_test, eof!());

        let res_not_over = eof_test(not_over);
        assert_eq!(res_not_over, Err(Err::Error(error_position!(not_over, ErrorKind::Eof))));

        let res_over = eof_test(is_over);
        assert_eq!(res_over, Ok((is_over, is_over)));
    }
    */

  #[test]
  fn rest_on_slices() {
    let input: &[u8] = &b"Hello, world!"[..];
    let empty: &[u8] = &b""[..];
    assert_parse!(rest(input), Ok((empty, input)));
  }

  #[test]
  fn rest_on_strs() {
    let input: &str = "Hello, world!";
    let empty: &str = "";
    assert_parse!(rest(input), Ok((empty, input)));
  }

  #[test]
  fn rest_len_on_slices() {
    let input: &[u8] = &b"Hello, world!"[..];
    assert_parse!(rest_len(input), Ok((input, input.len())));
  }

  use lib::std::convert::From;
  impl From<u32> for CustomError {
    fn from(_: u32) -> Self {
      CustomError
    }
  }

  impl<I> ParseError<I> for CustomError {
    fn from_error_kind(_: I, _: ErrorKind) -> Self {
      CustomError
    }

    fn append(_: I, _: ErrorKind, _: CustomError) -> Self {
      CustomError
    }
  }

  struct CustomError;
  #[allow(dead_code)]
  fn custom_error(input: &[u8]) -> IResult<&[u8], &[u8], CustomError> {
    //fix_error!(input, CustomError, alphanumeric)
    ::character::streaming::alphanumeric(input)
  }

}
<commit_msg>add map_opt combinator<commit_after>//! general purpose combinators

#![allow(unused_imports)]

#[cfg(feature = "alloc")]
use lib::std::boxed::Box;

#[cfg(feature = "std")]
use lib::std::fmt::Debug;
use internal::*;
use error::ParseError;
use traits::{AsChar, InputIter, InputLength, InputTakeAtPosition};
use traits::{need_more, need_more_err, AtEof, ParseTo};
use lib::std::ops::{Range, RangeFrom, RangeTo};
use traits::{Compare, CompareResult, Offset, Slice};
use error::ErrorKind;
use lib::std::mem::transmute;

#[macro_use]
mod macros;

#[cfg(feature = "alloc")]
#[inline]
pub fn tag_cl<'a, 'b>(rec: &'a [u8]) -> Box<Fn(&'b [u8]) -> IResult<&'b [u8], &'b [u8]> + 'a> {
  Box::new(move |i: &'b [u8]| -> IResult<&'b [u8], &'b [u8]> {
    if i.len() >= rec.len() && &i[0..rec.len()] == rec {
      Ok((&i[rec.len()..], &i[0..rec.len()]))
    } else {
      let e: ErrorKind = ErrorKind::TagClosure;
      Err(Err::Error(error_position!(i, e)))
    }
  })
}

#[cfg(feature = "std")]
#[inline]
pub fn print<T: Debug>(input: T) -> IResult<T, ()> {
  println!("{:?}", input);
  Ok((input, ()))
}

#[inline]
pub fn begin(input: &[u8]) -> IResult<(), &[u8]> {
  Ok(((), input))
}

pub fn sized_buffer<'a, E: ParseError<&'a[u8]>>(input: &'a[u8]) -> IResult<&'a[u8], &'a[u8], E> {
  if input.is_empty() {
    return need_more(input, Needed::Unknown);
  }

  let len = input[0] as usize;

  if input.len() >= len + 1 {
    Ok((&input[len + 1..], &input[1..len + 1]))
  } else {
    need_more(input, Needed::Size(1 + len))
  }
}

/// Recognizes non empty buffers
#[inline]
pub fn non_empty<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength + AtEof,
{
  if input.input_len() == 0 {
    return need_more_err(input, Needed::Unknown, ErrorKind::NonEmpty);
  } else {
    Ok((input.slice(input.input_len()..), input))
  }
}

/// Return the remaining input.
#[inline]
pub fn rest<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength,
{
  Ok((input.slice(input.input_len()..), input))
}

/// Return the length of the remaining input.
#[inline]
pub fn rest_len<T, E: ParseError<T>>(input: T) -> IResult<T, usize, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength,
{
  let len = input.input_len();
  Ok((input, len))
}

/// Return the remaining input, for strings.
#[inline]
pub fn rest_s<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, &'a str, E> {
  Ok((&input[input.len()..], input))
}

pub fn map<I, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> O2,
{
  move |input: I| {
    let (input, o1) = first(input)?;
    Ok((input, second(o1)))
  }
}

pub fn map_res<I: Clone, O1, O2, E: ParseError<I>, E2, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> Result<O2, E2>,
{
  move |input: I| {
    let i = input.clone();
    let (input, o1) = first(input)?;
    match second(o1) {
      Ok(o2) => Ok((input, o2)),
      Err(_) => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapRes))),
    }
  }
}

pub fn map_opt<I: Clone, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> Option<O2>,
{
  move |input: I| {
    let i = input.clone();
    let (input, o1) = first(input)?;
    match second(o1) {
      Some(o2) => Ok((input, o2)),
      None => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapOpt))),
    }
  }
}

pub fn flat_map<I, O1, O2, E: ParseError<I>, F, G, H>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> H,
  H: Fn(I) -> IResult<I, O2, E>
{
  move |input: I| {
    let (input, o1) = first(input)?;
    second(o1)(input)
  }
}

pub fn opt<I:Clone, O, E: ParseError<I>, F>(f: F) -> impl Fn(I) -> IResult<I, Option<O>, E>
where
  F: Fn(I) -> IResult<I, O, E>,
{
  move |input: I| {
    let i = input.clone();
    match f(input) {
      Ok((i, o)) => Ok((i, Some(o))),
      Err(Err::Error(_)) => Ok((i, None)),
      Err(e) => Err(e),
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use internal::{Err, IResult, Needed};
  use error::ParseError;

  macro_rules! assert_parse(
    ($left: expr, $right: expr) => {
      let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
      assert_eq!(res, $right);
    };
  );

  #[test]
  #[cfg(feature = "alloc")]
  fn tag_closure() {
    let x = tag_cl(&b"abcd"[..]);
    let r = x(&b"abcdabcdefgh"[..]);
    assert_eq!(r, Ok((&b"abcdefgh"[..], &b"abcd"[..])));

    let r2 = x(&b"abcefgh"[..]);
    assert_eq!(
      r2,
      Err(Err::Error(error_position!(
        &b"abcefgh"[..],
        ErrorKind::TagClosure
      ),))
    );
  }

  #[test]
  #[cfg(feature = "alloc")]
  fn buffer_with_size() {
    use lib::std::vec::Vec;
    let i: Vec<u8> = vec![7, 8];
    let o: Vec<u8> = vec![4, 5, 6];
    //let arr:[u8; 6usize] = [3, 4, 5, 6, 7, 8];
    let arr: [u8; 6usize] = [3, 4, 5, 6, 7, 8];
    let res = sized_buffer::<(_, ErrorKind)>(&arr[..]);
    assert_eq!(res, Ok((&i[..], &o[..])))
  }

  /*#[test]
  fn t1() {
    let v1:Vec<u8> = vec![1,2,3];
    let v2:Vec<u8> = vec![4,5,6];
    let d = Ok((&v1[..], &v2[..]));
    let res = d.flat_map(print);
    assert_eq!(res, Ok((&v2[..], ())));
  }*/

  /*
    #[test]
    fn end_of_input() {
        let not_over = &b"Hello, world!"[..];
        let is_over = &b""[..];
        named!(eof_test, eof!());

        let res_not_over = eof_test(not_over);
        assert_eq!(res_not_over, Err(Err::Error(error_position!(not_over, ErrorKind::Eof))));

        let res_over = eof_test(is_over);
        assert_eq!(res_over, Ok((is_over, is_over)));
    }
    */

  #[test]
  fn rest_on_slices() {
    let input: &[u8] = &b"Hello, world!"[..];
    let empty: &[u8] = &b""[..];
    assert_parse!(rest(input), Ok((empty, input)));
  }

  #[test]
  fn rest_on_strs() {
    let input: &str = "Hello, world!";
    let empty: &str = "";
    assert_parse!(rest(input), Ok((empty, input)));
  }

  #[test]
  fn rest_len_on_slices() {
    let input: &[u8] = &b"Hello, world!"[..];
    assert_parse!(rest_len(input), Ok((input, input.len())));
  }

  use lib::std::convert::From;
  impl From<u32> for CustomError {
    fn from(_: u32) -> Self {
      CustomError
    }
  }

  impl<I> ParseError<I> for CustomError {
    fn from_error_kind(_: I, _: ErrorKind) -> Self {
      CustomError
    }

    fn append(_: I, _: ErrorKind, _: CustomError) -> Self {
      CustomError
    }
  }

  struct CustomError;
  #[allow(dead_code)]
  fn custom_error(input: &[u8]) -> IResult<&[u8], &[u8], CustomError> {
    //fix_error!(input, CustomError, alphanumeric)
    ::character::streaming::alphanumeric(input)
  }

}
<|endoftext|>