<commit_before>//! This module contains definition of table rows stuff
use std::io::{Write, Error};
use std::iter::FromIterator;
use std::slice::{Iter, IterMut};
use std::ops::{Index, IndexMut};

use term::Terminal;

use super::utils::NEWLINE;
use super::cell::Cell;
use super::format::{TableFormat, ColumnPosition};

/// Represent a table row made of cells
#[derive(Clone, Debug)]
pub struct Row {
    cells: Vec<Cell>,
}

impl Row {
    /// Create a new `Row` backed with `cells` vector
    pub fn new(cells: Vec<Cell>) -> Row {
        Row { cells: cells }
    }

    /// Create an row of length `size`, with empty strings stored
    pub fn empty() -> Row {
        Self::new(vec![Cell::default(); 0])
    }

    /// Get the number of cells in this row
    pub fn len(&self) -> usize {
        self.cells.len()
    }

    /// Check if the row is empty (has no cell)
    pub fn is_empty(&self) -> bool {
        self.cells.is_empty()
    }

    /// Get the height of this row
    pub fn get_height(&self) -> usize {
        let mut height = 1; // Minimum height must be 1 to print empty rows
        for cell in &self.cells {
            let h = cell.get_height();
            if h > height {
                height = h;
            }
        }
        height
    }

    /// Get the minimum width required by the cell in the column `column`.
    /// Return 0 if the cell does not exist in this row
    pub fn get_cell_width(&self, column: usize) -> usize {
        self.cells
            .get(column)
            .map(|cell| cell.get_width())
            .unwrap_or(0)
    }

    /// Get the cell at index `idx`
    pub fn get_cell(&self, idx: usize) -> Option<&Cell> {
        self.cells.get(idx)
    }

    /// Get the mutable cell at index `idx`
    pub fn get_mut_cell(&mut self, idx: usize) -> Option<&mut Cell> {
        self.cells.get_mut(idx)
    }

    /// Set the `cell` in the row at the given `column`
    pub fn set_cell(&mut self, cell: Cell, column: usize) -> Result<(), &str> {
        if column >= self.len() {
            return Err("Cannot find cell");
        }
        self.cells[column] = cell;
        Ok(())
    }

    /// Append a `cell` at the end of the row
    pub fn add_cell(&mut self, cell: Cell) {
        self.cells.push(cell);
    }

    /// Insert `cell` at position `index`. If `index` is higher than the row length,
    /// the cell will be appended at the end
    pub fn insert_cell(&mut self, index: usize, cell: Cell) {
        if index < self.cells.len() {
            self.cells.insert(index, cell);
        } else {
            self.add_cell(cell);
        }
    }

    /// Remove the cell at position `index`. Silently skip if this cell does not exist
    pub fn remove_cell(&mut self, index: usize) {
        if index < self.cells.len() {
            self.cells.remove(index);
        }
    }

    /// Returns an immutable iterator over cells
    pub fn iter(&self) -> Iter<Cell> {
        self.cells.iter()
    }

    /// Returns an mutable iterator over cells
    pub fn iter_mut(&mut self) -> IterMut<Cell> {
        self.cells.iter_mut()
    }

    /// Internal only
    fn __print<T: Write + ?Sized, F>(&self,
                                     out: &mut T,
                                     format: &TableFormat,
                                     col_width: &[usize],
                                     f: F)
                                     -> Result<(), Error>
        where F: Fn(&Cell, &mut T, usize, usize, bool) -> Result<(), Error>
    {
        for i in 0..self.get_height() {
            //TODO: Wrap this into dedicated function one day
            try!(out.write_all(&vec![b' '; format.get_indent()]));
            try!(format.print_column_separator(out, ColumnPosition::Left));
            let (lp, rp) = format.get_padding();
            for j in 0..col_width.len() {
                try!(out.write_all(&vec![b' '; lp]));
                let skip_r_fill = (j == col_width.len() - 1) &&
                                  format.get_column_separator(ColumnPosition::Right).is_none();
                match self.get_cell(j) {
                    Some(c) => try!(f(c, out, i, col_width[j], skip_r_fill)),
                    None => try!(f(&Cell::default(), out, i, col_width[j], skip_r_fill)),
                };
                try!(out.write_all(&vec![b' '; rp]));
                if j < col_width.len() - 1 {
                    try!(format.print_column_separator(out, ColumnPosition::Intern));
                }
            }
            try!(format.print_column_separator(out, ColumnPosition::Right));
            try!(out.write_all(NEWLINE));
        }
        Ok(())
    }

    /// Print the row to `out`, with `separator` as column separator, and `col_width`
    /// specifying the width of each columns
    pub fn print<T: Write + ?Sized>(&self,
                                    out: &mut T,
                                    format: &TableFormat,
                                    col_width: &[usize])
                                    -> Result<(), Error> {
        self.__print(out, format, col_width, Cell::print)
    }

    /// Print the row to terminal `out`, with `separator` as column separator, and `col_width`
    /// specifying the width of each columns. Apply style when needed
    pub fn print_term<T: Terminal + ?Sized>(&self,
                                            out: &mut T,
                                            format: &TableFormat,
                                            col_width: &[usize])
                                            -> Result<(), Error> {
        self.__print(out, format, col_width, Cell::print_term)
    }
}

impl Default for Row {
    fn default() -> Row {
        Row::empty()
    }
}

impl Index<usize> for Row {
    type Output = Cell;
    fn index(&self, idx: usize) -> &Self::Output {
        &self.cells[idx]
    }
}

impl IndexMut<usize> for Row {
    fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
        &mut self.cells[idx]
    }
}

impl<A: ToString> FromIterator<A> for Row {
    fn from_iter<T>(iterator: T) -> Row
        where T: IntoIterator<Item = A>
    {
        Self::new(iterator.into_iter().map(|ref e| Cell::from(e)).collect())
    }
}

impl<T, A> From<T> for Row
    where A: ToString,
          T: IntoIterator<Item = A>
{
    fn from(it: T) -> Row {
        Self::from_iter(it)
    }
}

impl<'a> IntoIterator for &'a Row {
    type Item = &'a Cell;
    type IntoIter = Iter<'a, Cell>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> IntoIterator for &'a mut Row {
    type Item = &'a mut Cell;
    type IntoIter = IterMut<'a, Cell>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

/// This macro simplifies `Row` creation
///
/// The syntax support style spec
/// # Example
/// ```
/// # #[macro_use] extern crate prettytable;
/// # fn main() {
/// // Create a normal row
/// let row1 = row!["Element 1", "Element 2", "Element 3"];
/// // Create a row with all cells formatted with red foreground color, yellow background color
/// // bold, italic, align in the center of the cell
/// let row2 = row![FrBybic => "Element 1", "Element 2", "Element 3"];
/// // Create a row with first cell in blue, second one in red, and last one with default style
/// let row3 = row![Fb->"blue", Fr->"red", "normal"];
/// // Do something with rows
/// # drop(row1);
/// # drop(row2);
/// # drop(row3);
/// # }
/// ```
///
/// For details about style specifier syntax, check doc for [`Cell::style_spec`](cell/struct.Cell.html#method.style_spec) method
#[macro_export]
macro_rules! row {
    (($($out:tt)*); $value:expr) => (vec![$($out)* cell!($value)]);
    (($($out:tt)*); $value:expr, $($n:tt)*) => (row!(($($out)* cell!($value),); $($n)*));
    (($($out:tt)*); $style:ident -> $value:expr) => (vec![$($out)* cell!($style -> $value)]);
    (($($out:tt)*); $style:ident -> $value:expr, $($n: tt)*) => (row!(($($out)* cell!($style -> $value),); $($n)*));

    ($($content:expr), *) => ($crate::row::Row::new(vec![$(cell!($content)), *]));
    ($style:ident => $($content:expr), *) => ($crate::row::Row::new(vec![$(cell!($style -> $content)), *]));
    ($($content:tt)*) => ($crate::row::Row::new(row!((); $($content)*)));
}

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

    #[test]
    fn row_default_empty() {
        let row1 = Row::default();
        assert_eq!(row1.len(), 0);
        assert!(row1.is_empty());
    }

    #[test]
    fn get_add_set_cell() {
        let mut row = Row::from(vec!["foo", "bar", "foobar"]);
        assert_eq!(row.len(), 3);
        assert!(row.get_mut_cell(12).is_none());
        let c1 = row.get_mut_cell(0).unwrap().clone();
        assert_eq!(c1.get_content(), "foo");

        let c1 = Cell::from(&"baz");
        assert!(row.set_cell(c1.clone(), 0).is_ok());
        assert_eq!(row.get_cell(0).unwrap().get_content(), "baz");

        row.add_cell(c1.clone());
        assert_eq!(row.len(), 4);
        assert_eq!(row.get_cell(3).unwrap().get_content(), "baz");
    }

    #[test]
    fn insert_cell() {
        let mut row = Row::from(vec!["foo", "bar", "foobar"]);
        assert_eq!(row.len(), 3);
        let cell = Cell::new("baz");
        row.insert_cell(1000, cell.clone());
        assert_eq!(row.len(), 4);
        assert_eq!(row.get_cell(3).unwrap().get_content(), "baz");
        row.insert_cell(1, cell.clone());
        assert_eq!(row.len(), 5);
        assert_eq!(row.get_cell(1).unwrap().get_content(), "baz");
    }

    #[test]
    fn remove_cell() {
        let mut row = Row::from(vec!["foo", "bar", "foobar"]);
        assert_eq!(row.len(), 3);
        row.remove_cell(1000);
        assert_eq!(row.len(), 3);
        row.remove_cell(1);
        assert_eq!(row.len(), 2);
        assert_eq!(row.get_cell(0).unwrap().get_content(), "foo");
        assert_eq!(row.get_cell(1).unwrap().get_content(), "foobar");
    }
}<commit_msg>Fixed broken build for rust 1.9.0 to 1.14.0<commit_after>//! This module contains definition of table rows stuff
use std::io::{Write, Error};
use std::iter::FromIterator;
use std::slice::{Iter, IterMut};
use std::ops::{Index, IndexMut};

use term::Terminal;

use super::utils::NEWLINE;
use super::cell::Cell;
use super::format::{TableFormat, ColumnPosition};

/// Represent a table row made of cells
#[derive(Clone, Debug)]
pub struct Row {
    cells: Vec<Cell>,
}

impl Row {
    /// Create a new `Row` backed with `cells` vector
    pub fn new(cells: Vec<Cell>) -> Row {
        Row { cells: cells }
    }

    /// Create an row of length `size`, with empty strings stored
    pub fn empty() -> Row {
        Self::new(vec![Cell::default(); 0])
    }

    /// Get the number of cells in this row
    pub fn len(&self) -> usize {
        self.cells.len()
    }

    /// Check if the row is empty (has no cell)
    pub fn is_empty(&self) -> bool {
        self.cells.is_empty()
    }

    /// Get the height of this row
    pub fn get_height(&self) -> usize {
        let mut height = 1; // Minimum height must be 1 to print empty rows
        for cell in &self.cells {
            let h = cell.get_height();
            if h > height {
                height = h;
            }
        }
        height
    }

    /// Get the minimum width required by the cell in the column `column`.
    /// Return 0 if the cell does not exist in this row
    pub fn get_cell_width(&self, column: usize) -> usize {
        self.cells
            .get(column)
            .map(|cell| cell.get_width())
            .unwrap_or(0)
    }

    /// Get the cell at index `idx`
    pub fn get_cell(&self, idx: usize) -> Option<&Cell> {
        self.cells.get(idx)
    }

    /// Get the mutable cell at index `idx`
    pub fn get_mut_cell(&mut self, idx: usize) -> Option<&mut Cell> {
        self.cells.get_mut(idx)
    }

    /// Set the `cell` in the row at the given `column`
    pub fn set_cell(&mut self, cell: Cell, column: usize) -> Result<(), &str> {
        if column >= self.len() {
            return Err("Cannot find cell");
        }
        self.cells[column] = cell;
        Ok(())
    }

    /// Append a `cell` at the end of the row
    pub fn add_cell(&mut self, cell: Cell) {
        self.cells.push(cell);
    }

    /// Insert `cell` at position `index`. If `index` is higher than the row length,
    /// the cell will be appended at the end
    pub fn insert_cell(&mut self, index: usize, cell: Cell) {
        if index < self.cells.len() {
            self.cells.insert(index, cell);
        } else {
            self.add_cell(cell);
        }
    }

    /// Remove the cell at position `index`. Silently skip if this cell does not exist
    pub fn remove_cell(&mut self, index: usize) {
        if index < self.cells.len() {
            self.cells.remove(index);
        }
    }

    /// Returns an immutable iterator over cells
    pub fn iter(&self) -> Iter<Cell> {
        self.cells.iter()
    }

    /// Returns an mutable iterator over cells
    pub fn iter_mut(&mut self) -> IterMut<Cell> {
        self.cells.iter_mut()
    }

    /// Internal only
    fn __print<T: Write + ?Sized, F>(&self,
                                     out: &mut T,
                                     format: &TableFormat,
                                     col_width: &[usize],
                                     f: F)
                                     -> Result<(), Error>
        where F: Fn(&Cell, &mut T, usize, usize, bool) -> Result<(), Error>
    {
        for i in 0..self.get_height() {
            //TODO: Wrap this into dedicated function one day
            try!(out.write_all(&vec![b' '; format.get_indent()]));
            try!(format.print_column_separator(out, ColumnPosition::Left));
            let (lp, rp) = format.get_padding();
            for j in 0..col_width.len() {
                try!(out.write_all(&vec![b' '; lp]));
                let skip_r_fill = (j == col_width.len() - 1) &&
                                  format.get_column_separator(ColumnPosition::Right).is_none();
                match self.get_cell(j) {
                    Some(c) => try!(f(c, out, i, col_width[j], skip_r_fill)),
                    None => try!(f(&Cell::default(), out, i, col_width[j], skip_r_fill)),
                };
                try!(out.write_all(&vec![b' '; rp]));
                if j < col_width.len() - 1 {
                    try!(format.print_column_separator(out, ColumnPosition::Intern));
                }
            }
            try!(format.print_column_separator(out, ColumnPosition::Right));
            try!(out.write_all(NEWLINE));
        }
        Ok(())
    }

    /// Print the row to `out`, with `separator` as column separator, and `col_width`
    /// specifying the width of each columns
    pub fn print<T: Write + ?Sized>(&self,
                                    out: &mut T,
                                    format: &TableFormat,
                                    col_width: &[usize])
                                    -> Result<(), Error> {
        self.__print(out, format, col_width, Cell::print)
    }

    /// Print the row to terminal `out`, with `separator` as column separator, and `col_width`
    /// specifying the width of each columns. Apply style when needed
    pub fn print_term<T: Terminal + ?Sized>(&self,
                                            out: &mut T,
                                            format: &TableFormat,
                                            col_width: &[usize])
                                            -> Result<(), Error> {
        self.__print(out, format, col_width, Cell::print_term)
    }
}

impl Default for Row {
    fn default() -> Row {
        Row::empty()
    }
}

impl Index<usize> for Row {
    type Output = Cell;
    fn index(&self, idx: usize) -> &Self::Output {
        &self.cells[idx]
    }
}

impl IndexMut<usize> for Row {
    fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
        &mut self.cells[idx]
    }
}

impl<A: ToString> FromIterator<A> for Row {
    fn from_iter<T>(iterator: T) -> Row
        where T: IntoIterator<Item = A>
    {
        Self::new(iterator.into_iter().map(|ref e| Cell::from(e)).collect())
    }
}

impl<T, A> From<T> for Row
    where A: ToString,
          T: IntoIterator<Item = A>
{
    fn from(it: T) -> Row {
        Self::from_iter(it)
    }
}

impl<'a> IntoIterator for &'a Row {
    type Item = &'a Cell;
    type IntoIter = Iter<'a, Cell>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> IntoIterator for &'a mut Row {
    type Item = &'a mut Cell;
    type IntoIter = IterMut<'a, Cell>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

/// This macro simplifies `Row` creation
///
/// The syntax support style spec
/// # Example
/// ```
/// # #[macro_use] extern crate prettytable;
/// # fn main() {
/// // Create a normal row
/// let row1 = row!["Element 1", "Element 2", "Element 3"];
/// // Create a row with all cells formatted with red foreground color, yellow background color
/// // bold, italic, align in the center of the cell
/// let row2 = row![FrBybic => "Element 1", "Element 2", "Element 3"];
/// // Create a row with first cell in blue, second one in red, and last one with default style
/// let row3 = row![Fb->"blue", Fr->"red", "normal"];
/// // Do something with rows
/// # drop(row1);
/// # drop(row2);
/// # drop(row3);
/// # }
/// ```
///
/// For details about style specifier syntax, check doc for [`Cell::style_spec`](cell/struct.Cell.html#method.style_spec) method
#[macro_export]
macro_rules! row {
    (($($out:tt)*); $value:expr) => (vec![$($out)* cell!($value)]);
    (($($out:tt)*); $value:expr, $($n:tt)*) => (row!(($($out)* cell!($value),); $($n)*));
    (($($out:tt)*); $style:ident -> $value:expr) => (vec![$($out)* cell!($style -> $value)]);
    (($($out:tt)*); $style:ident -> $value:expr, $($n: tt)*) => (row!(($($out)* cell!($style -> $value),); $($n)*));

    ($($content:expr), *) => ($crate::row::Row::new(vec![$(cell!($content)), *]));
    ($style:ident => $($content:expr), *) => ($crate::row::Row::new(vec![$(cell!($style -> $content)), *]));
    ($($content:tt)*) => ($crate::row::Row::new(row!((); $($content)*)));
}

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

    #[test]
    fn row_default_empty() {
        let row1 = Row::default();
        assert_eq!(row1.len(), 0);
        assert!(row1.is_empty());
    }

    #[test]
    fn get_add_set_cell() {
        let mut row = Row::from(vec!["foo", "bar", "foobar"]);
        assert_eq!(row.len(), 3);
        assert!(row.get_mut_cell(12).is_none());
        let c1 = row.get_mut_cell(0).unwrap().clone();
        assert_eq!(c1.get_content(), "foo");

        let c1 = Cell::from(&"baz");
        assert!(row.set_cell(c1.clone(), 1000).is_err());
        assert!(row.set_cell(c1.clone(), 0).is_ok());
        assert_eq!(row.get_cell(0).unwrap().get_content(), "baz");

        row.add_cell(c1.clone());
        assert_eq!(row.len(), 4);
        assert_eq!(row.get_cell(3).unwrap().get_content(), "baz");
    }

    #[test]
    fn insert_cell() {
        let mut row = Row::from(vec!["foo", "bar", "foobar"]);
        assert_eq!(row.len(), 3);
        let cell = Cell::new("baz");
        row.insert_cell(1000, cell.clone());
        assert_eq!(row.len(), 4);
        assert_eq!(row.get_cell(3).unwrap().get_content(), "baz");
        row.insert_cell(1, cell.clone());
        assert_eq!(row.len(), 5);
        assert_eq!(row.get_cell(1).unwrap().get_content(), "baz");
    }

    #[test]
    fn remove_cell() {
        let mut row = Row::from(vec!["foo", "bar", "foobar"]);
        assert_eq!(row.len(), 3);
        row.remove_cell(1000);
        assert_eq!(row.len(), 3);
        row.remove_cell(1);
        assert_eq!(row.len(), 2);
        assert_eq!(row.get_cell(0).unwrap().get_content(), "foo");
        assert_eq!(row.get_cell(1).unwrap().get_content(), "foobar");
    }
}<|endoftext|>


<commit_before>use std::io;
use std::to_str::ToStr;
use std::os::{pipe, change_dir};
use std::io::{Open, Write};
use std::io::fs::{mkdir, File};
use std::io::pipe::PipeStream;
use std::io::stdio::{stdout, stderr};

use argparse::{ArgumentParser, Store, List};

use super::env::Environ;
use super::config::Config;
use super::linux::{make_namespace, change_root, bind_mount, mount_pseudofs};
use super::linux::{execute, forkme, wait_process};
use libc::funcs::posix88::unistd::getuid;

fn mount_all(root: &Path, mount_dir: &Path, project_root: &Path)
    -> Result<(), String>
{
    let vagga_marker = mount_dir.join_many(["tmp", ".vagga"]);
    try!(bind_mount(root, mount_dir, false));
    try!(bind_mount(&Path::new("/sys"), &mount_dir.join("sys"), false));
    // TODO(tailhook) use dev in /var/lib/container-dev
    try!(bind_mount(&Path::new("/dev"), &mount_dir.join("dev"), false));
    try!(bind_mount(project_root, &mount_dir.join("work"), true));
    try!(mount_pseudofs("proc", &mount_dir.join("proc"), ""));
    // TODO(tailhook) allow customize size of tmpfs
    try!(mount_pseudofs("tmpfs", &mount_dir.join("tmp"),
                        "size=102400k,mode=1777"));
    try!(ensure_dir(&vagga_marker));
    try!(bind_mount(&vagga_marker,
                    &mount_dir.join_many(["work", ".vagga"]),
                    false));
    match File::open_mode(&vagga_marker.join("CONTAINED.txt"), Open, Write)
        .write_line("You are running in vagga container.") {
        Ok(()) => {}
        Err(e) => return Err(format!("Can't write CONTAINED.txt: {}", e)),
    }
    return Ok(());
}

fn ensure_dir(p: &Path) -> Result<(),String> {
    if p.exists() {
        return Ok(());
    }
    return mkdir(p, io::UserRWX).map_err(|e| { e.to_str() });
}

pub fn run_chroot(env: &Environ, container_root: &Path, mount_dir: &Path,
    command: &String, args: &Vec<String>)
    -> Result<(),String>
{
    try!(mount_all(container_root, mount_dir, &env.project_root));
    debug!("Changing directory to {}", mount_dir.display());
    change_dir(mount_dir);
    try!(change_root(mount_dir));
    let reldir = match env.work_dir.path_relative_from(&env.project_root) {
        Some(path) => path,
        None => Path::new(""),
    };
    let path = Path::new("/work").join(reldir);
    debug!("Changing directory to {}", path.display());
    change_dir(&path);

    // TODO(tailhook) set environment from config
    let environ = vec!(
        "PATH=/bin:/usr/bin:/usr/local/bin".to_string(),
        "HOME=/non-existent".to_string(),
        );
    try!(execute(command, args, &environ));
    unreachable!();
}

pub fn run_user_command(env: &Environ, config: &Config,
    cmdname: &String, args: Vec<String>)
    -> Result<int, String>
{
    let command = match config.commands.find(cmdname) {
        Some(c) => c,
        None => {
            return Err(format!("Can't find command {} in config",
                               cmdname));
        }
    };
    let cname = match command.container {
        Some(ref name) => name.clone(),
        None => unimplemented!(),
    };
    match config.containers.find(&cname) {
        Some(c) => c,
        None => {
            return Err(format!("Can't find container {} for command {}",
                               command.container, cmdname));
        }
    };
    return match command.run {
        Some(ref cmdline) => _run(env, config, &cname,
            &"/bin/sh".to_string(),
            &(vec!("-c".to_string(), cmdline.clone()) + args.slice_from(1))),
        None => unimplemented!()
    }
}

pub fn run_command(env: &Environ, config: &Config, args: Vec<String>)
    -> Result<int, String>
{
    let mut cname = "devel".to_string();
    let mut command = "".to_string();
    let mut cmdargs = Vec::new();
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut cname)
            .add_argument("container", box Store::<String>,
                "A name of the container to build")
            .required();
        ap.refer(&mut command)
            .add_argument("command", box Store::<String>,
                "A command to run inside container")
            .required();
        ap.refer(&mut cmdargs)
            .add_argument("arguments", box List::<String>,
                "Arguments for the command")
            .required();
        ap.stop_on_first_argument(true);
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => return Ok(122),
        }
    }
    match config.containers.find(&cname) {
        Some(c) => c,
        None => {
            return Err(format!("Can't find container {} in config",
                               cname));
        }
    };
    _run(env, config, &cname, &command, &cmdargs)
}

pub fn _run(env: &Environ, config: &Config, container: &String,
    command: &String, cmdargs: &Vec<String>)
    -> Result<int, String>
{
    info!("Running {}: {} {}", container, command, cmdargs);
    let container_dir = env.project_root.join_many(
        [".vagga", container.as_slice()]);
    let container_root = container_dir.join("root");
    let uid = unsafe { getuid() };

    for dir in ["proc", "sys", "dev", "work", "tmp"].iter() {
        try!(ensure_dir(&container_root.join(*dir)));
    }

    let mount_dir = env.project_root.join_many([".vagga", "mnt"]);
    try!(ensure_dir(&mount_dir));
    try!(make_namespace());

    let mut pipe = match PipeStream::pair() {
        Ok(pipe) => pipe,
        Err(x) => return Err(format!("Can't create pipe: {}", x)),
    };

    let pid = try!(forkme());
    if pid == 0 {
        let mut buf: [u8,..1] = [0];
        match pipe.reader.read(buf) {
            Ok(_) => {}
            Err(x) => return Err(format!("Can't read from pipe: {}", x)),
        }
        drop(pipe);
        try!(run_chroot(env, &container_root, &mount_dir, command, cmdargs));
        unreachable!();
    } else {
        // TODO(tailhook) set uid map from config
        let uid_map = format!("0 {} 1", uid);
        debug!("Writing uid_map: {}", uid_map);
        match File::open_mode(&Path::new("/proc")
                          .join(pid.to_str())
                          .join("uid_map"), Open, Write)
                .write_str(uid_map.as_slice()) {
            Ok(()) => {}
            Err(e) => return Err(format!(
                "Error writing uid mapping: {}", e)),
        }

        match pipe.writer.write_char('x') {
            Ok(_) => {}
            Err(e) => return Err(format!(
                "Error writing to pipe: {}", e)),
        }
        drop(pipe);

        return wait_process(pid);
    }
}
<commit_msg>Add TERM variable to `_run` environment<commit_after>use std::io;
use std::to_str::ToStr;
use std::os::{pipe, change_dir, getenv};
use std::io::{Open, Write};
use std::io::fs::{mkdir, File};
use std::io::pipe::PipeStream;
use std::io::stdio::{stdout, stderr};

use argparse::{ArgumentParser, Store, List};

use super::env::Environ;
use super::config::Config;
use super::linux::{make_namespace, change_root, bind_mount, mount_pseudofs};
use super::linux::{execute, forkme, wait_process};
use libc::funcs::posix88::unistd::getuid;

fn mount_all(root: &Path, mount_dir: &Path, project_root: &Path)
    -> Result<(), String>
{
    let vagga_marker = mount_dir.join_many(["tmp", ".vagga"]);
    try!(bind_mount(root, mount_dir, false));
    try!(bind_mount(&Path::new("/sys"), &mount_dir.join("sys"), false));
    // TODO(tailhook) use dev in /var/lib/container-dev
    try!(bind_mount(&Path::new("/dev"), &mount_dir.join("dev"), false));
    try!(bind_mount(project_root, &mount_dir.join("work"), true));
    try!(mount_pseudofs("proc", &mount_dir.join("proc"), ""));
    // TODO(tailhook) allow customize size of tmpfs
    try!(mount_pseudofs("tmpfs", &mount_dir.join("tmp"),
                        "size=102400k,mode=1777"));
    try!(ensure_dir(&vagga_marker));
    try!(bind_mount(&vagga_marker,
                    &mount_dir.join_many(["work", ".vagga"]),
                    false));
    match File::open_mode(&vagga_marker.join("CONTAINED.txt"), Open, Write)
        .write_line("You are running in vagga container.") {
        Ok(()) => {}
        Err(e) => return Err(format!("Can't write CONTAINED.txt: {}", e)),
    }
    return Ok(());
}

fn ensure_dir(p: &Path) -> Result<(),String> {
    if p.exists() {
        return Ok(());
    }
    return mkdir(p, io::UserRWX).map_err(|e| { e.to_str() });
}

pub fn run_chroot(env: &Environ, container_root: &Path, mount_dir: &Path,
    command: &String, args: &Vec<String>)
    -> Result<(),String>
{
    try!(mount_all(container_root, mount_dir, &env.project_root));
    debug!("Changing directory to {}", mount_dir.display());
    change_dir(mount_dir);
    try!(change_root(mount_dir));
    let reldir = match env.work_dir.path_relative_from(&env.project_root) {
        Some(path) => path,
        None => Path::new(""),
    };
    let path = Path::new("/work").join(reldir);
    debug!("Changing directory to {}", path.display());
    change_dir(&path);

    // TODO(tailhook) set environment from config
    let environ = vec!(
        "PATH=/bin:/usr/bin:/usr/local/bin".to_string(),
        "HOME=/non-existent".to_string(),
        "TERM=".to_string() + getenv("TERM").unwrap_or("linux".to_string()),
        );
    try!(execute(command, args, &environ));
    unreachable!();
}

pub fn run_user_command(env: &Environ, config: &Config,
    cmdname: &String, args: Vec<String>)
    -> Result<int, String>
{
    let command = match config.commands.find(cmdname) {
        Some(c) => c,
        None => {
            return Err(format!("Can't find command {} in config",
                               cmdname));
        }
    };
    let cname = match command.container {
        Some(ref name) => name.clone(),
        None => unimplemented!(),
    };
    match config.containers.find(&cname) {
        Some(c) => c,
        None => {
            return Err(format!("Can't find container {} for command {}",
                               command.container, cmdname));
        }
    };
    return match command.run {
        Some(ref cmdline) => _run(env, config, &cname,
            &"/bin/sh".to_string(),
            &(vec!("-c".to_string(), cmdline.clone()) + args.slice_from(1))),
        None => unimplemented!()
    }
}

pub fn run_command(env: &Environ, config: &Config, args: Vec<String>)
    -> Result<int, String>
{
    let mut cname = "devel".to_string();
    let mut command = "".to_string();
    let mut cmdargs = Vec::new();
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut cname)
            .add_argument("container", box Store::<String>,
                "A name of the container to build")
            .required();
        ap.refer(&mut command)
            .add_argument("command", box Store::<String>,
                "A command to run inside container")
            .required();
        ap.refer(&mut cmdargs)
            .add_argument("arguments", box List::<String>,
                "Arguments for the command")
            .required();
        ap.stop_on_first_argument(true);
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => return Ok(122),
        }
    }
    match config.containers.find(&cname) {
        Some(c) => c,
        None => {
            return Err(format!("Can't find container {} in config",
                               cname));
        }
    };
    _run(env, config, &cname, &command, &cmdargs)
}

pub fn _run(env: &Environ, config: &Config, container: &String,
    command: &String, cmdargs: &Vec<String>)
    -> Result<int, String>
{
    info!("Running {}: {} {}", container, command, cmdargs);
    let container_dir = env.project_root.join_many(
        [".vagga", container.as_slice()]);
    let container_root = container_dir.join("root");
    let uid = unsafe { getuid() };

    for dir in ["proc", "sys", "dev", "work", "tmp"].iter() {
        try!(ensure_dir(&container_root.join(*dir)));
    }

    let mount_dir = env.project_root.join_many([".vagga", "mnt"]);
    try!(ensure_dir(&mount_dir));
    try!(make_namespace());

    let mut pipe = match PipeStream::pair() {
        Ok(pipe) => pipe,
        Err(x) => return Err(format!("Can't create pipe: {}", x)),
    };

    let pid = try!(forkme());
    if pid == 0 {
        let mut buf: [u8,..1] = [0];
        match pipe.reader.read(buf) {
            Ok(_) => {}
            Err(x) => return Err(format!("Can't read from pipe: {}", x)),
        }
        drop(pipe);
        try!(run_chroot(env, &container_root, &mount_dir, command, cmdargs));
        unreachable!();
    } else {
        // TODO(tailhook) set uid map from config
        let uid_map = format!("0 {} 1", uid);
        debug!("Writing uid_map: {}", uid_map);
        match File::open_mode(&Path::new("/proc")
                          .join(pid.to_str())
                          .join("uid_map"), Open, Write)
                .write_str(uid_map.as_slice()) {
            Ok(()) => {}
            Err(e) => return Err(format!(
                "Error writing uid mapping: {}", e)),
        }

        match pipe.writer.write_char('x') {
            Ok(_) => {}
            Err(e) => return Err(format!(
                "Error writing to pipe: {}", e)),
        }
        drop(pipe);

        return wait_process(pid);
    }
}
<|endoftext|>


<commit_before>use std::{error, fmt, thread};

use futures::{Sink, Future};
use futures::sync::mpsc::{channel, Receiver};
use rusoto_core::{self, default_tls_client, DefaultCredentialsProvider, Region};
use rusoto_sqs::{self, Sqs, SqsClient, ReceiveMessageRequest};

#[derive(Debug)]
pub enum Error {
    Credentials(rusoto_core::CredentialsError),
    Tls(rusoto_core::TlsError),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Credentials(ref err) => fmt::Display::fmt(err, f),
            Error::Tls(ref err) => fmt::Display::fmt(err, f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Credentials(ref err) => err.description(),
            Error::Tls(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Credentials(ref err) => err.cause(),
            Error::Tls(ref err) => err.cause(),
        }
    }
}

impl From<rusoto_core::CredentialsError> for Error {
    fn from(err: rusoto_core::CredentialsError) -> Self {
        Error::Credentials(err)
    }
}

impl From<rusoto_core::TlsError> for Error {
    fn from(err: rusoto_core::TlsError) -> Self {
        Error::Tls(err)
    }
}

pub fn sqs_receiver(queue_url: String) -> Result<Receiver<rusoto_sqs::Message>, Error> {
    let aws_credentials = DefaultCredentialsProvider::new()?;
    let sqs_client = SqsClient::new(default_tls_client()?, aws_credentials, Region::EuCentral1);
    let mut receive_req = ReceiveMessageRequest::default();
    receive_req.queue_url = queue_url;
    receive_req.wait_time_seconds = Some(10);

    let (tx, rx) = channel(1);
    thread::spawn(move || -> Result<(), ()> {
        loop {
            let resp = sqs_client.receive_message(&receive_req);
            match resp {
                Ok(resp) => {
                    if let Some(messages) = resp.messages {
                        let mut tx_loop = tx.clone();
                        for msg in messages.into_iter() {
                            match tx_loop.clone().send(msg).wait() {
                                Ok(s) => tx_loop = s,
                                Err(err) => {
                                    error!("Cannot send message through channel: {:?}", err);
                                    break;
                                }
                            };
                        }
                    }
                }
                Err(err) => warn!("SQS client error: {:?}", err),
            }
        }
    });
    Ok(rx)
}
<commit_msg>Also delete message from sqs on receive.<commit_after>use std::{error, fmt, thread};

use futures::{Sink, Future, Stream};
use futures::sync::mpsc::{channel, Receiver, Sender};
use rusoto_core::{self, default_tls_client, DefaultCredentialsProvider, Region};
use rusoto_sqs::{self, Sqs, SqsClient, ReceiveMessageRequest, DeleteMessageRequest};

#[derive(Debug)]
pub enum Error {
    Credentials(rusoto_core::CredentialsError),
    Tls(rusoto_core::TlsError),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Credentials(ref err) => fmt::Display::fmt(err, f),
            Error::Tls(ref err) => fmt::Display::fmt(err, f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Credentials(ref err) => err.description(),
            Error::Tls(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Credentials(ref err) => err.cause(),
            Error::Tls(ref err) => err.cause(),
        }
    }
}

impl From<rusoto_core::CredentialsError> for Error {
    fn from(err: rusoto_core::CredentialsError) -> Self {
        Error::Credentials(err)
    }
}

impl From<rusoto_core::TlsError> for Error {
    fn from(err: rusoto_core::TlsError) -> Self {
        Error::Tls(err)
    }
}

fn sqs_delete_worker(queue_url: String) -> Result<Sender<String /* sqs receipt handle */>, Error> {
    let aws_credentials = DefaultCredentialsProvider::new()?;
    let sqs_client = SqsClient::new(default_tls_client()?, aws_credentials, Region::UsEast1);

    let (del_tx, del_rx) = channel(1);
    let del_th_queue_url = queue_url.clone();
    thread::spawn(move || {
        del_rx
            .for_each(|receipt_handle| {
                let delete_req = DeleteMessageRequest {
                    queue_url: del_th_queue_url.clone(),
                    receipt_handle: receipt_handle,
                };
                if let Err(e) = sqs_client.delete_message(&delete_req) {
                    error!(
                        "Could not delete message with handle {}: {:?}",
                        delete_req.receipt_handle,
                        e
                    );
                };
                Ok(())
            })
            .wait()
            .unwrap();
    });
    Ok(del_tx)
}

pub fn sqs_receiver(queue_url: String) -> Result<Receiver<rusoto_sqs::Message>, Error> {
    let del_tx = sqs_delete_worker(queue_url.clone())?;

    let aws_credentials = DefaultCredentialsProvider::new()?;
    let sqs_client = SqsClient::new(default_tls_client()?, aws_credentials, Region::UsEast1);
    let mut receive_req = ReceiveMessageRequest::default();
    receive_req.queue_url = queue_url.clone();
    receive_req.wait_time_seconds = Some(10);

    let (tx, rx) = channel(1);
    thread::spawn(move || -> Result<(), ()> {
        loop {
            let resp = sqs_client.receive_message(&receive_req);
            match resp {
                Ok(resp) => {
                    if let Some(messages) = resp.messages {
                        let mut tx_loop = tx.clone();
                        for msg in messages.into_iter() {
                            match tx_loop.clone().send(msg.clone()).wait() {
                                Ok(s) => {
                                    tx_loop = s;
                                    if let Some(receipt_handle) = msg.receipt_handle {
                                        match del_tx.clone().send(receipt_handle).wait() {
                                            Ok(_) => (),
                                            Err(err) => {
                                                error!(
                                                    "Cannot send sqs msg delete task: {:?}",
                                                    err
                                                );
                                            }
                                        }
                                    }
                                }
                                Err(err) => {
                                    error!("Cannot send message through channel: {:?}", err);
                                    break;
                                }
                            };
                        }
                    }
                }
                Err(err) => warn!("SQS client error: {:?}", err),
            }
        }
    });
    Ok(rx)
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use getrandom::getrandom;

use poly::{eval, generate, y_intercept};

/// Split a secret into N shares, of which K are required to re-combine. Returns
/// a map of share IDs to share values.
pub fn split(n: u8, k: u8, secret: &[u8]) -> HashMap<u8, Vec<u8>> {
    // Generate a random K-degree polynomial for each byte of the secret.
    let polys = secret
        .iter()
        .map(|b| generate(k - 1, *b, &mut getrandom))
        .collect::<Vec<Vec<u8>>>();

    // Collect the evaluation of each polynomial with the share ID as the input.
    (1..n + 1)
        .map(|id| (id, polys.iter().map(|p| eval(p, id)).collect()))
        .collect()
}

/// Combine a map of share IDs into the original secret.
///
/// N.B.: There is no way to know if this is successful or not.
pub fn combine<S: ::std::hash::BuildHasher>(shares: &HashMap<u8, Vec<u8>, S>) -> Vec<u8> {
    let mut points: Vec<Vec<(u8, u8)>> = Vec::new();
    for (id, share) in shares.iter() {
        for (i, v) in share.iter().enumerate() {
            if points.len() <= i {
                points.push(Vec::new())
            }
            points[i].push((*id, *v));
        }
    }
    points.into_iter().map(|v| y_intercept(&v)).collect()
}

#[cfg(test)]
mod test {
    extern crate itertools;
    use self::itertools::Itertools;
    use super::*;

    #[test]
    fn test_split() {
        let secret = vec![1, 2, 3, 4, 5];
        let splits = split(5, 3, &secret);

        for i in 5..3 {
            for keys in splits.keys().combinations(i) {
                let mut subset: HashMap<u8, Vec<u8>> = HashMap::new();
                for key in keys {
                    subset.insert(*key, splits.get(key).unwrap().to_vec());
                }
                assert_eq!(combine(&subset), secret);
            }
        }

        for i in 2..1 {
            for keys in splits.keys().combinations(i) {
                let mut subset: HashMap<u8, Vec<u8>> = HashMap::new();
                for key in keys {
                    subset.insert(*key, splits.get(key).unwrap().to_vec());
                }
                assert_ne!(combine(&subset), secret);
            }
        }
    }

    #[test]
    fn test_combine() {
        let mut shares: HashMap<u8, Vec<u8>> = HashMap::new();
        shares.insert(1, vec![64, 163, 216, 189, 193]);
        shares.insert(3, vec![194, 250, 117, 212, 82]);
        shares.insert(5, vec![95, 17, 153, 111, 252]);

        assert_eq!(combine(&shares), vec![1, 2, 3, 4, 5])
    }
}
<commit_msg>Use inclusive range.<commit_after>use std::collections::HashMap;

use getrandom::getrandom;

use poly::{eval, generate, y_intercept};

/// Split a secret into N shares, of which K are required to re-combine. Returns
/// a map of share IDs to share values.
pub fn split(n: u8, k: u8, secret: &[u8]) -> HashMap<u8, Vec<u8>> {
    // Generate a random K-degree polynomial for each byte of the secret.
    let polys = secret
        .iter()
        .map(|b| generate(k - 1, *b, &mut getrandom))
        .collect::<Vec<Vec<u8>>>();

    // Collect the evaluation of each polynomial with the share ID as the input.
    (1..=n)
        .map(|id| (id, polys.iter().map(|p| eval(p, id)).collect()))
        .collect()
}

/// Combine a map of share IDs into the original secret.
///
/// N.B.: There is no way to know if this is successful or not.
pub fn combine<S: ::std::hash::BuildHasher>(shares: &HashMap<u8, Vec<u8>, S>) -> Vec<u8> {
    let mut points: Vec<Vec<(u8, u8)>> = Vec::new();
    for (id, share) in shares.iter() {
        for (i, v) in share.iter().enumerate() {
            if points.len() <= i {
                points.push(Vec::new())
            }
            points[i].push((*id, *v));
        }
    }
    points.into_iter().map(|v| y_intercept(&v)).collect()
}

#[cfg(test)]
mod test {
    extern crate itertools;
    use self::itertools::Itertools;
    use super::*;

    #[test]
    fn test_split() {
        let secret = vec![1, 2, 3, 4, 5];
        let splits = split(5, 3, &secret);

        for i in 5..3 {
            for keys in splits.keys().combinations(i) {
                let mut subset: HashMap<u8, Vec<u8>> = HashMap::new();
                for key in keys {
                    subset.insert(*key, splits.get(key).unwrap().to_vec());
                }
                assert_eq!(combine(&subset), secret);
            }
        }

        for i in 2..1 {
            for keys in splits.keys().combinations(i) {
                let mut subset: HashMap<u8, Vec<u8>> = HashMap::new();
                for key in keys {
                    subset.insert(*key, splits.get(key).unwrap().to_vec());
                }
                assert_ne!(combine(&subset), secret);
            }
        }
    }

    #[test]
    fn test_combine() {
        let mut shares: HashMap<u8, Vec<u8>> = HashMap::new();
        shares.insert(1, vec![64, 163, 216, 189, 193]);
        shares.insert(3, vec![194, 250, 117, 212, 82]);
        shares.insert(5, vec![95, 17, 153, 111, 252]);

        assert_eq!(combine(&shares), vec![1, 2, 3, 4, 5])
    }
}
<|endoftext|>


<commit_before>use crypto::digest::Digest;
use crypto::sha2::{Sha512, Sha256};
use json;
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::marker::PhantomData;
use std::path::{PathBuf, Path};
use url::Url;

use cjson;
use error::Error;
use metadata::{Role, RoleType, Root, Targets, Timestamp, Snapshot, Metadata, SignedMetadata,
               RootMetadata, TargetsMetadata, TimestampMetadata, SnapshotMetadata, HashType,
               HashValue};

pub struct Tuf {
    url: Url,
    local_path: PathBuf,
    root: RootMetadata,
    targets: Option<TargetsMetadata>,
    timestamp: Option<TimestampMetadata>,
    snapshot: Option<SnapshotMetadata>,
}

impl Tuf {
    pub fn new(config: Config) -> Result<Self, Error> {
        // TODO don't do an unverified root read, but make someone hard code keys
        // for the first time around
        let root = {
            let scary_bad_root = Self::unverified_read_root(&config.local_path)?;
            Self::load_metadata::<Root, RootMetadata>(&config.local_path, &scary_bad_root)?
        };

        let targets = Self::load_metadata::<Targets, TargetsMetadata>(&config.local_path, &root)?;
        let timestamp = Self::load_metadata::<Timestamp, TimestampMetadata>(&config.local_path,
                                                                            &root)?;
        let snapshot = Self::load_metadata::<Snapshot, SnapshotMetadata>(&config.local_path,
                                                                         &root)?;

        // TODO cross verification of all the metadata against each other
        // TODO check the timestamps aren't expired

        Ok(Tuf {
            url: config.url,
            local_path: config.local_path,
            root: root,
            targets: Some(targets), // TODO we are wrongly assuming that this is always present
            timestamp: Some(timestamp), // TODO we are wrongly assuming that this is always present
            snapshot: Some(snapshot), // TODO we are wrongly assuming that this is always present
        })
    }

    fn load_metadata<R: RoleType, M: Metadata<R>>(local_path: &Path,
                                                  root: &RootMetadata)
                                                  -> Result<M, Error> {
        Self::load_meta_prefix(local_path, "", root)
    }

    fn load_meta_num<R: RoleType, M: Metadata<R>>(local_path: &Path,
                                                  num: i32,
                                                  root: &RootMetadata)
                                                  -> Result<M, Error> {
        Self::load_meta_prefix(local_path, &format!("{}.", num), root)
    }

    fn load_meta_hash<R: RoleType, M: Metadata<R>>(local_path: &Path,
                                                   hash: &str,
                                                   root: &RootMetadata)
                                                   -> Result<M, Error> {
        Self::load_meta_prefix(local_path, &format!("{}.", hash), root)
    }

    fn unverified_read_root(local_path: &Path) -> Result<RootMetadata, Error> {
        let path = local_path.join("meta").join("root.json");
        let mut file = File::open(path)?;
        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;

        let signed: SignedMetadata<Root> = json::from_slice(&buf)?;
        let root_str = signed.signed.to_string();
        Ok(json::from_str(&root_str)?)
    }

    fn load_meta_prefix<R: RoleType, M: Metadata<R>>(local_path: &Path,
                                                     prefix: &str,
                                                     root: &RootMetadata)
                                                     -> Result<M, Error> {
        let path = local_path.join("meta").join(format!("{}{}.json", prefix, R::role()));
        info!("Reading metadata from local path: {:?}", path);

        let mut file = File::open(path)?;
        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;

        let signed = json::from_slice(&buf)?;
        let safe_bytes = Self::verify_meta::<R>(signed, root)?;
        Ok(json::from_slice(&safe_bytes)?)
    }

    fn verify_meta<R: RoleType>(signed: SignedMetadata<R>,
                                root: &RootMetadata)
                                -> Result<Vec<u8>, Error> {
        // TODO use the real cjson lib and not this crap
        let bytes =
            cjson::canonicalize(signed.signed).map_err(|err| Error::CanonicalJsonError(err))?;

        let role = root.role_definition::<R>();

        // TODO verify that sigs are unique
        // TODO verify that threshold > 0
        // TODO verify that #keys >= threshold

        let keys = role.key_ids
            .iter()
            .map(|id| (id, root.keys.get(id)))
            .fold(HashMap::new(), |mut m, (id, k)| {
                if let Some(key) = k {
                    m.insert(id, key);
                }
                m
            });

        // count down to zero and not up to the threshold to:
        //   1) short curcuit complete
        //   2) avoid ever comparing 0 >= 0 (horribly unsafe)
        let mut threshold = role.threshold;
        for sig in signed.signatures.iter() {
            if let Some(key) = keys.get(&sig.key_id) {
                match key.verify(&sig.method, &bytes, &sig.sig) {
                    Ok(()) => threshold -= 1,
                    Err(e) => warn!("Failed to verify with key ID {:?}: {:?}", &sig.key_id, e),
                }
                if threshold == 0 {
                    return Ok(bytes);
                }
            }
        }

        Err(Error::VerificationFailure(format!("Threshold not met: {}/{}",
                                               role.threshold - threshold,
                                               role.threshold)))
    }

    // TODO stronger return type
    pub fn list_targets(&self) -> Vec<String> {
        match self.targets {
            Some(ref targets) => {
                let mut res = targets.targets.keys().cloned().collect::<Vec<String>>();
                res.sort();
                res
            },
            None => Vec::new(),
        }
    }

    // TODO stronger input type
    pub fn verify_target(&self, target: &str) -> Result<(), Error> {
        let target_meta = match self.targets {
            Some(ref targets) => {
                targets.targets
                    .get(target)
                    .ok_or_else(|| Error::UnknownTarget)?
            }
            None => unreachable!(), // TODO
        };

        let (hash_alg, expected_hash): (HashType, HashValue) = HashType::preferences().iter()
            .fold(None, |res, pref| {
                res.or_else(|| if let Some(hash) = target_meta.hashes.get(&pref) {
                    Some((pref.clone(), hash.clone()))
                } else {
                    None
                })
            })
            .ok_or_else(|| Error::NoSupportedHashAlgorithms)?;

        let path = self.local_path.join("targets").join(target);
        info!("Reading target from local path: {:?}", path);
        let mut file = File::open(path)?;

        match hash_alg {
            HashType::Sha512 => {
                Self::read_and_verify(&mut file,
                                      &mut Sha512::new(),
                                      target_meta.length,
                                      &expected_hash.0)
            }
            HashType::Sha256 => {
                Self::read_and_verify(&mut file,
                                      &mut Sha256::new(),
                                      target_meta.length,
                                      &expected_hash.0)
            }
            HashType::Unsupported(_) => Err(Error::NoSupportedHashAlgorithms),
        }
    }

    fn read_and_verify<R: Read, D: Digest>(input: &mut R,
                                           digest: &mut D,
                                           size: i64,
                                           expected_hash: &[u8])
                                           -> Result<(), Error> {
        let mut buf = [0; 1024];
        let mut bytes_left = size;

        loop {
            match input.read(&mut buf) {
                Ok(read_bytes) => {
                    digest.input(&buf[0..read_bytes]);
                    bytes_left -= read_bytes as i64;
                    if bytes_left == 0 {
                        break;
                    } else if bytes_left <= 0 {
                        panic!("Too many bytes read") // TODO this is sad
                    }
                }
                e @ Err(_) => e.map(|_| ())?,
            }
        }

        let mut generated_hash = vec![0; digest.output_bytes()];
        digest.result(&mut generated_hash);

        if generated_hash.as_slice() == expected_hash {
            Ok(())
        } else {
            Err(Error::TargetHashMismatch)
        }
    }
}

pub struct Config {
    url: Url,
    local_path: PathBuf,
}

impl Config {
    pub fn build() -> ConfigBuilder {
        ConfigBuilder::new()
    }
}

pub struct ConfigBuilder {
    url: Option<Url>,
    local_path: Option<PathBuf>,
}

impl ConfigBuilder {
    pub fn new() -> Self {
        ConfigBuilder {
            url: None,
            local_path: None,
        }
    }

    pub fn url(mut self, url: Url) -> Self {
        self.url = Some(url);
        self
    }

    pub fn local_path(mut self, local_path: PathBuf) -> Self {
        self.local_path = Some(local_path);
        self
    }

    pub fn finish(self) -> Result<Config, Error> {
        let url = self.url
            .ok_or_else(|| Error::InvalidConfig("Repository URL was not set".to_string()))?;
        let local_path = self.local_path
            .ok_or_else(|| Error::InvalidConfig("Local path was not set".to_string()))?;

        // TODO error if path is not fully owned by the current user
        // TODO create path if not exists

        Ok(Config {
            url: url,
            local_path: local_path,
        })
    }
}
<commit_msg>verifies signatures are unique<commit_after>use crypto::digest::Digest;
use crypto::sha2::{Sha512, Sha256};
use json;
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::Read;
use std::marker::PhantomData;
use std::path::{PathBuf, Path};
use url::Url;

use cjson;
use error::Error;
use metadata::{Role, RoleType, Root, Targets, Timestamp, Snapshot, Metadata, SignedMetadata,
               RootMetadata, TargetsMetadata, TimestampMetadata, SnapshotMetadata, HashType,
               HashValue, KeyId};

pub struct Tuf {
    url: Url,
    local_path: PathBuf,
    root: RootMetadata,
    targets: Option<TargetsMetadata>,
    timestamp: Option<TimestampMetadata>,
    snapshot: Option<SnapshotMetadata>,
}

impl Tuf {
    pub fn new(config: Config) -> Result<Self, Error> {
        // TODO don't do an unverified root read, but make someone hard code keys
        // for the first time around
        let root = {
            let scary_bad_root = Self::unverified_read_root(&config.local_path)?;
            Self::load_metadata::<Root, RootMetadata>(&config.local_path, &scary_bad_root)?
        };

        let targets = Self::load_metadata::<Targets, TargetsMetadata>(&config.local_path, &root)?;
        let timestamp = Self::load_metadata::<Timestamp, TimestampMetadata>(&config.local_path,
                                                                            &root)?;
        let snapshot = Self::load_metadata::<Snapshot, SnapshotMetadata>(&config.local_path,
                                                                         &root)?;

        // TODO cross verification of all the metadata against each other
        // TODO check the timestamps aren't expired

        Ok(Tuf {
            url: config.url,
            local_path: config.local_path,
            root: root,
            targets: Some(targets), // TODO we are wrongly assuming that this is always present
            timestamp: Some(timestamp), // TODO we are wrongly assuming that this is always present
            snapshot: Some(snapshot), // TODO we are wrongly assuming that this is always present
        })
    }

    fn load_metadata<R: RoleType, M: Metadata<R>>(local_path: &Path,
                                                  root: &RootMetadata)
                                                  -> Result<M, Error> {
        Self::load_meta_prefix(local_path, "", root)
    }

    fn load_meta_num<R: RoleType, M: Metadata<R>>(local_path: &Path,
                                                  num: i32,
                                                  root: &RootMetadata)
                                                  -> Result<M, Error> {
        Self::load_meta_prefix(local_path, &format!("{}.", num), root)
    }

    fn load_meta_hash<R: RoleType, M: Metadata<R>>(local_path: &Path,
                                                   hash: &str,
                                                   root: &RootMetadata)
                                                   -> Result<M, Error> {
        Self::load_meta_prefix(local_path, &format!("{}.", hash), root)
    }

    fn unverified_read_root(local_path: &Path) -> Result<RootMetadata, Error> {
        let path = local_path.join("meta").join("root.json");
        let mut file = File::open(path)?;
        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;

        let signed: SignedMetadata<Root> = json::from_slice(&buf)?;
        let root_str = signed.signed.to_string();
        Ok(json::from_str(&root_str)?)
    }

    fn load_meta_prefix<R: RoleType, M: Metadata<R>>(local_path: &Path,
                                                     prefix: &str,
                                                     root: &RootMetadata)
                                                     -> Result<M, Error> {
        let path = local_path.join("meta").join(format!("{}{}.json", prefix, R::role()));
        info!("Reading metadata from local path: {:?}", path);

        let mut file = File::open(path)?;
        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;

        let signed = json::from_slice(&buf)?;
        let safe_bytes = Self::verify_meta::<R>(signed, root)?;
        Ok(json::from_slice(&safe_bytes)?)
    }

    fn verify_meta<R: RoleType>(signed: SignedMetadata<R>,
                                root: &RootMetadata)
                                -> Result<Vec<u8>, Error> {
        // TODO use the real cjson lib and not this crap
        let bytes =
            cjson::canonicalize(signed.signed).map_err(|err| Error::CanonicalJsonError(err))?;

        let role = root.role_definition::<R>();

        let unique_count = signed.signatures
            .iter()
            .map(|s| &s.key_id)
            .collect::<HashSet<&KeyId>>()
            .len();

        if signed.signatures.len() != unique_count {
            return Err(Error::NonUniqueSignatures);
        }

        let keys = role.key_ids
            .iter()
            .map(|id| (id, root.keys.get(id)))
            .fold(HashMap::new(), |mut m, (id, k)| {
                if let Some(key) = k {
                    m.insert(id, key);
                }
                m
            });

        // count down to zero and not up to the threshold to:
        //   1) short curcuit complete
        //   2) avoid ever comparing 0 >= 0 (horribly unsafe)
        let mut threshold = role.threshold;
        for sig in signed.signatures.iter() {
            if let Some(key) = keys.get(&sig.key_id) {
                match key.verify(&sig.method, &bytes, &sig.sig) {
                    Ok(()) => threshold -= 1,
                    Err(e) => warn!("Failed to verify with key ID {:?}: {:?}", &sig.key_id, e),
                }
                if threshold == 0 {
                    return Ok(bytes);
                }
            }
        }

        Err(Error::VerificationFailure(format!("Threshold not met: {}/{}",
                                               role.threshold - threshold,
                                               role.threshold)))
    }

    // TODO stronger return type
    pub fn list_targets(&self) -> Vec<String> {
        match self.targets {
            Some(ref targets) => {
                let mut res = targets.targets.keys().cloned().collect::<Vec<String>>();
                res.sort();
                res
            },
            None => Vec::new(),
        }
    }

    // TODO stronger input type
    pub fn verify_target(&self, target: &str) -> Result<(), Error> {
        let target_meta = match self.targets {
            Some(ref targets) => {
                targets.targets
                    .get(target)
                    .ok_or_else(|| Error::UnknownTarget)?
            }
            None => unreachable!(), // TODO
        };

        let (hash_alg, expected_hash): (HashType, HashValue) = HashType::preferences().iter()
            .fold(None, |res, pref| {
                res.or_else(|| if let Some(hash) = target_meta.hashes.get(&pref) {
                    Some((pref.clone(), hash.clone()))
                } else {
                    None
                })
            })
            .ok_or_else(|| Error::NoSupportedHashAlgorithms)?;

        let path = self.local_path.join("targets").join(target);
        info!("Reading target from local path: {:?}", path);
        let mut file = File::open(path)?;

        match hash_alg {
            HashType::Sha512 => {
                Self::read_and_verify(&mut file,
                                      &mut Sha512::new(),
                                      target_meta.length,
                                      &expected_hash.0)
            }
            HashType::Sha256 => {
                Self::read_and_verify(&mut file,
                                      &mut Sha256::new(),
                                      target_meta.length,
                                      &expected_hash.0)
            }
            HashType::Unsupported(_) => Err(Error::NoSupportedHashAlgorithms),
        }
    }

    fn read_and_verify<R: Read, D: Digest>(input: &mut R,
                                           digest: &mut D,
                                           size: i64,
                                           expected_hash: &[u8])
                                           -> Result<(), Error> {
        let mut buf = [0; 1024];
        let mut bytes_left = size;

        loop {
            match input.read(&mut buf) {
                Ok(read_bytes) => {
                    digest.input(&buf[0..read_bytes]);
                    bytes_left -= read_bytes as i64;
                    if bytes_left == 0 {
                        break;
                    } else if bytes_left <= 0 {
                        panic!("Too many bytes read") // TODO this is sad
                    }
                }
                e @ Err(_) => e.map(|_| ())?,
            }
        }

        let mut generated_hash = vec![0; digest.output_bytes()];
        digest.result(&mut generated_hash);

        if generated_hash.as_slice() == expected_hash {
            Ok(())
        } else {
            Err(Error::TargetHashMismatch)
        }
    }
}

pub struct Config {
    url: Url,
    local_path: PathBuf,
}

impl Config {
    pub fn build() -> ConfigBuilder {
        ConfigBuilder::new()
    }
}

pub struct ConfigBuilder {
    url: Option<Url>,
    local_path: Option<PathBuf>,
}

impl ConfigBuilder {
    pub fn new() -> Self {
        ConfigBuilder {
            url: None,
            local_path: None,
        }
    }

    pub fn url(mut self, url: Url) -> Self {
        self.url = Some(url);
        self
    }

    pub fn local_path(mut self, local_path: PathBuf) -> Self {
        self.local_path = Some(local_path);
        self
    }

    pub fn finish(self) -> Result<Config, Error> {
        let url = self.url
            .ok_or_else(|| Error::InvalidConfig("Repository URL was not set".to_string()))?;
        let local_path = self.local_path
            .ok_or_else(|| Error::InvalidConfig("Local path was not set".to_string()))?;

        // TODO error if path is not fully owned by the current user
        // TODO create path if not exists

        Ok(Config {
            url: url,
            local_path: local_path,
        })
    }
}
<|endoftext|>


<commit_before>//! Implementation of the Chalk `Interner` trait, which allows customizing the
//! representation of the various objects Chalk deals with (types, goals etc.).

use super::tls;
use base_db::salsa::InternId;
use chalk_ir::{GenericArg, Goal, GoalData};
use hir_def::TypeAliasId;
use smallvec::SmallVec;
use std::{fmt, sync::Arc};

#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct Interner;

pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
pub(crate) type TraitId = chalk_ir::TraitId<Interner>;
pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>;
pub(crate) type AdtId = chalk_ir::AdtId<Interner>;
pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>;
pub(crate) type ImplId = chalk_ir::ImplId<Interner>;
pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>;
pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>;
pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>;
pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
pub(crate) type Variances = chalk_ir::Variances<Interner>;

impl chalk_ir::interner::Interner for Interner {
    type InternedType = Arc<chalk_ir::TyData<Self>>;
    type InternedLifetime = chalk_ir::LifetimeData<Self>;
    type InternedConst = Arc<chalk_ir::ConstData<Self>>;
    type InternedConcreteConst = ();
    type InternedGenericArg = chalk_ir::GenericArgData<Self>;
    type InternedGoal = Arc<GoalData<Self>>;
    type InternedGoals = Vec<Goal<Self>>;
    type InternedSubstitution = SmallVec<[GenericArg<Self>; 2]>;
    type InternedProgramClause = Arc<chalk_ir::ProgramClauseData<Self>>;
    type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>;
    type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>;
    type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>;
    type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>;
    type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
    type InternedVariances = Arc<[chalk_ir::Variance]>;
    type DefId = InternId;
    type InternedAdtId = hir_def::AdtId;
    type Identifier = TypeAliasId;
    type FnAbi = ();

    fn debug_adt_id(type_kind_id: AdtId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt)))
    }

    fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt)))
    }

    fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt)))
    }

    fn debug_alias(
        alias: &chalk_ir::AliasTy<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt)))
    }

    fn debug_projection_ty(
        proj: &chalk_ir::ProjectionTy<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt)))
    }

    fn debug_opaque_ty(
        opaque_ty: &chalk_ir::OpaqueTy<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_opaque_ty(opaque_ty, fmt)))
    }

    fn debug_opaque_ty_id(
        opaque_ty_id: chalk_ir::OpaqueTyId<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_opaque_ty_id(opaque_ty_id, fmt)))
    }

    fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt)))
    }

    fn debug_lifetime(
        lifetime: &chalk_ir::Lifetime<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_lifetime(lifetime, fmt)))
    }

    fn debug_generic_arg(
        parameter: &GenericArg<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt)))
    }

    fn debug_goal(goal: &Goal<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_goal(goal, fmt)))
    }

    fn debug_goals(
        goals: &chalk_ir::Goals<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_goals(goals, fmt)))
    }

    fn debug_program_clause_implication(
        pci: &chalk_ir::ProgramClauseImplication<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt)))
    }

    fn debug_substitution(
        substitution: &chalk_ir::Substitution<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_substitution(substitution, fmt)))
    }

    fn debug_separator_trait_ref(
        separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| {
            Some(prog?.debug_separator_trait_ref(separator_trait_ref, fmt))
        })
    }

    fn debug_fn_def_id(
        fn_def_id: chalk_ir::FnDefId<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_fn_def_id(fn_def_id, fmt)))
    }
    fn debug_const(
        constant: &chalk_ir::Const<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_const(constant, fmt)))
    }
    fn debug_variable_kinds(
        variable_kinds: &chalk_ir::VariableKinds<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_variable_kinds(variable_kinds, fmt)))
    }
    fn debug_variable_kinds_with_angles(
        variable_kinds: &chalk_ir::VariableKinds<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| {
            Some(prog?.debug_variable_kinds_with_angles(variable_kinds, fmt))
        })
    }
    fn debug_canonical_var_kinds(
        canonical_var_kinds: &chalk_ir::CanonicalVarKinds<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| {
            Some(prog?.debug_canonical_var_kinds(canonical_var_kinds, fmt))
        })
    }
    fn debug_program_clause(
        clause: &chalk_ir::ProgramClause<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_program_clause(clause, fmt)))
    }
    fn debug_program_clauses(
        clauses: &chalk_ir::ProgramClauses<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_program_clauses(clauses, fmt)))
    }
    fn debug_quantified_where_clauses(
        clauses: &chalk_ir::QuantifiedWhereClauses<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_quantified_where_clauses(clauses, fmt)))
    }

    fn intern_ty(&self, kind: chalk_ir::TyKind<Self>) -> Arc<chalk_ir::TyData<Self>> {
        let flags = kind.compute_flags(self);
        Arc::new(chalk_ir::TyData { kind, flags })
    }

    fn ty_data<'a>(&self, ty: &'a Arc<chalk_ir::TyData<Self>>) -> &'a chalk_ir::TyData<Self> {
        ty
    }

    fn intern_lifetime(
        &self,
        lifetime: chalk_ir::LifetimeData<Self>,
    ) -> chalk_ir::LifetimeData<Self> {
        lifetime
    }

    fn lifetime_data<'a>(
        &self,
        lifetime: &'a chalk_ir::LifetimeData<Self>,
    ) -> &'a chalk_ir::LifetimeData<Self> {
        lifetime
    }

    fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Arc<chalk_ir::ConstData<Self>> {
        Arc::new(constant)
    }

    fn const_data<'a>(
        &self,
        constant: &'a Arc<chalk_ir::ConstData<Self>>,
    ) -> &'a chalk_ir::ConstData<Self> {
        constant
    }

    fn const_eq(&self, _ty: &Arc<chalk_ir::TyData<Self>>, _c1: &(), _c2: &()) -> bool {
        true
    }

    fn intern_generic_arg(
        &self,
        parameter: chalk_ir::GenericArgData<Self>,
    ) -> chalk_ir::GenericArgData<Self> {
        parameter
    }

    fn generic_arg_data<'a>(
        &self,
        parameter: &'a chalk_ir::GenericArgData<Self>,
    ) -> &'a chalk_ir::GenericArgData<Self> {
        parameter
    }

    fn intern_goal(&self, goal: GoalData<Self>) -> Arc<GoalData<Self>> {
        Arc::new(goal)
    }

    fn intern_goals<E>(
        &self,
        data: impl IntoIterator<Item = Result<Goal<Self>, E>>,
    ) -> Result<Self::InternedGoals, E> {
        data.into_iter().collect()
    }

    fn goal_data<'a>(&self, goal: &'a Arc<GoalData<Self>>) -> &'a GoalData<Self> {
        goal
    }

    fn goals_data<'a>(&self, goals: &'a Vec<Goal<Interner>>) -> &'a [Goal<Interner>] {
        goals
    }

    fn intern_substitution<E>(
        &self,
        data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>,
    ) -> Result<Self::InternedSubstitution, E> {
        data.into_iter().collect()
    }

    fn substitution_data<'a>(
        &self,
        substitution: &'a Self::InternedSubstitution,
    ) -> &'a [GenericArg<Self>] {
        substitution
    }

    fn intern_program_clause(
        &self,
        data: chalk_ir::ProgramClauseData<Self>,
    ) -> Arc<chalk_ir::ProgramClauseData<Self>> {
        Arc::new(data)
    }

    fn program_clause_data<'a>(
        &self,
        clause: &'a Arc<chalk_ir::ProgramClauseData<Self>>,
    ) -> &'a chalk_ir::ProgramClauseData<Self> {
        clause
    }

    fn intern_program_clauses<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>,
    ) -> Result<Arc<[chalk_ir::ProgramClause<Self>]>, E> {
        data.into_iter().collect()
    }

    fn program_clauses_data<'a>(
        &self,
        clauses: &'a Arc<[chalk_ir::ProgramClause<Self>]>,
    ) -> &'a [chalk_ir::ProgramClause<Self>] {
        &clauses
    }

    fn intern_quantified_where_clauses<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>,
    ) -> Result<Self::InternedQuantifiedWhereClauses, E> {
        data.into_iter().collect()
    }

    fn quantified_where_clauses_data<'a>(
        &self,
        clauses: &'a Self::InternedQuantifiedWhereClauses,
    ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] {
        clauses
    }

    fn intern_generic_arg_kinds<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>,
    ) -> Result<Self::InternedVariableKinds, E> {
        data.into_iter().collect()
    }

    fn variable_kinds_data<'a>(
        &self,
        parameter_kinds: &'a Self::InternedVariableKinds,
    ) -> &'a [chalk_ir::VariableKind<Self>] {
        &parameter_kinds
    }

    fn intern_canonical_var_kinds<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>,
    ) -> Result<Self::InternedCanonicalVarKinds, E> {
        data.into_iter().collect()
    }

    fn canonical_var_kinds_data<'a>(
        &self,
        canonical_var_kinds: &'a Self::InternedCanonicalVarKinds,
    ) -> &'a [chalk_ir::CanonicalVarKind<Self>] {
        &canonical_var_kinds
    }

    fn intern_constraints<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>, E>>,
    ) -> Result<Self::InternedConstraints, E> {
        data.into_iter().collect()
    }

    fn constraints_data<'a>(
        &self,
        constraints: &'a Self::InternedConstraints,
    ) -> &'a [chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] {
        constraints
    }
    fn debug_closure_id(
        _fn_def_id: chalk_ir::ClosureId<Self>,
        _fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        None
    }
    fn debug_constraints(
        _clauses: &chalk_ir::Constraints<Self>,
        _fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        None
    }

    fn intern_variances<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>,
    ) -> Result<Self::InternedVariances, E> {
        data.into_iter().collect()
    }

    fn variances_data<'a>(
        &self,
        variances: &'a Self::InternedVariances,
    ) -> &'a [chalk_ir::Variance] {
        &variances
    }
}

impl chalk_ir::interner::HasInterner for Interner {
    type Interner = Self;
}
<commit_msg>Use more assoc. type aliases in the chalk interner<commit_after>//! Implementation of the Chalk `Interner` trait, which allows customizing the
//! representation of the various objects Chalk deals with (types, goals etc.).

use super::tls;
use base_db::salsa::InternId;
use chalk_ir::{GenericArg, Goal, GoalData};
use hir_def::TypeAliasId;
use smallvec::SmallVec;
use std::{fmt, sync::Arc};

#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct Interner;

pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
pub(crate) type TraitId = chalk_ir::TraitId<Interner>;
pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>;
pub(crate) type AdtId = chalk_ir::AdtId<Interner>;
pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>;
pub(crate) type ImplId = chalk_ir::ImplId<Interner>;
pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>;
pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>;
pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>;
pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
pub(crate) type Variances = chalk_ir::Variances<Interner>;

impl chalk_ir::interner::Interner for Interner {
    type InternedType = Arc<chalk_ir::TyData<Self>>;
    type InternedLifetime = chalk_ir::LifetimeData<Self>;
    type InternedConst = Arc<chalk_ir::ConstData<Self>>;
    type InternedConcreteConst = ();
    type InternedGenericArg = chalk_ir::GenericArgData<Self>;
    type InternedGoal = Arc<GoalData<Self>>;
    type InternedGoals = Vec<Goal<Self>>;
    type InternedSubstitution = SmallVec<[GenericArg<Self>; 2]>;
    type InternedProgramClause = Arc<chalk_ir::ProgramClauseData<Self>>;
    type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>;
    type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>;
    type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>;
    type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>;
    type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
    type InternedVariances = Arc<[chalk_ir::Variance]>;
    type DefId = InternId;
    type InternedAdtId = hir_def::AdtId;
    type Identifier = TypeAliasId;
    type FnAbi = ();

    fn debug_adt_id(type_kind_id: AdtId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt)))
    }

    fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt)))
    }

    fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt)))
    }

    fn debug_alias(
        alias: &chalk_ir::AliasTy<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt)))
    }

    fn debug_projection_ty(
        proj: &chalk_ir::ProjectionTy<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt)))
    }

    fn debug_opaque_ty(
        opaque_ty: &chalk_ir::OpaqueTy<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_opaque_ty(opaque_ty, fmt)))
    }

    fn debug_opaque_ty_id(
        opaque_ty_id: chalk_ir::OpaqueTyId<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_opaque_ty_id(opaque_ty_id, fmt)))
    }

    fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt)))
    }

    fn debug_lifetime(
        lifetime: &chalk_ir::Lifetime<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_lifetime(lifetime, fmt)))
    }

    fn debug_generic_arg(
        parameter: &GenericArg<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt)))
    }

    fn debug_goal(goal: &Goal<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_goal(goal, fmt)))
    }

    fn debug_goals(
        goals: &chalk_ir::Goals<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_goals(goals, fmt)))
    }

    fn debug_program_clause_implication(
        pci: &chalk_ir::ProgramClauseImplication<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt)))
    }

    fn debug_substitution(
        substitution: &chalk_ir::Substitution<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_substitution(substitution, fmt)))
    }

    fn debug_separator_trait_ref(
        separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| {
            Some(prog?.debug_separator_trait_ref(separator_trait_ref, fmt))
        })
    }

    fn debug_fn_def_id(
        fn_def_id: chalk_ir::FnDefId<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_fn_def_id(fn_def_id, fmt)))
    }
    fn debug_const(
        constant: &chalk_ir::Const<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_const(constant, fmt)))
    }
    fn debug_variable_kinds(
        variable_kinds: &chalk_ir::VariableKinds<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_variable_kinds(variable_kinds, fmt)))
    }
    fn debug_variable_kinds_with_angles(
        variable_kinds: &chalk_ir::VariableKinds<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| {
            Some(prog?.debug_variable_kinds_with_angles(variable_kinds, fmt))
        })
    }
    fn debug_canonical_var_kinds(
        canonical_var_kinds: &chalk_ir::CanonicalVarKinds<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| {
            Some(prog?.debug_canonical_var_kinds(canonical_var_kinds, fmt))
        })
    }
    fn debug_program_clause(
        clause: &chalk_ir::ProgramClause<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_program_clause(clause, fmt)))
    }
    fn debug_program_clauses(
        clauses: &chalk_ir::ProgramClauses<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_program_clauses(clauses, fmt)))
    }
    fn debug_quantified_where_clauses(
        clauses: &chalk_ir::QuantifiedWhereClauses<Self>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        tls::with_current_program(|prog| Some(prog?.debug_quantified_where_clauses(clauses, fmt)))
    }

    fn intern_ty(&self, kind: chalk_ir::TyKind<Self>) -> Self::InternedType {
        let flags = kind.compute_flags(self);
        Arc::new(chalk_ir::TyData { kind, flags })
    }

    fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> {
        ty
    }

    fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData<Self>) -> Self::InternedLifetime {
        lifetime
    }

    fn lifetime_data<'a>(
        &self,
        lifetime: &'a Self::InternedLifetime,
    ) -> &'a chalk_ir::LifetimeData<Self> {
        lifetime
    }

    fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Self::InternedConst {
        Arc::new(constant)
    }

    fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> {
        constant
    }

    fn const_eq(
        &self,
        _ty: &Self::InternedType,
        _c1: &Self::InternedConcreteConst,
        _c2: &Self::InternedConcreteConst,
    ) -> bool {
        true
    }

    fn intern_generic_arg(
        &self,
        parameter: chalk_ir::GenericArgData<Self>,
    ) -> Self::InternedGenericArg {
        parameter
    }

    fn generic_arg_data<'a>(
        &self,
        parameter: &'a Self::InternedGenericArg,
    ) -> &'a chalk_ir::GenericArgData<Self> {
        parameter
    }

    fn intern_goal(&self, goal: GoalData<Self>) -> Self::InternedGoal {
        Arc::new(goal)
    }

    fn intern_goals<E>(
        &self,
        data: impl IntoIterator<Item = Result<Goal<Self>, E>>,
    ) -> Result<Self::InternedGoals, E> {
        data.into_iter().collect()
    }

    fn goal_data<'a>(&self, goal: &'a Self::InternedGoal) -> &'a GoalData<Self> {
        goal
    }

    fn goals_data<'a>(&self, goals: &'a Self::InternedGoals) -> &'a [Goal<Interner>] {
        goals
    }

    fn intern_substitution<E>(
        &self,
        data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>,
    ) -> Result<Self::InternedSubstitution, E> {
        data.into_iter().collect()
    }

    fn substitution_data<'a>(
        &self,
        substitution: &'a Self::InternedSubstitution,
    ) -> &'a [GenericArg<Self>] {
        substitution
    }

    fn intern_program_clause(
        &self,
        data: chalk_ir::ProgramClauseData<Self>,
    ) -> Self::InternedProgramClause {
        Arc::new(data)
    }

    fn program_clause_data<'a>(
        &self,
        clause: &'a Self::InternedProgramClause,
    ) -> &'a chalk_ir::ProgramClauseData<Self> {
        clause
    }

    fn intern_program_clauses<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>,
    ) -> Result<Self::InternedProgramClauses, E> {
        data.into_iter().collect()
    }

    fn program_clauses_data<'a>(
        &self,
        clauses: &'a Self::InternedProgramClauses,
    ) -> &'a [chalk_ir::ProgramClause<Self>] {
        &clauses
    }

    fn intern_quantified_where_clauses<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>,
    ) -> Result<Self::InternedQuantifiedWhereClauses, E> {
        data.into_iter().collect()
    }

    fn quantified_where_clauses_data<'a>(
        &self,
        clauses: &'a Self::InternedQuantifiedWhereClauses,
    ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] {
        clauses
    }

    fn intern_generic_arg_kinds<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>,
    ) -> Result<Self::InternedVariableKinds, E> {
        data.into_iter().collect()
    }

    fn variable_kinds_data<'a>(
        &self,
        parameter_kinds: &'a Self::InternedVariableKinds,
    ) -> &'a [chalk_ir::VariableKind<Self>] {
        &parameter_kinds
    }

    fn intern_canonical_var_kinds<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>,
    ) -> Result<Self::InternedCanonicalVarKinds, E> {
        data.into_iter().collect()
    }

    fn canonical_var_kinds_data<'a>(
        &self,
        canonical_var_kinds: &'a Self::InternedCanonicalVarKinds,
    ) -> &'a [chalk_ir::CanonicalVarKind<Self>] {
        &canonical_var_kinds
    }

    fn intern_constraints<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>, E>>,
    ) -> Result<Self::InternedConstraints, E> {
        data.into_iter().collect()
    }

    fn constraints_data<'a>(
        &self,
        constraints: &'a Self::InternedConstraints,
    ) -> &'a [chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] {
        constraints
    }
    fn debug_closure_id(
        _fn_def_id: chalk_ir::ClosureId<Self>,
        _fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        None
    }
    fn debug_constraints(
        _clauses: &chalk_ir::Constraints<Self>,
        _fmt: &mut fmt::Formatter<'_>,
    ) -> Option<fmt::Result> {
        None
    }

    fn intern_variances<E>(
        &self,
        data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>,
    ) -> Result<Self::InternedVariances, E> {
        data.into_iter().collect()
    }

    fn variances_data<'a>(
        &self,
        variances: &'a Self::InternedVariances,
    ) -> &'a [chalk_ir::Variance] {
        &variances
    }
}

impl chalk_ir::interner::HasInterner for Interner {
    type Interner = Self;
}
<|endoftext|>


<commit_before>//! Server flow statistic

use std::sync::atomic::Ordering;

#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))]
type FlowCounter = std::sync::atomic::AtomicU64;
#[cfg(any(target_arch = "mips", target_arch = "powerpc"))]
type FlowCounter = std::sync::atomic::AtomicU32;

/// Connection flow statistic
pub struct FlowStat {
    tx: FlowCounter,
    rx: FlowCounter,
}

impl Default for FlowStat {
    fn default() -> Self {
        FlowStat {
            tx: FlowCounter::new(0),
            rx: FlowCounter::new(0),
        }
    }
}

impl FlowStat {
    /// Create an empty flow statistic
    pub fn new() -> FlowStat {
        FlowStat::default()
    }

    /// Transmitted bytes count
    pub fn tx(&self) -> u64 {
        self.tx.load(Ordering::Relaxed) as _
    }

    /// Increase transmitted bytes
    pub fn incr_tx(&self, n: u64) {
        self.tx.fetch_add(n as _, Ordering::AcqRel);
    }

    /// Received bytes count
    pub fn rx(&self) -> u64 {
        self.rx.load(Ordering::Relaxed) as _
    }

    /// Increase received bytes
    pub fn incr_rx(&self, n: u64) {
        self.rx.fetch_add(n as _, Ordering::AcqRel);
    }
}
<commit_msg>check AtomicU64 with target_has_atomic, fixed #924<commit_after>//! Server flow statistic

use std::sync::atomic::Ordering;

#[cfg(target_has_atomic = "64")]
type FlowCounter = std::sync::atomic::AtomicU64;
#[cfg(not(target_has_atomic = "64"))]
type FlowCounter = std::sync::atomic::AtomicU32;

/// Connection flow statistic
pub struct FlowStat {
    tx: FlowCounter,
    rx: FlowCounter,
}

impl Default for FlowStat {
    fn default() -> Self {
        FlowStat {
            tx: FlowCounter::new(0),
            rx: FlowCounter::new(0),
        }
    }
}

impl FlowStat {
    /// Create an empty flow statistic
    pub fn new() -> FlowStat {
        FlowStat::default()
    }

    /// Transmitted bytes count
    pub fn tx(&self) -> u64 {
        self.tx.load(Ordering::Relaxed) as _
    }

    /// Increase transmitted bytes
    pub fn incr_tx(&self, n: u64) {
        self.tx.fetch_add(n as _, Ordering::AcqRel);
    }

    /// Received bytes count
    pub fn rx(&self) -> u64 {
        self.rx.load(Ordering::Relaxed) as _
    }

    /// Increase received bytes
    pub fn incr_rx(&self, n: u64) {
        self.rx.fetch_add(n as _, Ordering::AcqRel);
    }
}
<|endoftext|>