<commit_before>use std::f64;
use std::cmp::min;
use std::num::Float;
use std::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
use elem;
use elem::Molecule;
use error::{CTResult, CTError};
use error::CTErrorKind::InputError;

macro_rules! impl_matrix_index {
    ($idx:ty, $out:ty) => {
        impl Index<$idx> for Matrix {
            type Output = $out;

            fn index(&self, index: &$idx) -> &$out {
                &self.buf[*index]
            }
        }
    }
}

macro_rules! impl_matrix_index_mut {
    ($idx:ty, $out:ty) => {
        impl IndexMut<$idx> for Matrix {
            fn index_mut(&mut self, index: &$idx) -> &mut $out {
                &mut self.buf[*index]
            }
        }
    }
}

/// Balances a chemical reaction using Gaussian elimination
pub fn balance_reaction(reaction: &(Vec<Molecule>, Vec<Molecule>)) -> CTResult<Vec<u32>> {
    let reac_mat = Matrix::from_reaction(reaction);
    let reduced_mat = try!(forward_elim(reac_mat));
    let coefs = back_substitute(&reduced_mat);

    // if any of the coefs are 0, then an element in that molecule is missing on the other side
    // of the reaction
    if let Some(pos) = coefs.iter().position(|&c| c == 0.0) {
        let &(ref lhs, ref rhs) = reaction;
        let molecule = lhs.iter().chain(rhs.iter()).nth(pos).unwrap();
        let begin = molecule.first().unwrap().pos;
        let len = molecule.last().unwrap().pos + molecule.last().unwrap().len - begin;
        return Err(CTError {
            kind: InputError,
            desc: format!("An element in {} is missing on the other side of the reaction", molecule),
            pos: Some((begin, len)),
        })
    }

    // we find the minimum element with fold, since f64 does not implement Ord...
    let min = coefs.iter().fold(f64::INFINITY, |crnt, &num| {
        if num < crnt {
            num
        } else {
            crnt
        }
    });
    // now we divide all elements by the minimum to (hopefully) convert them all to intergers
    // after which we do the actual conversion
    // we also reverse the Vec so the coefs are in the right order
    Ok(coefs.iter().rev().map(|n| (n / min) as u32).collect())
}

fn column_abs_max_index(columns: &[Vec<f64>], column: usize) -> usize {
    let mut max = 0;
    for i in 1..columns.len() {
        if columns[i][column].abs() > columns[max][column].abs() {
            max = i;
        }
    }
    max
}

fn forward_elim(mut mat: Matrix) -> CTResult<Matrix> {
    for k in 0..min(mat.width(), mat.height()) {
        // locate the pivot
        let pivot = column_abs_max_index(&mat[k..], k) + k;
        if mat[pivot][k] == 0_f64 {
            return Err(CTError {
                kind: InputError,
                desc: "Could not balance reaction".to_string(),
                pos: None,
            })
        }
        // move the pivot to its new position
        mat.switch_rows(k, pivot);

        // zero out the rest of the column
        for i in k + 1..mat.height() {
            let mult = -(mat[i][k] / mat[k][k]);
            mat.add_row_to_row(i, k, mult);
        }
    }
    Ok(mat)
}

fn back_substitute(mat: &Matrix) -> Vec<f64> {
    let mut vars = Vec::with_capacity(mat.width());
    for k in (0..mat.width()).rev() {
        if k >= mat.height() {
            // if this coef does not have a corresponding row in the matrix, then treat is as a
            // free variable and set it to 1
            vars.push(1_f64);
        } else {
            let mut var = 0f64;
            for i in k + 1..mat.width() {
                var -= mat[k][i] * vars[mat.width() - 1 - i];
            }
            vars.push(var / mat[k][k]);
        }
    }
    vars
}

#[derive(Debug, PartialEq)]
struct Matrix {
    buf: Vec<Vec<f64>>,
    height: usize,
    width: usize,
}

impl Matrix {
    fn from_reaction(reaction: &(Vec<Molecule>, Vec<Molecule>)) -> Matrix {
        let &(ref lhs, ref rhs) = reaction;
        let mut names = Vec::<String>::new();
        for molecule in lhs.iter().chain(rhs.iter()) {
            let grouped = elem::group_elems(molecule.clone());
            for elem in grouped.into_iter() {
                if names.iter().find(|e| **e == elem.name).is_none() {
                    names.push(elem.name);
                }
            }
        }
        let mut buf = Vec::with_capacity(names.len());
        for name in names.iter() {
            let mut row = Vec::with_capacity(lhs.len() + rhs.len());
            for molecule in lhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(e.coef as f64))
                                 .unwrap_or(0_f64));
            }
            // we loop over rhs seperately, since we need to multiply the coefs with -1
            for molecule in rhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(-1.0*(e.coef as f64)))
                                 .unwrap_or(0_f64));
            }
            buf.push(row);
        }
        let height = names.len();
        let width = lhs.len() + rhs.len();
        Matrix {
            buf: buf,
            height: height,
            width: width,
        }
    }

    fn add_row_to_row(&mut self, dest: usize, row: usize, mult: f64) {
        for i in 0..self.width {
            let incr = self.buf[row][i] * mult;
            self.buf[dest][i] += incr;
        }
    }

    fn switch_rows(&mut self, row1: usize, row2: usize)  {
        self.buf.swap(row1, row2);
    }

    fn width(&self) -> usize {
        self.width
    }

    fn height(&self) -> usize {
        self.height
    }
}

impl_matrix_index!(usize, Vec<f64>);
impl_matrix_index!(Range<usize>, [Vec<f64>]);
impl_matrix_index!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFull, [Vec<f64>]);

impl_matrix_index_mut!(usize, Vec<f64>);
impl_matrix_index_mut!(Range<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFull, [Vec<f64>]);

mod test {
    use super::*;
    use elem::PerElem;
    use error::CTErrorKind::InputError;

    macro_rules! dummy_elem(
        ($name:expr) => (
            PerElem { name: $name.to_string(), coef: 1, pos: 0, len: 1 }
        );
        ($name:expr, $coef:expr) => (
            PerElem { name: $name.to_string(), coef: $coef, pos: 0, len: 1 }
        );
    );

    #[test]
    fn balance() {
        // attempt to balance C3H8 + O2 -> CO2 + H2O
        let reaction = (vec!(vec!(dummy_elem!("C", 3), dummy_elem!("H", 8)),
                             vec!(dummy_elem!("O", 2))),
                        vec!(vec!(dummy_elem!("C", 1), dummy_elem!("O", 2)),
                             vec!(dummy_elem!("H", 2), dummy_elem!("O", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 5, 3, 4));
        assert_eq!(result, expected);
    }

    #[test]
    fn no_balance_needed() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 1, 1, 1));
        assert_eq!(result, expected);
    }

    #[test]
    fn missing_elem() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1))));
        let result = balance_reaction(&reaction);
        println!("{:?}", result);
        assert!(result.is_err());
        assert_eq!(result.err().unwrap().kind, InputError);
    }
}<commit_msg>Make function to pretty print balanced reaction<commit_after>use std::f64;
use std::cmp::min;
use std::num::Float;
use std::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
use elem;
use elem::Molecule;
use error::{CTResult, CTError};
use error::CTErrorKind::InputError;

macro_rules! impl_matrix_index {
    ($idx:ty, $out:ty) => {
        impl Index<$idx> for Matrix {
            type Output = $out;

            fn index(&self, index: &$idx) -> &$out {
                &self.buf[*index]
            }
        }
    }
}

macro_rules! impl_matrix_index_mut {
    ($idx:ty, $out:ty) => {
        impl IndexMut<$idx> for Matrix {
            fn index_mut(&mut self, index: &$idx) -> &mut $out {
                &mut self.buf[*index]
            }
        }
    }
}

pub fn pretty_print_balanced(reaction: &(Vec<Molecule>, Vec<Molecule>), coefs: &Vec<u32>) {
    let &(ref lhs, ref rhs) = reaction;
    print!("{} {}", coefs[0], lhs[0]);
    for (coef, molecule) in coefs.iter().zip(lhs.iter()).skip(1) {
        print!(" + {} {}", coef, molecule);
    }
    print!(" -> ");
    print!("{} {}", coefs[lhs.len()], rhs[0]);
    for (coef, molecule) in coefs.iter().skip(lhs.len()).zip(rhs.iter()).skip(1) {
        print!(" + {} {}", coef, molecule);
    }
    println!("");
}

/// Balances a chemical reaction using Gaussian elimination
pub fn balance_reaction(reaction: &(Vec<Molecule>, Vec<Molecule>)) -> CTResult<Vec<u32>> {
    let reac_mat = Matrix::from_reaction(reaction);
    let reduced_mat = try!(forward_elim(reac_mat));
    let coefs = back_substitute(&reduced_mat);

    // if any of the coefs are 0, then an element in that molecule is missing on the other side
    // of the reaction
    if let Some(pos) = coefs.iter().position(|&c| c == 0.0) {
        let &(ref lhs, ref rhs) = reaction;
        let molecule = lhs.iter().chain(rhs.iter()).nth(pos).unwrap();
        let begin = molecule.first().unwrap().pos;
        let len = molecule.last().unwrap().pos + molecule.last().unwrap().len - begin;
        return Err(CTError {
            kind: InputError,
            desc: format!("An element in {} is missing on the other side of the reaction", molecule),
            pos: Some((begin, len)),
        })
    }

    // we find the minimum element with fold, since f64 does not implement Ord...
    let min = coefs.iter().fold(f64::INFINITY, |crnt, &num| {
        if num < crnt {
            num
        } else {
            crnt
        }
    });
    // now we divide all elements by the minimum to (hopefully) convert them all to intergers
    // after which we do the actual conversion
    // we also reverse the Vec so the coefs are in the right order
    Ok(coefs.iter().rev().map(|n| (n / min) as u32).collect())
}

fn column_abs_max_index(columns: &[Vec<f64>], column: usize) -> usize {
    let mut max = 0;
    for i in 1..columns.len() {
        if columns[i][column].abs() > columns[max][column].abs() {
            max = i;
        }
    }
    max
}

fn forward_elim(mut mat: Matrix) -> CTResult<Matrix> {
    for k in 0..min(mat.width(), mat.height()) {
        // locate the pivot
        let pivot = column_abs_max_index(&mat[k..], k) + k;
        if mat[pivot][k] == 0_f64 {
            return Err(CTError {
                kind: InputError,
                desc: "Could not balance reaction".to_string(),
                pos: None,
            })
        }
        // move the pivot to its new position
        mat.switch_rows(k, pivot);

        // zero out the rest of the column
        for i in k + 1..mat.height() {
            let mult = -(mat[i][k] / mat[k][k]);
            mat.add_row_to_row(i, k, mult);
        }
    }
    Ok(mat)
}

fn back_substitute(mat: &Matrix) -> Vec<f64> {
    let mut vars = Vec::with_capacity(mat.width());
    for k in (0..mat.width()).rev() {
        if k >= mat.height() {
            // if this coef does not have a corresponding row in the matrix, then treat is as a
            // free variable and set it to 1
            vars.push(1_f64);
        } else {
            let mut var = 0f64;
            for i in k + 1..mat.width() {
                var -= mat[k][i] * vars[mat.width() - 1 - i];
            }
            vars.push(var / mat[k][k]);
        }
    }
    vars
}

#[derive(Debug, PartialEq)]
struct Matrix {
    buf: Vec<Vec<f64>>,
    height: usize,
    width: usize,
}

impl Matrix {
    fn from_reaction(reaction: &(Vec<Molecule>, Vec<Molecule>)) -> Matrix {
        let &(ref lhs, ref rhs) = reaction;
        let mut names = Vec::<String>::new();
        for molecule in lhs.iter().chain(rhs.iter()) {
            let grouped = elem::group_elems(molecule.clone());
            for elem in grouped.into_iter() {
                if names.iter().find(|e| **e == elem.name).is_none() {
                    names.push(elem.name);
                }
            }
        }
        let mut buf = Vec::with_capacity(names.len());
        for name in names.iter() {
            let mut row = Vec::with_capacity(lhs.len() + rhs.len());
            for molecule in lhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(e.coef as f64))
                                 .unwrap_or(0_f64));
            }
            // we loop over rhs seperately, since we need to multiply the coefs with -1
            for molecule in rhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(-1.0*(e.coef as f64)))
                                 .unwrap_or(0_f64));
            }
            buf.push(row);
        }
        let height = names.len();
        let width = lhs.len() + rhs.len();
        Matrix {
            buf: buf,
            height: height,
            width: width,
        }
    }

    fn add_row_to_row(&mut self, dest: usize, row: usize, mult: f64) {
        for i in 0..self.width {
            let incr = self.buf[row][i] * mult;
            self.buf[dest][i] += incr;
        }
    }

    fn switch_rows(&mut self, row1: usize, row2: usize)  {
        self.buf.swap(row1, row2);
    }

    fn width(&self) -> usize {
        self.width
    }

    fn height(&self) -> usize {
        self.height
    }
}

impl_matrix_index!(usize, Vec<f64>);
impl_matrix_index!(Range<usize>, [Vec<f64>]);
impl_matrix_index!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFull, [Vec<f64>]);

impl_matrix_index_mut!(usize, Vec<f64>);
impl_matrix_index_mut!(Range<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFull, [Vec<f64>]);

mod test {
    use super::*;
    use elem::PerElem;
    use error::CTErrorKind::InputError;

    macro_rules! dummy_elem(
        ($name:expr) => (
            PerElem { name: $name.to_string(), coef: 1, pos: 0, len: 1 }
        );
        ($name:expr, $coef:expr) => (
            PerElem { name: $name.to_string(), coef: $coef, pos: 0, len: 1 }
        );
    );

    #[test]
    fn balance() {
        // attempt to balance C3H8 + O2 -> CO2 + H2O
        let reaction = (vec!(vec!(dummy_elem!("C", 3), dummy_elem!("H", 8)),
                             vec!(dummy_elem!("O", 2))),
                        vec!(vec!(dummy_elem!("C", 1), dummy_elem!("O", 2)),
                             vec!(dummy_elem!("H", 2), dummy_elem!("O", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 5, 3, 4));
        assert_eq!(result, expected);
    }

    #[test]
    fn no_balance_needed() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 1, 1, 1));
        assert_eq!(result, expected);
    }

    #[test]
    fn missing_elem() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1))));
        let result = balance_reaction(&reaction);
        println!("{:?}", result);
        assert!(result.is_err());
        assert_eq!(result.err().unwrap().kind, InputError);
    }
}<|endoftext|>


<commit_before>//#![deny(warnings)]

extern crate coreutils;

use coreutils::ArgParser;
use std::{process, env};
use std::io::{self, Read, Write};

const MAN_PAGE: &'static str = /* @MANSTART{true} */ r#"
NAME
    tee - read from standard input and write to standard output and files

SYNOPSIS
    tee [OPTION]... [FILE]...

DESCRIPTION
    Copy standard input to each FILE, and also to standard output.

    -a, --append
        append to given FILEs, do not overwrite

    --help display this help and exit

AUTHOR
    Written by Stefan Lücke.
"#; /* @MANEND */

fn main() {
    let mut parser = ArgParser::new(2).
        add_flag("a", "append").
        add_flag("h", "help");
    parser.initialize(env::args());

    let mut stdout = io::stdout();

    if parser.flagged('h') || parser.flagged("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).unwrap();
        stdout.flush().unwrap();
        process::exit(0);
    }

    let mut fds: Vec<std::fs::File> = Vec::with_capacity(env::args().len());

    if parser.flagged('a') || parser.flagged("append") {
        let args = env::args().skip(2);
        if args.len() > 0 {
            for arg in args {
               let fd = std::fs::OpenOptions::new().append(true).open(arg);
               match fd {
                   Ok(f) => fds.push(f),
                   Err(e) => println!("Err(e): {}", e),
               }
            }
        }
    } else {
        let args = env::args().skip(1);
        if args.len() > 0 {
            for arg in args {
               let fd = std::fs::OpenOptions::new().write(true).create(true).open(arg);
               match fd {
                   Ok(f) => fds.push(f),
                   Err(e) => println!("Err(e): {}", e),
               }
            }
        }
    }

    let stdintemp = io::stdin();
    let mut stdin = stdintemp.lock();
    let mut buffer: &mut [u8] = &mut[0 as u8; 4096];
    'programmloop: loop {
        let result_read = stdin.read(buffer);
        match result_read {
            Ok(size) => {
                if size == 0 {
                    // we've read a EOF here
                    break;
                }

                let result_write = stdout.write(&mut buffer[0..size]);
                    match result_write {
                        Ok(_) => (),
                        Err(e) => {
                            println!("Err(e): {}", e);
                            break 'programmloop;
                        },
                    };

                // iterate over open files
                'writeloop: for mut f in &mut fds {
                    let result_write = f.write(&mut buffer[0..size]);
                    match result_write {
                        Ok(_) => (),
                        Err(e) => {
                            println!("Err(e): {}", e);
                            break 'programmloop;
                        },
                    };
                }

            },
            Err(e) => {
                println!("Err(e): {}", e);
                break;
            },
        };
    }

    stdout.flush().unwrap();
    process::exit(0);
}
<commit_msg>Fix man name of tee<commit_after>//#![deny(warnings)]

extern crate coreutils;

use coreutils::ArgParser;
use std::{process, env};
use std::io::{self, Read, Write};

const MAN_PAGE: &'static str = /* @MANSTART{tee} */ r#"
NAME
    tee - read from standard input and write to standard output and files

SYNOPSIS
    tee [OPTION]... [FILE]...

DESCRIPTION
    Copy standard input to each FILE, and also to standard output.

    -a, --append
        append to given FILEs, do not overwrite

    --help display this help and exit

AUTHOR
    Written by Stefan Lücke.
"#; /* @MANEND */

fn main() {
    let mut parser = ArgParser::new(2).
        add_flag("a", "append").
        add_flag("h", "help");
    parser.initialize(env::args());

    let mut stdout = io::stdout();

    if parser.flagged('h') || parser.flagged("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).unwrap();
        stdout.flush().unwrap();
        process::exit(0);
    }

    let mut fds: Vec<std::fs::File> = Vec::with_capacity(env::args().len());

    if parser.flagged('a') || parser.flagged("append") {
        let args = env::args().skip(2);
        if args.len() > 0 {
            for arg in args {
               let fd = std::fs::OpenOptions::new().append(true).open(arg);
               match fd {
                   Ok(f) => fds.push(f),
                   Err(e) => println!("Err(e): {}", e),
               }
            }
        }
    } else {
        let args = env::args().skip(1);
        if args.len() > 0 {
            for arg in args {
               let fd = std::fs::OpenOptions::new().write(true).create(true).open(arg);
               match fd {
                   Ok(f) => fds.push(f),
                   Err(e) => println!("Err(e): {}", e),
               }
            }
        }
    }

    let stdintemp = io::stdin();
    let mut stdin = stdintemp.lock();
    let mut buffer: &mut [u8] = &mut[0 as u8; 4096];
    'programmloop: loop {
        let result_read = stdin.read(buffer);
        match result_read {
            Ok(size) => {
                if size == 0 {
                    // we've read a EOF here
                    break;
                }

                let result_write = stdout.write(&mut buffer[0..size]);
                    match result_write {
                        Ok(_) => (),
                        Err(e) => {
                            println!("Err(e): {}", e);
                            break 'programmloop;
                        },
                    };

                // iterate over open files
                'writeloop: for mut f in &mut fds {
                    let result_write = f.write(&mut buffer[0..size]);
                    match result_write {
                        Ok(_) => (),
                        Err(e) => {
                            println!("Err(e): {}", e);
                            break 'programmloop;
                        },
                    };
                }

            },
            Err(e) => {
                println!("Err(e): {}", e);
                break;
            },
        };
    }

    stdout.flush().unwrap();
    process::exit(0);
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! GtkPlacesSidebar — Sidebar that displays frequently-used places in the file system

use ffi;
use FFIWidget;
use cast::GTK_PLACES_SIDEBAR;
use glib::{to_bool, to_gboolean};

struct_Widget!(PlacesSidebar);

impl PlacesSidebar {
    pub fn new() -> Option<PlacesSidebar> {
        let tmp_pointer = unsafe { ffi::gtk_places_sidebar_new() };
        check_pointer!(tmp_pointer, PlacesSidebar)
    }

    pub fn set_open_flags(&self, flags: ::PlacesOpenFlags) {
        unsafe { ffi::gtk_places_sidebar_set_open_flags(GTK_PLACES_SIDEBAR(self.unwrap_widget()), flags) }
    }

    pub fn get_open_flags(&self) -> ::PlacesOpenFlags {
        unsafe { ffi::gtk_places_sidebar_get_open_flags(GTK_PLACES_SIDEBAR(self.unwrap_widget())) }
    }

    pub fn set_show_desktop(&self, show_desktop: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_desktop(GTK_PLACES_SIDEBAR(self.unwrap_widget()), to_gboolean(show_desktop)) }
    }

    pub fn get_show_desktop(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_desktop(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    pub fn set_show_connect_to_server(&self, show_connect_to_server: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_connect_to_server(GTK_PLACES_SIDEBAR(self.unwrap_widget()),
            to_gboolean(show_connect_to_server)) }
    }

    pub fn get_show_connect_to_server(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_connect_to_server(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    pub fn set_local_only(&self, local_only: bool) {
        unsafe { ffi::gtk_places_sidebar_set_local_only(GTK_PLACES_SIDEBAR(self.unwrap_widget()), to_gboolean(local_only)) }
    }

    pub fn get_local_only(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_local_only(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    pub fn set_show_enter_location(&self, show_enter_location: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_enter_location(GTK_PLACES_SIDEBAR(self.unwrap_widget()),
            to_gboolean(show_enter_location)) }
    }

    pub fn get_show_enter_location(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_enter_location(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }
}

impl_drop!(PlacesSidebar);
impl_TraitWidget!(PlacesSidebar);

impl ::ContainerTrait for PlacesSidebar {}
impl ::BinTrait for PlacesSidebar {}
impl ::ScrolledWindowTrait for PlacesSidebar {}
<commit_msg>Fix build error (missing cfg 3_12)<commit_after>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! GtkPlacesSidebar — Sidebar that displays frequently-used places in the file system

use ffi;
use FFIWidget;
use cast::GTK_PLACES_SIDEBAR;
use glib::{to_bool, to_gboolean};

struct_Widget!(PlacesSidebar);

impl PlacesSidebar {
    pub fn new() -> Option<PlacesSidebar> {
        let tmp_pointer = unsafe { ffi::gtk_places_sidebar_new() };
        check_pointer!(tmp_pointer, PlacesSidebar)
    }

    pub fn set_open_flags(&self, flags: ::PlacesOpenFlags) {
        unsafe { ffi::gtk_places_sidebar_set_open_flags(GTK_PLACES_SIDEBAR(self.unwrap_widget()), flags) }
    }

    pub fn get_open_flags(&self) -> ::PlacesOpenFlags {
        unsafe { ffi::gtk_places_sidebar_get_open_flags(GTK_PLACES_SIDEBAR(self.unwrap_widget())) }
    }

    pub fn set_show_desktop(&self, show_desktop: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_desktop(GTK_PLACES_SIDEBAR(self.unwrap_widget()), to_gboolean(show_desktop)) }
    }

    pub fn get_show_desktop(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_desktop(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    pub fn set_show_connect_to_server(&self, show_connect_to_server: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_connect_to_server(GTK_PLACES_SIDEBAR(self.unwrap_widget()),
            to_gboolean(show_connect_to_server)) }
    }

    pub fn get_show_connect_to_server(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_connect_to_server(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    #[cfg(gtk_3_12)]
    pub fn set_local_only(&self, local_only: bool) {
        unsafe { ffi::gtk_places_sidebar_set_local_only(GTK_PLACES_SIDEBAR(self.unwrap_widget()), to_gboolean(local_only)) }
    }

    #[cfg(gtk_3_12)]
    pub fn get_local_only(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_local_only(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    #[cfg(gtk_3_12)]
    pub fn set_show_enter_location(&self, show_enter_location: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_enter_location(GTK_PLACES_SIDEBAR(self.unwrap_widget()),
            to_gboolean(show_enter_location)) }
    }

    #[cfg(gtk_3_12)]
    pub fn get_show_enter_location(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_enter_location(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }
}

impl_drop!(PlacesSidebar);
impl_TraitWidget!(PlacesSidebar);

impl ::ContainerTrait for PlacesSidebar {}
impl ::BinTrait for PlacesSidebar {}
impl ::ScrolledWindowTrait for PlacesSidebar {}
<|endoftext|>


<commit_before>//! Track which values are live in an EBB with instruction granularity.
//!
//! The `LiveValueTracker` keeps track of the set of live SSA values at each instruction in an EBB.
//! The sets of live values are computed on the fly as the tracker is moved from instruction to
//! instruction, starting at the EBB header.

use dominator_tree::DominatorTree;
use entity_list::{EntityList, ListPool};
use ir::instructions::BranchInfo;
use ir::{Inst, Ebb, Value, DataFlowGraph, ProgramOrder, ExpandedProgramPoint};
use partition_slice::partition_slice;
use regalloc::liveness::Liveness;

use std::collections::HashMap;

type ValueList = EntityList<Value>;

/// Compute and track live values throughout an EBB.
pub struct LiveValueTracker {
    /// The set of values that are live at the current program point.
    live: LiveValueVec,

    /// Saved set of live values for every jump and branch that can potentially be an immediate
    /// dominator of an EBB.
    ///
    /// This is the set of values that are live *before* the branch.
    idom_sets: HashMap<Inst, ValueList>,

    /// Memory pool for the live sets.
    idom_pool: ListPool<Value>,
}

/// Information about a value that is live at the current program point.
pub struct LiveValue {
    /// The live value.
    pub value: Value,

    /// The local ending point of the live range in the current EBB, as returned by
    /// `LiveRange::def_local_end()` or `LiveRange::livein_local_end()`.
    pub endpoint: Inst,
}

struct LiveValueVec {
    /// The set of values that are live at the current program point.
    values: Vec<LiveValue>,

    /// How many values at the front of `values` are known to be live after `inst`?
    ///
    /// This is used to pass a much smaller slice to `partition_slice` when its called a second
    /// time for the same instruction.
    live_prefix: Option<(Inst, usize)>,
}

impl LiveValueVec {
    fn new() -> LiveValueVec {
        LiveValueVec {
            values: Vec::new(),
            live_prefix: None,
        }
    }

    /// Add a new live value to `values`.
    fn push(&mut self, value: Value, endpoint: Inst) {
        self.values.push(LiveValue {
            value: value,
            endpoint: endpoint,
        });
    }

    /// Remove all elements.
    fn clear(&mut self) {
        self.values.clear();
        self.live_prefix = None;
    }

    /// Make sure that the values killed by `next_inst` are moved to the end of the `values`
    /// vector.
    ///
    /// Returns the number of values that will be live after `next_inst`.
    fn live_after(&mut self, next_inst: Inst) -> usize {
        // How many values at the front of the vector are already known to survive `next_inst`?
        // We don't need to pass this prefix to `partition_slice()`
        let keep = match self.live_prefix {
            Some((i, prefix)) if i == next_inst => prefix,
            _ => 0,
        };

        // Move the remaining surviving values to the front partition of the vector.
        let prefix = keep + partition_slice(&mut self.values[keep..], |v| v.endpoint != next_inst);

        // Remember the new prefix length in case we get called again for the same `next_inst`.
        self.live_prefix = Some((next_inst, prefix));
        prefix
    }

    /// Remove the values killed by `next_inst`.
    fn remove_kill_values(&mut self, next_inst: Inst) {
        let keep = self.live_after(next_inst);
        self.values.truncate(keep);
    }
}

impl LiveValueTracker {
    /// Create a new blank tracker.
    pub fn new() -> LiveValueTracker {
        LiveValueTracker {
            live: LiveValueVec::new(),
            idom_sets: HashMap::new(),
            idom_pool: ListPool::new(),
        }
    }

    /// Clear all cached information.
    pub fn clear(&mut self) {
        self.live.clear();
        self.idom_sets.clear();
        self.idom_pool.clear();
    }

    /// Get the set of currently live values.
    ///
    /// Between calls to `process_inst()` and `drop_dead()`, this includes both values killed and
    /// defined by the current instruction.
    pub fn live(&self) -> &[LiveValue] {
        &self.live.values
    }

    /// Move the current position to the top of `ebb`.
    ///
    /// This depends on the stored live value set at `ebb`'s immediate dominator, so that must have
    /// been visited first.
    ///
    /// Returns `(liveins, args)` as a pair or slices. The first slice is the set of live-in values
    /// from the immediate dominator. The second slice is the set of `ebb` arguments that are live.
    /// Dead arguments with no uses are ignored and not added to the set.
    pub fn ebb_top<PO: ProgramOrder>(&mut self,
                                     ebb: Ebb,
                                     dfg: &DataFlowGraph,
                                     liveness: &Liveness,
                                     program_order: &PO,
                                     domtree: &DominatorTree)
                                     -> (&[LiveValue], &[LiveValue]) {
        // Start over, compute the set of live values at the top of the EBB from two sources:
        //
        // 1. Values that were live before `ebb`'s immediate dominator, filtered for those that are
        //    actually live-in.
        // 2. Arguments to `ebb` that are not dead.
        //
        self.live.clear();

        // Compute the live-in values. Start by filtering the set of values that were live before
        // the immediate dominator. Just use the empty set if there's no immediate dominator (i.e.,
        // the entry block or an unreachable block).
        if let Some(idom) = domtree.idom(ebb) {
            // If the immediate dominator exits, we must have a stored list for it. This is a
            // requirement to the order EBBs are visited: All dominators must have been processed
            // before the current EBB.
            let idom_live_list =
                self.idom_sets.get(&idom).expect("No stored live set for dominator");
            // Get just the values that are live-in to `ebb`.
            for &value in idom_live_list.as_slice(&self.idom_pool) {
                let lr = liveness.get(value)
                    .expect("Immediate dominator value has no live range");

                // Check if this value is live-in here.
                if let Some(endpoint) = lr.livein_local_end(ebb, program_order) {
                    self.live.push(value, endpoint);
                }
            }
        }

        // Now add all the live arguments to `ebb`.
        let first_arg = self.live.values.len();
        for value in dfg.ebb_args(ebb) {
            let lr = liveness.get(value).expect("EBB argument value has no live range");
            assert_eq!(lr.def(), ebb.into());
            match lr.def_local_end().into() {
                ExpandedProgramPoint::Inst(endpoint) => {
                    self.live.push(value, endpoint);
                }
                ExpandedProgramPoint::Ebb(local_ebb) => {
                    // This is a dead EBB argument which is not even live into the first
                    // instruction in the EBB. We can ignore it.
                    assert_eq!(local_ebb,
                               ebb,
                               "EBB argument live range ends at wrong EBB header");
                }
            }
        }

        self.live.values.split_at(first_arg)
    }

    /// Prepare to move past `inst`.
    ///
    /// Determine the set of already live values that are killed by `inst`, and add the new defined
    /// values to the tracked set.
    ///
    /// Returns `(kills, defs)` as a pair of slices. The `defs` slice is guaranteed to be in the
    /// same order as `inst`'s results, and includes dead defines. The order of `kills` is
    /// arbitrary.
    ///
    /// The `drop_dead()` method must be called next to actually remove the dead values from the
    /// tracked set after the two returned slices are no longer needed.
    pub fn process_inst(&mut self,
                        inst: Inst,
                        dfg: &DataFlowGraph,
                        liveness: &Liveness)
                        -> (&[LiveValue], &[LiveValue]) {
        // Save a copy of the live values before any branches or jumps that could be somebody's
        // immediate dominator.
        match dfg[inst].analyze_branch() {
            BranchInfo::NotABranch => {}
            _ => self.save_idom_live_set(inst),
        }

        // Move killed values to the end of the vector.
        // Don't remove them yet, `drop_dead()` will do that.
        let first_kill = self.live.live_after(inst);

        // Add the values defined by `inst`.
        let first_def = self.live.values.len();
        for value in dfg.inst_results(inst) {
            let lr = liveness.get(value).expect("Instruction result has no live range");
            assert_eq!(lr.def(), inst.into());
            match lr.def_local_end().into() {
                ExpandedProgramPoint::Inst(endpoint) => {
                    self.live.push(value, endpoint);
                }
                ExpandedProgramPoint::Ebb(ebb) => {
                    panic!("Instruction result live range can't end at {}", ebb);
                }
            }
        }

        (&self.live.values[first_kill..first_def], &self.live.values[first_def..])
    }

    /// Drop the values that are now dead after moving past `inst`.
    ///
    /// This removes both live values that were killed by `inst` and dead defines on `inst` itself.
    ///
    /// This must be called after `process_inst(inst)` and before proceeding to the next
    /// instruction.
    pub fn drop_dead(&mut self, inst: Inst) {
        // Remove both live values that were killed by `inst` and dead defines from `inst`.
        self.live.remove_kill_values(inst);
    }

    /// Save the current set of live values so it is associated with `idom`.
    fn save_idom_live_set(&mut self, idom: Inst) {
        let values = self.live.values.iter().map(|lv| lv.value);
        let pool = &mut self.idom_pool;
        // If there already is a set saved for `idom`, just keep it.
        self.idom_sets.entry(idom).or_insert_with(|| {
            let mut list = ValueList::default();
            list.extend(values, pool);
            list
        });
    }
}
<commit_msg>Cache the affinity in LiveValue.<commit_after>//! Track which values are live in an EBB with instruction granularity.
//!
//! The `LiveValueTracker` keeps track of the set of live SSA values at each instruction in an EBB.
//! The sets of live values are computed on the fly as the tracker is moved from instruction to
//! instruction, starting at the EBB header.

use dominator_tree::DominatorTree;
use entity_list::{EntityList, ListPool};
use ir::instructions::BranchInfo;
use ir::{Inst, Ebb, Value, DataFlowGraph, ProgramOrder, ExpandedProgramPoint};
use partition_slice::partition_slice;
use regalloc::affinity::Affinity;
use regalloc::liveness::Liveness;

use std::collections::HashMap;

type ValueList = EntityList<Value>;

/// Compute and track live values throughout an EBB.
pub struct LiveValueTracker {
    /// The set of values that are live at the current program point.
    live: LiveValueVec,

    /// Saved set of live values for every jump and branch that can potentially be an immediate
    /// dominator of an EBB.
    ///
    /// This is the set of values that are live *before* the branch.
    idom_sets: HashMap<Inst, ValueList>,

    /// Memory pool for the live sets.
    idom_pool: ListPool<Value>,
}

/// Information about a value that is live at the current program point.
pub struct LiveValue {
    /// The live value.
    pub value: Value,

    /// The local ending point of the live range in the current EBB, as returned by
    /// `LiveRange::def_local_end()` or `LiveRange::livein_local_end()`.
    pub endpoint: Inst,

    /// The affinity of the value as represented in its `LiveRange`.
    ///
    /// This value is simply a copy of the affinity stored in the live range. We copy it because
    /// almost all users of `LiveValue` need to look at it.
    pub affinity: Affinity,
}

struct LiveValueVec {
    /// The set of values that are live at the current program point.
    values: Vec<LiveValue>,

    /// How many values at the front of `values` are known to be live after `inst`?
    ///
    /// This is used to pass a much smaller slice to `partition_slice` when its called a second
    /// time for the same instruction.
    live_prefix: Option<(Inst, usize)>,
}

impl LiveValueVec {
    fn new() -> LiveValueVec {
        LiveValueVec {
            values: Vec::new(),
            live_prefix: None,
        }
    }

    /// Add a new live value to `values`.
    fn push(&mut self, value: Value, endpoint: Inst, affinity: Affinity) {
        self.values.push(LiveValue {
            value: value,
            endpoint: endpoint,
            affinity: affinity,
        });
    }

    /// Remove all elements.
    fn clear(&mut self) {
        self.values.clear();
        self.live_prefix = None;
    }

    /// Make sure that the values killed by `next_inst` are moved to the end of the `values`
    /// vector.
    ///
    /// Returns the number of values that will be live after `next_inst`.
    fn live_after(&mut self, next_inst: Inst) -> usize {
        // How many values at the front of the vector are already known to survive `next_inst`?
        // We don't need to pass this prefix to `partition_slice()`
        let keep = match self.live_prefix {
            Some((i, prefix)) if i == next_inst => prefix,
            _ => 0,
        };

        // Move the remaining surviving values to the front partition of the vector.
        let prefix = keep + partition_slice(&mut self.values[keep..], |v| v.endpoint != next_inst);

        // Remember the new prefix length in case we get called again for the same `next_inst`.
        self.live_prefix = Some((next_inst, prefix));
        prefix
    }

    /// Remove the values killed by `next_inst`.
    fn remove_kill_values(&mut self, next_inst: Inst) {
        let keep = self.live_after(next_inst);
        self.values.truncate(keep);
    }
}

impl LiveValueTracker {
    /// Create a new blank tracker.
    pub fn new() -> LiveValueTracker {
        LiveValueTracker {
            live: LiveValueVec::new(),
            idom_sets: HashMap::new(),
            idom_pool: ListPool::new(),
        }
    }

    /// Clear all cached information.
    pub fn clear(&mut self) {
        self.live.clear();
        self.idom_sets.clear();
        self.idom_pool.clear();
    }

    /// Get the set of currently live values.
    ///
    /// Between calls to `process_inst()` and `drop_dead()`, this includes both values killed and
    /// defined by the current instruction.
    pub fn live(&self) -> &[LiveValue] {
        &self.live.values
    }

    /// Move the current position to the top of `ebb`.
    ///
    /// This depends on the stored live value set at `ebb`'s immediate dominator, so that must have
    /// been visited first.
    ///
    /// Returns `(liveins, args)` as a pair or slices. The first slice is the set of live-in values
    /// from the immediate dominator. The second slice is the set of `ebb` arguments that are live.
    /// Dead arguments with no uses are ignored and not added to the set.
    pub fn ebb_top<PO: ProgramOrder>(&mut self,
                                     ebb: Ebb,
                                     dfg: &DataFlowGraph,
                                     liveness: &Liveness,
                                     program_order: &PO,
                                     domtree: &DominatorTree)
                                     -> (&[LiveValue], &[LiveValue]) {
        // Start over, compute the set of live values at the top of the EBB from two sources:
        //
        // 1. Values that were live before `ebb`'s immediate dominator, filtered for those that are
        //    actually live-in.
        // 2. Arguments to `ebb` that are not dead.
        //
        self.live.clear();

        // Compute the live-in values. Start by filtering the set of values that were live before
        // the immediate dominator. Just use the empty set if there's no immediate dominator (i.e.,
        // the entry block or an unreachable block).
        if let Some(idom) = domtree.idom(ebb) {
            // If the immediate dominator exits, we must have a stored list for it. This is a
            // requirement to the order EBBs are visited: All dominators must have been processed
            // before the current EBB.
            let idom_live_list =
                self.idom_sets.get(&idom).expect("No stored live set for dominator");
            // Get just the values that are live-in to `ebb`.
            for &value in idom_live_list.as_slice(&self.idom_pool) {
                let lr = liveness.get(value)
                    .expect("Immediate dominator value has no live range");

                // Check if this value is live-in here.
                if let Some(endpoint) = lr.livein_local_end(ebb, program_order) {
                    self.live.push(value, endpoint, lr.affinity);
                }
            }
        }

        // Now add all the live arguments to `ebb`.
        let first_arg = self.live.values.len();
        for value in dfg.ebb_args(ebb) {
            let lr = liveness.get(value).expect("EBB argument value has no live range");
            assert_eq!(lr.def(), ebb.into());
            match lr.def_local_end().into() {
                ExpandedProgramPoint::Inst(endpoint) => {
                    self.live.push(value, endpoint, lr.affinity);
                }
                ExpandedProgramPoint::Ebb(local_ebb) => {
                    // This is a dead EBB argument which is not even live into the first
                    // instruction in the EBB. We can ignore it.
                    assert_eq!(local_ebb,
                               ebb,
                               "EBB argument live range ends at wrong EBB header");
                }
            }
        }

        self.live.values.split_at(first_arg)
    }

    /// Prepare to move past `inst`.
    ///
    /// Determine the set of already live values that are killed by `inst`, and add the new defined
    /// values to the tracked set.
    ///
    /// Returns `(kills, defs)` as a pair of slices. The `defs` slice is guaranteed to be in the
    /// same order as `inst`'s results, and includes dead defines. The order of `kills` is
    /// arbitrary.
    ///
    /// The `drop_dead()` method must be called next to actually remove the dead values from the
    /// tracked set after the two returned slices are no longer needed.
    pub fn process_inst(&mut self,
                        inst: Inst,
                        dfg: &DataFlowGraph,
                        liveness: &Liveness)
                        -> (&[LiveValue], &[LiveValue]) {
        // Save a copy of the live values before any branches or jumps that could be somebody's
        // immediate dominator.
        match dfg[inst].analyze_branch() {
            BranchInfo::NotABranch => {}
            _ => self.save_idom_live_set(inst),
        }

        // Move killed values to the end of the vector.
        // Don't remove them yet, `drop_dead()` will do that.
        let first_kill = self.live.live_after(inst);

        // Add the values defined by `inst`.
        let first_def = self.live.values.len();
        for value in dfg.inst_results(inst) {
            let lr = liveness.get(value).expect("Instruction result has no live range");
            assert_eq!(lr.def(), inst.into());
            match lr.def_local_end().into() {
                ExpandedProgramPoint::Inst(endpoint) => {
                    self.live.push(value, endpoint, lr.affinity);
                }
                ExpandedProgramPoint::Ebb(ebb) => {
                    panic!("Instruction result live range can't end at {}", ebb);
                }
            }
        }

        (&self.live.values[first_kill..first_def], &self.live.values[first_def..])
    }

    /// Drop the values that are now dead after moving past `inst`.
    ///
    /// This removes both live values that were killed by `inst` and dead defines on `inst` itself.
    ///
    /// This must be called after `process_inst(inst)` and before proceeding to the next
    /// instruction.
    pub fn drop_dead(&mut self, inst: Inst) {
        // Remove both live values that were killed by `inst` and dead defines from `inst`.
        self.live.remove_kill_values(inst);
    }

    /// Save the current set of live values so it is associated with `idom`.
    fn save_idom_live_set(&mut self, idom: Inst) {
        let values = self.live.values.iter().map(|lv| lv.value);
        let pool = &mut self.idom_pool;
        // If there already is a set saved for `idom`, just keep it.
        self.idom_sets.entry(idom).or_insert_with(|| {
            let mut list = ValueList::default();
            list.extend(values, pool);
            list
        });
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate quick_error;

use std::env;
use std::convert::AsRef;
use std::fs::{File, create_dir_all};
use std::io::{Write, Read, BufWriter};
use std::path::Path;
use std::process::Command;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: std::io::Error) {
            from()
        }
        MissingEnvVar {
        }
    }
}

pub fn write_version <P: AsRef<Path>>(topdir: P, file_contents: String) -> Result<(), Error> {
    let path = env::var_os("OUT_DIR").ok_or(Error::MissingEnvVar)?;
    let path : &Path = path.as_ref();
    create_dir_all(path)?;

    let path = path.join("version.rs");
    let mut file = BufWriter::new(File::create(&path)?);
    write!(file, "{}", file_contents)?;
    Ok(())
}

static ENV_VARS: [&'static str;17] = ["GIT_COMMIT", "GIT_COMMIT_SHORT","GIT_OPTIONAL_TAG",
    "GIT_DESCRIBE_ALWAYS", "GIT_DESCRIBE_ALWAYS_LONG", "GIT_DESCRIBE_AAL", "GIT_OPTIONAL_BRANCH",
    "ESTIMATED_ARTIFACT_URL","ESTIMATED_DOCS_URL","CI_SEQUENTIAL_BUILD_NUMBER","CI_BUILD_URL","CI_JOB_URL","CI_JOB_TITLE","CI_STRING",
    "CI_PULL_REQUEST_INFO", "CI_TAG", "CI_RELATED_BRANCH"
    ];

const PACKAGE_TOP_DIR : &'static str = ".";

fn main() {

//    let output = Command::new("/bin/cat")
//        .arg("file.txt")
//        .output()
//        .expect("failed to execute process");

    //Pull in imageflow_core/conaninfo.txt for compiler versions and dependencies

//    - git rev-parse --short HEAD | set /P GIT_COMMIT_SHORT
//        - git describe --always --tags | set /P GIT_DESCRIBE_ALWAYS
//        - git describe --always --tags --long | set /P GIT_DESCRIBE_ALWAYS_LONG
//        - git describe --always --all --long | set /P GIT_DESCRIBE_AAL
//        - git describe --exact-match --tags | set /P GIT_OPTIONAL_TAG
//     git rev-parse --abbrev-ref HEAD | set /P GIT_OPTIONAL_BRANCH
// rustc -V
    // cargo -V
    // cd c_components && cargo info > file
    //RUSTC version
    //Gcc/clang version
    //conan package versions?

    let mut contents = String::new();
    for name in ENV_VARS.iter(){
        if let Some(value) = env::var(name).ok(){
            let line = format!("static {}: &'static str = {:?};\n", name,value);
            contents += &line;
        }
    }

    write_version(PACKAGE_TOP_DIR, contents ).expect("Saving git version");
}<commit_msg>More WIP<commit_after>#[macro_use]
extern crate quick_error;

use std::env;
use std::convert::AsRef;
use std::fs::{File, create_dir_all};
use std::io::{Write, Read, BufWriter};
use std::path::Path;
use std::process::Command;
use std::collections::HashMap;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: std::io::Error) {
            from()
        }
        MissingEnvVar {
        }
    }
}
//
//struct CompilationInfo{
//    env_vars: HashMap<&'static str, Option<String>>,
//    commands: HashMap<&'static str, Option<String>>,
//    conan_info: String,
//
//}
//
static ENV_VARS: [&'static str;17] = ["GIT_COMMIT", "GIT_COMMIT_SHORT","GIT_OPTIONAL_TAG",
    "GIT_DESCRIBE_ALWAYS", "GIT_DESCRIBE_ALWAYS_LONG", "GIT_DESCRIBE_AAL", "GIT_OPTIONAL_BRANCH",
    "ESTIMATED_ARTIFACT_URL","ESTIMATED_DOCS_URL","CI_SEQUENTIAL_BUILD_NUMBER","CI_BUILD_URL","CI_JOB_URL","CI_JOB_TITLE","CI_STRING",
    "CI_PULL_REQUEST_INFO", "CI_TAG", "CI_RELATED_BRANCH"
];

//fn add_command(&mut commands: HashMap<&'static str, Option<String>>, key: &'static str, command: &str){
//
//}
//fn populate_compilation_info() -> CompilationIfno{
//    let mut c = HashMap::new();
//    add_command(c, "GIT_COMMIT", "git rev-parse HEAD");
//    add_command(c, "GIT_COMMIT_SHORT", "git rev-parse --short HEAD");
//    add_command(c, "GIT_DESCRIBE_ALWAYS", "git describe --always --tags");
//    add_command(c, "GIT_DESCRIBE_ALWAYS_LONG", "git describe --always --tags --long");
//    add_command(c, "GIT_DESCRIBE_AAL", "git describe --always --all --long");
//    add_command(c, "GIT_OPTIONAL_TAG", "git describe --exact-match --tags");
//    add_command(c, "GIT_OPTIONAL_BRANCH", "git rev-parse --abbrev-ref HEAD");
//    add_command(c, "CONAN_VERSION", "conan -V");
//    add_command(c, "DEFAULT_GCC_VERSION", "gcc -v");
//    add_command(c, "DEFAULT_CLANG_VERSION", "clang --version");
//    add_command(c, "DEFAULT_RUSTC_VERSION", "rustc- -V");
//    add_command(c, "DEFAULT_CARGO_VERSION", "cargo -V");
//
//
//    let mut env = HashMap::new();
//    for name in ENV_VARS.iter(){
//        if let Some(value) = env::var(name).ok(){
//            env.insert(name, value);
//        }
//    }
//
//
//    //    - git rev-parse --short HEAD | set /P GIT_COMMIT_SHORT
//    //        - git describe --always --tags | set /P GIT_DESCRIBE_ALWAYS
//    //        - git describe --always --tags --long | set /P GIT_DESCRIBE_ALWAYS_LONG
//    //        - git describe --always --all --long | set /P GIT_DESCRIBE_AAL
//    //        - git describe --exact-match --tags | set /P GIT_OPTIONAL_TAG
//    //     git rev-parse --abbrev-ref HEAD | set /P GIT_OPTIONAL_BRANCH
//    // rustc -V
//    // cargo -V
//    // cd c_components && cargo info > file
//    //RUSTC version
//    //Gcc/clang version
//
//    CompilationInfo{
//        commands: c,
//        env_vars: env,
//        conan_info:
//    }
//}

pub fn write_version <P: AsRef<Path>>(topdir: P, file_contents: String) -> Result<(), Error> {
    let path = env::var_os("OUT_DIR").ok_or(Error::MissingEnvVar)?;
    let path : &Path = path.as_ref();
    create_dir_all(path)?;

    let path = path.join("version.rs");
    let mut file = BufWriter::new(File::create(&path)?);
    write!(file, "{}", file_contents)?;
    Ok(())
}

const PACKAGE_TOP_DIR : &'static str = ".";

fn main() {

//    let output = Command::new("/bin/cat")
//        .arg("file.txt")
//        .output()
//        .expect("failed to execute process");

    //Pull in imageflow_core/conaninfo.txt for compiler versions and dependencies

//    - git rev-parse --short HEAD | set /P GIT_COMMIT_SHORT
//        - git describe --always --tags | set /P GIT_DESCRIBE_ALWAYS
//        - git describe --always --tags --long | set /P GIT_DESCRIBE_ALWAYS_LONG
//        - git describe --always --all --long | set /P GIT_DESCRIBE_AAL
//        - git describe --exact-match --tags | set /P GIT_OPTIONAL_TAG
//     git rev-parse --abbrev-ref HEAD | set /P GIT_OPTIONAL_BRANCH
// rustc -V
    // cargo -V
    // cd c_components && cargo info > file
    //RUSTC version
    //Gcc/clang version
    //conan package versions?

    let mut contents = String::new();
    for name in ENV_VARS.iter(){
        if let Some(value) = env::var(name).ok(){
            let line = format!("static {}: &'static str = {:?};\n", name,value);
            contents += &line;
        }
    }

    write_version(PACKAGE_TOP_DIR, contents ).expect("Saving git version");
}<|endoftext|>


<commit_before>//! An enum mapping type.
//!
//! It is implemented using array, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! #[macro_use]
//! extern crate enum_map;
//! #[macro_use]
//! extern crate enum_map_derive;
//!
//! use enum_map::EnumMap;
//!
//! #[derive(Debug, EnumMap)]
//! enum Example {
//!     A,
//!     B,
//!     C,
//! }
//!
//! fn main() {
//!     let mut map = enum_map! {
//!         Example::A => 1,
//!         Example::B => 2,
//!         Example::C => 3,
//!     };
//!     map[Example::C] = 4;
//!
//!     assert_eq!(map[Example::A], 1);
//!
//!     for (key, &value) in &map {
//!         println!("{:?} has {} as value.", key, value);
//!     }
//! }
//! ```

#![no_std]
#![deny(missing_docs)]

#[cfg(feature = "serde")]
extern crate serde;

#[cfg(feature = "serde")]
use serde::ser::{Serialize, Serializer, SerializeMap};
#[cfg(feature = "serde")]
use serde::de::{self, Deserialize, Deserializer, Error, MapAccess};

#[cfg(feature = "serde")]
use core::fmt;
use core::hash::{Hash, Hasher};
use core::iter::Enumerate;
use core::marker::PhantomData;
use core::ops::{Index, IndexMut};
use core::slice;

// this is not stable, do not depend on this
#[doc(hidden)]
pub trait Internal<V>: Sized {
    type Array;
    fn slice(&Self::Array) -> &[V];
    fn slice_mut(&mut Self::Array) -> &mut [V];
    fn from_usize(usize) -> Self;
    fn to_usize(self) -> usize;
    fn from_function<F: FnMut(Self) -> V>(F) -> Self::Array;
}

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(EnumMap)]` from `enum_map_derive` crate.
///
/// # Examples
///
/// ```
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// use enum_map::EnumMap;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
#[derive(Debug)]
pub struct EnumMap<K: Internal<V>, V> {
    array: K::Array,
}

impl<K: Internal<V>, V> EnumMap<K, V> {
    /// Returns number of elements in enum map.
    pub fn len(&self) -> usize {
        K::slice(&self.array).len()
    }

    /// Returns an iterator over enum map.
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }
}

impl<F: FnMut(K) -> V, K: Internal<V>, V> From<F> for EnumMap<K, V> {
    fn from(f: F) -> Self {
        EnumMap { array: K::from_function(f) }
    }
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        ::enum_map::EnumMap::from(|k| match k { $($t)* })
    };
}

impl<K: Internal<V>, V: Default> EnumMap<K, V>
    where K::Array: Default
{
    /// Creates an enum map with default values.
    ///
    /// ```
    /// extern crate enum_map;
    /// #[macro_use]
    /// extern crate enum_map_derive;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    pub fn new() -> Self {
        EnumMap::default()
    }
}

// Implementations provided by derive attribute are too specific, and put requirements on K.
// This is caused by rust-lang/rust#26925.
impl<K: Internal<V>, V> Clone for EnumMap<K, V>
    where K::Array: Clone
{
    fn clone(&self) -> Self {
        EnumMap { array: self.array.clone() }
    }
}

impl<K: Internal<V>, V> Copy for EnumMap<K, V> where K::Array: Copy {}

impl<K: Internal<V>, V> PartialEq for EnumMap<K, V>
    where K::Array: PartialEq
{
    fn eq(&self, other: &Self) -> bool {
        self.array == other.array
    }
}

impl<K: Internal<V>, V> Eq for EnumMap<K, V> where K::Array: Eq {}

impl<K: Internal<V>, V> Hash for EnumMap<K, V>
    where K::Array: Hash
{
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.array.hash(state);
    }
}

impl<K: Internal<V>, V> Default for EnumMap<K, V>
    where K::Array: Default
{
    fn default() -> Self {
        EnumMap { array: K::Array::default() }
    }
}

impl<K: Internal<V>, V> Index<K> for EnumMap<K, V> {
    type Output = V;

    fn index(&self, key: K) -> &V {
        &K::slice(&self.array)[key.to_usize()]
    }
}

impl<K: Internal<V>, V> IndexMut<K> for EnumMap<K, V> {
    fn index_mut(&mut self, key: K) -> &mut V {
        &mut K::slice_mut(&mut self.array)[key.to_usize()]
    }
}

/// Immutable enum map iterator
///
/// This struct is created by `iter` method or `into_iter` on a reference
/// to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     assert_eq!(map[Example::A], 3);
///     for (key, &value) in &map {
///         assert_eq!(match key {
///             Example::A => 3,
///             _ => 0,
///         }, value);
///     }
/// }
/// ```
pub struct Iter<'a, K, V: 'a> {
    _phantom: PhantomData<K>,
    iterator: Enumerate<slice::Iter<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for Iter<'a, K, V> {
    type Item = (K, &'a V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for Iter<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for Iter<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a EnumMap<K, V> {
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        Iter {
            _phantom: PhantomData,
            iterator: K::slice(&self.array).iter().enumerate(),
        }
    }
}

/// Mutable map iterator
///
/// This struct is created by `iter_mut` method or `into_iter` on a mutable
/// reference to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(Debug, EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     for (_, value) in &mut map {
///         *value += 1;
///     }
///     assert_eq!(map, enum_map! { Example::A => 4, _ => 1 });
/// }
/// ```
pub struct IterMut<'a, K, V: 'a> {
    _phantom: PhantomData<K>,
    iterator: Enumerate<slice::IterMut<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for IterMut<'a, K, V> {
    type Item = (K, &'a mut V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for IterMut<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for IterMut<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a mut EnumMap<K, V> {
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        IterMut {
            _phantom: PhantomData,
            iterator: K::slice_mut(&mut self.array).iter_mut().enumerate(),
        }
    }
}

#[cfg(feature = "serde")]
impl<K: Internal<V> + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (key, value) in self {
            map.serialize_entry(&key, value)?;
        }
        map.end()
    }
}

#[cfg(feature = "serde")]
impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_map(Visitor(PhantomData))
    }
}

#[cfg(feature = "serde")]
struct Visitor<K: Internal<V>, V>(PhantomData<EnumMap<K, V>>);

#[cfg(feature = "serde")]
impl<'de, K, V> de::Visitor<'de> for Visitor<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    type Value = EnumMap<K, V>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "map")
    }

    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
        let mut entries = EnumMap::from(|_| None);
        while let Some((key, value)) = access.next_entry()? {
            entries[key] = Some(value);
        }
        for (_, value) in &entries {
            if value.is_none() {
                return Err(M::Error::custom("key not specified"));
            }
        }
        Ok(EnumMap::from(|key| entries[key].take().unwrap()))
    }
}
<commit_msg>Clarify it's an array type, not just an array in intro<commit_after>//! An enum mapping type.
//!
//! It is implemented using an array type, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! #[macro_use]
//! extern crate enum_map;
//! #[macro_use]
//! extern crate enum_map_derive;
//!
//! use enum_map::EnumMap;
//!
//! #[derive(Debug, EnumMap)]
//! enum Example {
//!     A,
//!     B,
//!     C,
//! }
//!
//! fn main() {
//!     let mut map = enum_map! {
//!         Example::A => 1,
//!         Example::B => 2,
//!         Example::C => 3,
//!     };
//!     map[Example::C] = 4;
//!
//!     assert_eq!(map[Example::A], 1);
//!
//!     for (key, &value) in &map {
//!         println!("{:?} has {} as value.", key, value);
//!     }
//! }
//! ```

#![no_std]
#![deny(missing_docs)]

#[cfg(feature = "serde")]
extern crate serde;

#[cfg(feature = "serde")]
use serde::ser::{Serialize, Serializer, SerializeMap};
#[cfg(feature = "serde")]
use serde::de::{self, Deserialize, Deserializer, Error, MapAccess};

#[cfg(feature = "serde")]
use core::fmt;
use core::hash::{Hash, Hasher};
use core::iter::Enumerate;
use core::marker::PhantomData;
use core::ops::{Index, IndexMut};
use core::slice;

// this is not stable, do not depend on this
#[doc(hidden)]
pub trait Internal<V>: Sized {
    type Array;
    fn slice(&Self::Array) -> &[V];
    fn slice_mut(&mut Self::Array) -> &mut [V];
    fn from_usize(usize) -> Self;
    fn to_usize(self) -> usize;
    fn from_function<F: FnMut(Self) -> V>(F) -> Self::Array;
}

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(EnumMap)]` from `enum_map_derive` crate.
///
/// # Examples
///
/// ```
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// use enum_map::EnumMap;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
#[derive(Debug)]
pub struct EnumMap<K: Internal<V>, V> {
    array: K::Array,
}

impl<K: Internal<V>, V> EnumMap<K, V> {
    /// Returns number of elements in enum map.
    pub fn len(&self) -> usize {
        K::slice(&self.array).len()
    }

    /// Returns an iterator over enum map.
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }
}

impl<F: FnMut(K) -> V, K: Internal<V>, V> From<F> for EnumMap<K, V> {
    fn from(f: F) -> Self {
        EnumMap { array: K::from_function(f) }
    }
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        ::enum_map::EnumMap::from(|k| match k { $($t)* })
    };
}

impl<K: Internal<V>, V: Default> EnumMap<K, V>
    where K::Array: Default
{
    /// Creates an enum map with default values.
    ///
    /// ```
    /// extern crate enum_map;
    /// #[macro_use]
    /// extern crate enum_map_derive;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    pub fn new() -> Self {
        EnumMap::default()
    }
}

// Implementations provided by derive attribute are too specific, and put requirements on K.
// This is caused by rust-lang/rust#26925.
impl<K: Internal<V>, V> Clone for EnumMap<K, V>
    where K::Array: Clone
{
    fn clone(&self) -> Self {
        EnumMap { array: self.array.clone() }
    }
}

impl<K: Internal<V>, V> Copy for EnumMap<K, V> where K::Array: Copy {}

impl<K: Internal<V>, V> PartialEq for EnumMap<K, V>
    where K::Array: PartialEq
{
    fn eq(&self, other: &Self) -> bool {
        self.array == other.array
    }
}

impl<K: Internal<V>, V> Eq for EnumMap<K, V> where K::Array: Eq {}

impl<K: Internal<V>, V> Hash for EnumMap<K, V>
    where K::Array: Hash
{
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.array.hash(state);
    }
}

impl<K: Internal<V>, V> Default for EnumMap<K, V>
    where K::Array: Default
{
    fn default() -> Self {
        EnumMap { array: K::Array::default() }
    }
}

impl<K: Internal<V>, V> Index<K> for EnumMap<K, V> {
    type Output = V;

    fn index(&self, key: K) -> &V {
        &K::slice(&self.array)[key.to_usize()]
    }
}

impl<K: Internal<V>, V> IndexMut<K> for EnumMap<K, V> {
    fn index_mut(&mut self, key: K) -> &mut V {
        &mut K::slice_mut(&mut self.array)[key.to_usize()]
    }
}

/// Immutable enum map iterator
///
/// This struct is created by `iter` method or `into_iter` on a reference
/// to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     assert_eq!(map[Example::A], 3);
///     for (key, &value) in &map {
///         assert_eq!(match key {
///             Example::A => 3,
///             _ => 0,
///         }, value);
///     }
/// }
/// ```
pub struct Iter<'a, K, V: 'a> {
    _phantom: PhantomData<K>,
    iterator: Enumerate<slice::Iter<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for Iter<'a, K, V> {
    type Item = (K, &'a V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for Iter<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for Iter<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a EnumMap<K, V> {
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        Iter {
            _phantom: PhantomData,
            iterator: K::slice(&self.array).iter().enumerate(),
        }
    }
}

/// Mutable map iterator
///
/// This struct is created by `iter_mut` method or `into_iter` on a mutable
/// reference to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(Debug, EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     for (_, value) in &mut map {
///         *value += 1;
///     }
///     assert_eq!(map, enum_map! { Example::A => 4, _ => 1 });
/// }
/// ```
pub struct IterMut<'a, K, V: 'a> {
    _phantom: PhantomData<K>,
    iterator: Enumerate<slice::IterMut<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for IterMut<'a, K, V> {
    type Item = (K, &'a mut V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for IterMut<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for IterMut<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a mut EnumMap<K, V> {
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        IterMut {
            _phantom: PhantomData,
            iterator: K::slice_mut(&mut self.array).iter_mut().enumerate(),
        }
    }
}

#[cfg(feature = "serde")]
impl<K: Internal<V> + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (key, value) in self {
            map.serialize_entry(&key, value)?;
        }
        map.end()
    }
}

#[cfg(feature = "serde")]
impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_map(Visitor(PhantomData))
    }
}

#[cfg(feature = "serde")]
struct Visitor<K: Internal<V>, V>(PhantomData<EnumMap<K, V>>);

#[cfg(feature = "serde")]
impl<'de, K, V> de::Visitor<'de> for Visitor<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    type Value = EnumMap<K, V>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "map")
    }

    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
        let mut entries = EnumMap::from(|_| None);
        while let Some((key, value)) = access.next_entry()? {
            entries[key] = Some(value);
        }
        for (_, value) in &entries {
            if value.is_none() {
                return Err(M::Error::custom("key not specified"));
            }
        }
        Ok(EnumMap::from(|key| entries[key].take().unwrap()))
    }
}
<|endoftext|>


<commit_before>//! An enum mapping type.
//!
//! It is implemented using an array type, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! #[macro_use]
//! extern crate enum_map;
//!
//! use enum_map::EnumMap;
//!
//! #[derive(Debug, EnumMap)]
//! enum Example {
//!     A,
//!     B,
//!     C,
//! }
//!
//! fn main() {
//!     let mut map = enum_map! {
//!         Example::A => 1,
//!         Example::B => 2,
//!         Example::C => 3,
//!     };
//!     map[Example::C] = 4;
//!
//!     assert_eq!(map[Example::A], 1);
//!
//!     for (key, &value) in &map {
//!         println!("{:?} has {} as value.", key, value);
//!     }
//! }
//! ```

#![no_std]
#![deny(missing_docs)]

#[macro_use]
extern crate array_macro;
// This allows to quiet "proc macro crates and `#[no_link]` crates have no
// effect without `#[macro_use]`" warning. Just using extern DOES have
// an effect of letting me export the macro.
#[allow(unused_imports)]
#[macro_use]
extern crate enum_map_derive;

mod enummap_impls;
mod internal;
mod iter;
mod serde;

pub use internal::Internal;
pub use iter::{Iter, IterMut};
// `*` here means re-exporting a derive procedural macro.
pub use enum_map_derive::*;

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(EnumMap)]` from `enum_map_derive` crate.
///
/// Additionally, `bool` and `u8` automatically derives from `EnumMap`. While
/// `u8` is not technically an enum, it's convenient to consider it like one.
/// In particular, [reverse-complement in benchmark game] could be using `u8`
/// as an enum.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// use enum_map::EnumMap;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
///
/// [reverse-complement in benchmark game]:
///     http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2
#[derive(Debug)]
pub struct EnumMap<K: Internal<V>, V> {
    array: K::Array,
}

impl<K: Internal<V>, V: Default> EnumMap<K, V>
where
    K::Array: Default,
{
    /// Creates an enum map with default values.
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    pub fn new() -> Self {
        EnumMap::default()
    }
}

impl<K: Internal<V>, V> EnumMap<K, V> {
    /// Returns number of elements in enum map.
    pub fn len(&self) -> usize {
        K::slice(&self.array).len()
    }

    /// Returns whether the enum variant set is empty.
    ///
    /// This isn't particularly useful, as there is no real reason to use
    /// enum map for enums without variants. However, it is provided for
    /// consistency with data structures providing len method (and I will
    /// admit, to avoid clippy warnings).
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Void {}
    ///
    /// #[derive(EnumMap)]
    /// enum SingleVariant {
    ///     Variant,
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(EnumMap::<Void, ()>::new().is_empty(), true);
    ///     assert_eq!(EnumMap::<SingleVariant, ()>::new().is_empty(), false);
    /// }
    pub fn is_empty(&self) -> bool {
        K::slice(&self.array).is_empty()
    }

    /// Returns an iterator over enum map.
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }

    /// Swaps two indexes.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { false => 0, true => 1 };
    ///     map.swap(false, true);
    ///     assert_eq!(map[false], 1);
    ///     assert_eq!(map[true], 0);
    /// }
    /// ```
    pub fn swap(&mut self, a: K, b: K) {
        K::slice_mut(&mut self.array).swap(a.to_usize(), b.to_usize())
    }

    /// Returns a raw pointer to the enum map's buffer.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// Modifying the container referenced by this slice may cause its buffer
    /// to be reallocated, which would also make any pointers to it invalid.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// fn main() {
    ///     let map = enum_map! { 5 => 42, _ => 0 };
    ///     assert_eq!(unsafe { *map.as_ptr().offset(5) }, 42);
    /// }
    /// ```
    pub fn as_ptr(&self) -> *const V {
        K::slice(&self.array).as_ptr()
    }

    /// Returns an unsafe mutable pointer to the enum map's buffer.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// Modifying the container referenced by this slice may cause its buffer
    /// to be reallocated, which would also make any pointers to it invalid.
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { _ => 0 };
    ///     unsafe {
    ///         *map.as_mut_ptr().offset(11) = 23
    ///     };
    ///     assert_eq!(map[11], 23);
    /// }
    /// ```
    pub fn as_mut_ptr(&mut self) -> *mut V {
        K::slice_mut(&mut self.array).as_mut_ptr()
    }
}

impl<F: FnMut(K) -> V, K: Internal<V>, V> From<F> for EnumMap<K, V> {
    fn from(f: F) -> Self {
        EnumMap { array: K::from_function(f) }
    }
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        $crate::EnumMap::from(|k| match k { $($t)* })
    };
}
<commit_msg>Implement values and values_mut<commit_after>//! An enum mapping type.
//!
//! It is implemented using an array type, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! #[macro_use]
//! extern crate enum_map;
//!
//! use enum_map::EnumMap;
//!
//! #[derive(Debug, EnumMap)]
//! enum Example {
//!     A,
//!     B,
//!     C,
//! }
//!
//! fn main() {
//!     let mut map = enum_map! {
//!         Example::A => 1,
//!         Example::B => 2,
//!         Example::C => 3,
//!     };
//!     map[Example::C] = 4;
//!
//!     assert_eq!(map[Example::A], 1);
//!
//!     for (key, &value) in &map {
//!         println!("{:?} has {} as value.", key, value);
//!     }
//! }
//! ```

#![no_std]
#![deny(missing_docs)]

#[macro_use]
extern crate array_macro;
// This allows to quiet "proc macro crates and `#[no_link]` crates have no
// effect without `#[macro_use]`" warning. Just using extern DOES have
// an effect of letting me export the macro.
#[allow(unused_imports)]
#[macro_use]
extern crate enum_map_derive;

mod enummap_impls;
mod internal;
mod iter;
mod serde;

pub use internal::Internal;
pub use iter::{Iter, IterMut};
// `*` here means re-exporting a derive procedural macro.
pub use enum_map_derive::*;

use core::slice;

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(EnumMap)]` from `enum_map_derive` crate.
///
/// Additionally, `bool` and `u8` automatically derives from `EnumMap`. While
/// `u8` is not technically an enum, it's convenient to consider it like one.
/// In particular, [reverse-complement in benchmark game] could be using `u8`
/// as an enum.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// use enum_map::EnumMap;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
///
/// [reverse-complement in benchmark game]:
///     http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2
#[derive(Debug)]
pub struct EnumMap<K: Internal<V>, V> {
    array: K::Array,
}

impl<K: Internal<V>, V: Default> EnumMap<K, V>
where
    K::Array: Default,
{
    /// Creates an enum map with default values.
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    pub fn new() -> Self {
        EnumMap::default()
    }
}

impl<K: Internal<V>, V> EnumMap<K, V> {
    /// Returns number of elements in enum map.
    pub fn len(&self) -> usize {
        K::slice(&self.array).len()
    }

    /// Returns whether the enum variant set is empty.
    ///
    /// This isn't particularly useful, as there is no real reason to use
    /// enum map for enums without variants. However, it is provided for
    /// consistency with data structures providing len method (and I will
    /// admit, to avoid clippy warnings).
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Void {}
    ///
    /// #[derive(EnumMap)]
    /// enum SingleVariant {
    ///     Variant,
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(EnumMap::<Void, ()>::new().is_empty(), true);
    ///     assert_eq!(EnumMap::<SingleVariant, ()>::new().is_empty(), false);
    /// }
    pub fn is_empty(&self) -> bool {
        K::slice(&self.array).is_empty()
    }

    /// Returns an iterator over enum map.
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }

    /// Swaps two indexes.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { false => 0, true => 1 };
    ///     map.swap(false, true);
    ///     assert_eq!(map[false], 1);
    ///     assert_eq!(map[true], 0);
    /// }
    /// ```
    pub fn swap(&mut self, a: K, b: K) {
        K::slice_mut(&mut self.array).swap(a.to_usize(), b.to_usize())
    }

    /// An iterator visiting all values. The iterator type is `&V`.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let map = enum_map! { false => 3, true => 4 };
    ///     let mut values = map.values();
    ///     assert_eq!(values.next(), Some(&3));
    ///     assert_eq!(values.next(), Some(&4));
    ///     assert_eq!(values.next(), None);
    /// }
    /// ```
    pub fn values(&self) -> slice::Iter<V> {
        K::slice(&self.array).iter()
    }

    /// An iterator visiting all values mutably. The iterator type is `&mut V`.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { _ => 2 };
    ///     for value in map.values_mut() {
    ///         *value += 2;
    ///     }
    ///     assert_eq!(map[false], 4);
    ///     assert_eq!(map[true], 4);
    /// }
    /// ```
    pub fn values_mut(&mut self) -> slice::IterMut<V> {
        K::slice_mut(&mut self.array).iter_mut()
    }

    /// Returns a raw pointer to the enum map's buffer.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// Modifying the container referenced by this slice may cause its buffer
    /// to be reallocated, which would also make any pointers to it invalid.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// fn main() {
    ///     let map = enum_map! { 5 => 42, _ => 0 };
    ///     assert_eq!(unsafe { *map.as_ptr().offset(5) }, 42);
    /// }
    /// ```
    pub fn as_ptr(&self) -> *const V {
        K::slice(&self.array).as_ptr()
    }

    /// Returns an unsafe mutable pointer to the enum map's buffer.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// Modifying the container referenced by this slice may cause its buffer
    /// to be reallocated, which would also make any pointers to it invalid.
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { _ => 0 };
    ///     unsafe {
    ///         *map.as_mut_ptr().offset(11) = 23
    ///     };
    ///     assert_eq!(map[11], 23);
    /// }
    /// ```
    pub fn as_mut_ptr(&mut self) -> *mut V {
        K::slice_mut(&mut self.array).as_mut_ptr()
    }
}

impl<F: FnMut(K) -> V, K: Internal<V>, V> From<F> for EnumMap<K, V> {
    fn from(f: F) -> Self {
        EnumMap { array: K::from_function(f) }
    }
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        $crate::EnumMap::from(|k| match k { $($t)* })
    };
}
<|endoftext|>