<commit_before>//! Edit a `DataBase`.

use database::{write_database, DataBase};
use error::Result;
use ui::utils;
use ui::utils::CommandParser;

use std::error::Error;

#[derive(Clone, Copy, Debug)]
/// Editing commands.
enum Command {
    AddResidue,
    RemoveResidue,
    AddComponent,
    RemoveComponent,
    WriteToDisk,
    SetLocation,
    ShowDatabase,
    QuitAndSave,
    QuitWithoutSaving,
}

/// The main user menu.
pub fn user_menu(database: &mut DataBase) -> Result<&str> {
    let commands = command_parser!(
        ("ra", Command::AddResidue, "Add a residue definition"),
        ("rr", Command::RemoveResidue, "Remove a residue definition"),
        ("sa", Command::AddComponent, "Add a component definition"),
        ("sr", Command::RemoveComponent, "Remove a component definition"),
        ("w", Command::WriteToDisk, "Write database to disk"),
        ("c", Command::SetLocation, "Change output location of database"),
        ("l", Command::ShowDatabase, "List database content"),
        ("f", Command::QuitAndSave, "Finish editing database"),
        ("a", Command::QuitWithoutSaving, "Abort editing and discard changes")
    );

    let path_backup = database.path.clone();
    let residues_backup = database.residue_defs.clone();
    let components_backup = database.component_defs.clone();

    println!("Editing the current database.\n");
    database.describe();
    println!("");

    loop {
        commands.print_menu();
        let input = utils::get_input_string("Selection")?;

        if let Some((cmd, tail)) = commands.get_selection_and_tail(&input) {
            match cmd {
                Command::AddResidue => {
                    match define_residue::user_menu() {
                        Ok(residue) => {
                            println!("Added residue '{}' to database.", residue.code);
                            database.residue_defs.push(residue);
                        },
                        Err(err) => println!("Could not create residue: {}", err.description()),
                    }
                },
                Command::RemoveResidue => {
                    match utils::remove_item(&mut database.residue_defs, &tail) {
                        Ok(i) => println!("Removed residue with index {} from database.", i),
                        Err(err) => println!("Could not remove residue: {}", err.description()),
                    }
                },
                Command::AddComponent => {
                    match define_component::user_menu(&database.residue_defs) {
                        Ok(component) => {
                            println!("Added component definition '{}' to database.",
                                     component.name());
                            database.component_defs.push(component);
                        },
                        Err(err) => println!("Could not create component: {}", err.description()),
                    }
                },
                Command::RemoveComponent => {
                    match utils::remove_item(&mut database.component_defs, &tail) {
                        Ok(i) => println!("Removed substrate with index {} from database.", i),
                        Err(err) => println!("Could not remove substrate: {}", err.description()),
                    }
                },
                Command::WriteToDisk => {
                    match write_database(&database) {
                        Ok(_) => println!("Wrote database to '{}'.",
                                          database.path.as_ref().unwrap().to_str().unwrap()),
                        Err(err) => println!("Could not write database: {}", err.description()),
                    }
                },
                Command::SetLocation => {
                    match database.set_path(&tail) {
                        Ok(_) => println!("Database path set to {}.",
                                          database.get_path_pretty()),
                        Err(err) => println!("Could not change database path: {}",
                                             err.description()),
                    }
                },
                Command::ShowDatabase => {
                    println!("");
                    database.describe();
                },
                Command::QuitAndSave => {
                    return Ok("Finished editing database.");
                },
                Command::QuitWithoutSaving => {
                    database.path = path_backup;
                    database.residue_defs = residues_backup;
                    database.component_defs = components_backup;

                    return Ok("Discarding changes to database.");
                },
            }
        } else {
            println!("Not a valid selection.");
        }

        println!("");
    }
}

#[macro_use]
mod define_residue {
    //! Define a new `ResidueBase`.

    use error::{GrafenCliError, Result, UIErrorKind};
    use ui::utils;
    use ui::utils::CommandParser;

    use grafen::system::{Atom, Coord, ResidueBase};
    use std::error::Error;

    #[derive(Clone, Copy, Debug)]
    enum ResidueCommand {
        SetName,
        AddAtom,
        RemoveAtom,
        SwapAtoms,
        ShowResidue,
        QuitAndSave,
        QuitWithoutSaving,
    }

    pub fn user_menu() -> Result<ResidueBase> {
        let commands = command_parser!(
            ("n", ResidueCommand::SetName, "Set residue name"),
            ("at", ResidueCommand::AddAtom, "Add atom to residue"),
            ("r", ResidueCommand::RemoveAtom, "Remove atom from residue"),
            ("s", ResidueCommand::SwapAtoms, "Swap two atoms in list"),
            ("l", ResidueCommand::ShowResidue, "List current residue data"),
            ("f", ResidueCommand::QuitAndSave, "Finish and add residue to list"),
            ("a", ResidueCommand::QuitWithoutSaving, "Abort and discard changes")
        );

        println!("Creating a new residue.\n");

        let mut name = String::new();
        let mut atoms: Vec<Atom> = Vec::new();

        loop {
            commands.print_menu();
            let input = utils::get_input_string("Selection")?;
            println!("");

            if let Some((cmd, tail)) = commands.get_selection_and_tail(&input) {
                match cmd {
                    ResidueCommand::SetName => {
                        name = tail.to_uppercase().to_string();
                        println!("Set residue name to '{}'", &name);
                    },
                    ResidueCommand::AddAtom => {
                        match parse_string_for_atom(&tail) {
                            Ok(atom) => {
                                println!("Added atom '{}' to residue.", &atom.code);
                                atoms.push(atom);
                            },
                            Err(err) => println!("Could not add atom: {}", err.description()),
                        }

                    },
                    ResidueCommand::RemoveAtom => {
                        match utils::remove_item(&mut atoms, &tail) {
                            Ok(i) => println!("Removed atom with index {} from residue.", i),
                            Err(err) => println!("Could not remove atom: {}", err.description()),
                        }
                    },
                    ResidueCommand::SwapAtoms => {
                        match utils::swap_items(&mut atoms, &tail) {
                            Ok((i, j)) => println!("Swapped atoms at index {} with atom at {}.",
                                                   i, j),
                            Err(err) => println!("Could not swap atoms: {}", err.description()),
                        }
                    },
                    ResidueCommand::ShowResidue => {
                        describe_residue(&name, &atoms);
                    },
                    ResidueCommand::QuitAndSave => {
                        if name.is_empty() {
                            println!("Cannot add residue: No name is set");
                        } else if atoms.is_empty() {
                            println!("Cannot add residue: No atoms are set");
                        } else {
                            return Ok(ResidueBase {
                                code: name,
                                atoms: atoms,
                            });
                        }
                    }
                    ResidueCommand::QuitWithoutSaving => {
                        return Err(GrafenCliError::from(UIErrorKind::Abort));
                    },
                }
            } else {
                println!("Not a valid selection.");
            }

            println!("");
        }
    }

    fn parse_string_for_atom(input: &str) -> Result<Atom> {
        let mut iter = input.splitn(2, ' ');
        let name = iter.next().and_then(|s| {
                if s.is_empty() {
                    None
                } else {
                    Some(s)
                }
            })
            .ok_or(UIErrorKind::BadValue("No name was given".to_string()))?;

        let tail = iter.next().unwrap_or("");

        let coords = utils::parse_string(&tail)?;
        let &x = coords.get(0)
                       .ok_or(UIErrorKind::BadValue("3 positions are required".to_string()))?;
        let &y = coords.get(1)
                       .ok_or(UIErrorKind::BadValue("3 positions are required".to_string()))?;
        let &z = coords.get(2)
                       .ok_or(UIErrorKind::BadValue("3 positions are required".to_string()))?;

        Ok(Atom {
            code: name.to_uppercase().to_string(),
            position: Coord::new(x, y, z),
        })
    }

    fn describe_residue(name: &str, atoms: &[Atom]) {
        println!("Residue name: '{}'", name);
        println!("Atoms:");
        for (i, atom) in atoms.iter().enumerate() {
            let (x, y, z) = atom.position.to_tuple();
            println!("{:4}. {} at ({:.1}, {:.1}, {:.1})", i, atom.code, x, y, z);
        }
    }

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

        #[test]
        fn parse_atom_string() {
            let atom = Atom { code: "A1".to_string(), position: Coord::new(1.0, 2.0, 0.0) };
            assert_eq!(atom, parse_string_for_atom("A1 1 2 0").unwrap());
        }

        #[test]
        fn parse_atoms_without_name_or_some_values_is_error() {
            assert!(parse_string_for_atom("\t\n").is_err());
            assert!(parse_string_for_atom("\tname\n 1.0").is_err());
            assert!(parse_string_for_atom("\tname 1.0\t2.0").is_err());
            assert!(parse_string_for_atom("\tname 1.0 2.0 3").is_ok());
            assert!(parse_string_for_atom("\tname 1.0 2.0 a").is_err());
        }

        #[test]
        fn parse_atoms_sets_name_to_uppercase() {
            assert_eq!("AT1", parse_string_for_atom("at1 1 2 0").unwrap().code);
        }
    }
}

mod define_component {
    //! Define a new `SheetConfEntry`.

    use database::{AvailableComponents, CylinderConfEntry, SheetConfEntry};
    use error::{GrafenCliError, Result};
    use ui::utils;
    use ui::utils::CommandParser;

    use grafen::substrate::LatticeType;
    use grafen::system::ResidueBase;

    #[derive(Clone, Copy, Debug)]
    /// Available lattices to construct from. Each of these require
    /// a separate constructor since they have different qualities in
    /// their corresponding `LatticeType` unit.
    enum LatticeCommand {
        Triclinic,
        Hexagonal,
        PoissonDisc,
    }

    #[derive(Clone, Copy, Debug)]
    /// Available component types.
    enum ComponentSelect {
        Sheet,
        Cylinder,
    }

    pub fn user_menu(residue_list: &[ResidueBase]) -> Result<AvailableComponents> {
        match select_component_type() {
            Some(ComponentSelect::Sheet) => {
                let name = utils::get_input_string("Substrate name")
                    .and_then(|string| {
                        if string.is_empty() {
                            Err(GrafenCliError::UIError("No name was entered".to_string()))
                        } else {
                            Ok(string)
                        }
                    })
                    .map_err(|err| GrafenCliError::from(err))?;
                println!("");

                let residue = select_residue(&residue_list)?;
                println!("");
                let lattice = select_lattice()?;
                println!("");
                let std_z = select_deviation_along_z()?;
                println!("");

                Ok(AvailableComponents::Sheet(SheetConfEntry {
                    name,
                    lattice,
                    residue,
                    std_z,
                    size: None,
                    position: None
                }))
            },

            Some(ComponentSelect::Cylinder) => {
                let name = utils::get_input_string("Cylinder name")
                    .and_then(|string| {
                        if string.is_empty() {
                            Err(GrafenCliError::UIError("No name was entered".to_string()))
                        } else {
                            Ok(string)
                        }
                    })
                    .map_err(|err| GrafenCliError::from(err))?;
                println!("");

                let residue = select_residue(&residue_list)?;
                println!("");
                let lattice = select_lattice()?;
                println!("");

                Ok(AvailableComponents::Cylinder(CylinderConfEntry {
                    name,
                    lattice,
                    residue,
                    radius: None,
                    height: None,
                    position: None,
                }))
            },

            None => {
                Err(GrafenCliError::UIError("Could not select a component".to_string()))
            },
        }
    }

    fn select_component_type() -> Option<ComponentSelect> {
        let commands = command_parser!(
            ("s", ComponentSelect::Sheet, "Sheet"),
            ("c", ComponentSelect::Cylinder, "Cylinder")
        );

        commands.print_menu();
        if let Some(input) = utils::get_input_string("Selection").ok() {
            commands.get_selection(&input)
        } else {
            None
        }
    }

    fn select_residue(residue_list: &[ResidueBase]) -> Result<ResidueBase> {
        println!("Available residues:");
        for (i, residue) in residue_list.iter().enumerate() {
            println!("{:4}. {}", i, residue.code);
        }
        println!("");

        let input = utils::get_input_string("Selection")?;
        let index = utils::parse_string_for_index(&input, &residue_list)?;

        Ok(residue_list[index].clone())
    }

    fn select_lattice() -> Result<LatticeType> {
        let lattice_list = vec![
            (LatticeCommand::Triclinic, "Triclinic lattice: two base vector lengths and an angle in-between"),
            (LatticeCommand::Hexagonal, "Hexagonal lattice: a honeycomb grid with a spacing"),
            (LatticeCommand::PoissonDisc, "Poisson disc: Randomly generated points with a density")
        ];

        println!("Available lattices:");
        for (i, lattice) in lattice_list.iter().enumerate() {
            println!("{:4}. {}", i, lattice.1);
        }
        println!("");

        let input = utils::get_input_string("Selection")?;
        let index = utils::parse_string_for_index(&input, &lattice_list)?;

        match lattice_list[index].0 {
            LatticeCommand::Triclinic => {
                println!("A triclinic lattice is constructed from two base ");
                println!("vectors of length a and b, separated by an angle γ.");
                println!("");

                let input = utils::get_input_string("Input length 'a' (nm)")?;
                let a = utils::parse_string_single(&input)?;
                let input = utils::get_input_string("Input length 'b' (nm)")?;
                let b = utils::parse_string_single(&input)?;
                let input = utils::get_input_string("Input angle 'γ' (deg.)")?;
                let gamma = utils::parse_string_single(&input)?;

                Ok(LatticeType::Triclinic { a, b, gamma })
            },

            LatticeCommand::Hexagonal => {
                println!("A hexagonal lattice is a honeycomb grid with an input side length.");
                println!("");

                let input = utils::get_input_string("Input side length (nm)")?;
                let a = utils::parse_string_single(&input)?;

                Ok(LatticeType::Hexagonal { a })
            },

            LatticeCommand::PoissonDisc => {
                println!("A Poisson disc is a generated set of points with an even distribution.");
                println!("They are generated with an input density in points per area.");
                println!("");

                let input = utils::get_input_string("Input density (1/nm^2)")?;
                let density = utils::parse_string_single(&input)?;

                Ok(LatticeType::PoissonDisc { density })
            },
        }
    }

    fn select_deviation_along_z() -> Result<Option<f64>> {
        let query = "Distribute residue positions along z with this deviation in nm (default: No)";
        let selection = utils::get_input_string(query)?;

        match utils::parse_string_single(&selection) {
            Ok(value) => Ok(Some(value)),
            _ => Ok(None),
        }
    }
}
<commit_msg>Rewrite a bad line in functional form<commit_after>//! Edit a `DataBase`.

use database::{write_database, DataBase};
use error::Result;
use ui::utils;
use ui::utils::CommandParser;

use std::error::Error;

#[derive(Clone, Copy, Debug)]
/// Editing commands.
enum Command {
    AddResidue,
    RemoveResidue,
    AddComponent,
    RemoveComponent,
    WriteToDisk,
    SetLocation,
    ShowDatabase,
    QuitAndSave,
    QuitWithoutSaving,
}

/// The main user menu.
pub fn user_menu(database: &mut DataBase) -> Result<&str> {
    let commands = command_parser!(
        ("ra", Command::AddResidue, "Add a residue definition"),
        ("rr", Command::RemoveResidue, "Remove a residue definition"),
        ("sa", Command::AddComponent, "Add a component definition"),
        ("sr", Command::RemoveComponent, "Remove a component definition"),
        ("w", Command::WriteToDisk, "Write database to disk"),
        ("c", Command::SetLocation, "Change output location of database"),
        ("l", Command::ShowDatabase, "List database content"),
        ("f", Command::QuitAndSave, "Finish editing database"),
        ("a", Command::QuitWithoutSaving, "Abort editing and discard changes")
    );

    let path_backup = database.path.clone();
    let residues_backup = database.residue_defs.clone();
    let components_backup = database.component_defs.clone();

    println!("Editing the current database.\n");
    database.describe();
    println!("");

    loop {
        commands.print_menu();
        let input = utils::get_input_string("Selection")?;

        if let Some((cmd, tail)) = commands.get_selection_and_tail(&input) {
            match cmd {
                Command::AddResidue => {
                    match define_residue::user_menu() {
                        Ok(residue) => {
                            println!("Added residue '{}' to database.", residue.code);
                            database.residue_defs.push(residue);
                        },
                        Err(err) => println!("Could not create residue: {}", err.description()),
                    }
                },
                Command::RemoveResidue => {
                    match utils::remove_item(&mut database.residue_defs, &tail) {
                        Ok(i) => println!("Removed residue with index {} from database.", i),
                        Err(err) => println!("Could not remove residue: {}", err.description()),
                    }
                },
                Command::AddComponent => {
                    match define_component::user_menu(&database.residue_defs) {
                        Ok(component) => {
                            println!("Added component definition '{}' to database.",
                                     component.name());
                            database.component_defs.push(component);
                        },
                        Err(err) => println!("Could not create component: {}", err.description()),
                    }
                },
                Command::RemoveComponent => {
                    match utils::remove_item(&mut database.component_defs, &tail) {
                        Ok(i) => println!("Removed substrate with index {} from database.", i),
                        Err(err) => println!("Could not remove substrate: {}", err.description()),
                    }
                },
                Command::WriteToDisk => {
                    match write_database(&database) {
                        Ok(_) => println!("Wrote database to '{}'.",
                                          database.path.as_ref().unwrap().to_str().unwrap()),
                        Err(err) => println!("Could not write database: {}", err.description()),
                    }
                },
                Command::SetLocation => {
                    match database.set_path(&tail) {
                        Ok(_) => println!("Database path set to {}.",
                                          database.get_path_pretty()),
                        Err(err) => println!("Could not change database path: {}",
                                             err.description()),
                    }
                },
                Command::ShowDatabase => {
                    println!("");
                    database.describe();
                },
                Command::QuitAndSave => {
                    return Ok("Finished editing database.");
                },
                Command::QuitWithoutSaving => {
                    database.path = path_backup;
                    database.residue_defs = residues_backup;
                    database.component_defs = components_backup;

                    return Ok("Discarding changes to database.");
                },
            }
        } else {
            println!("Not a valid selection.");
        }

        println!("");
    }
}

#[macro_use]
mod define_residue {
    //! Define a new `ResidueBase`.

    use error::{GrafenCliError, Result, UIErrorKind};
    use ui::utils;
    use ui::utils::CommandParser;

    use grafen::system::{Atom, Coord, ResidueBase};
    use std::error::Error;

    #[derive(Clone, Copy, Debug)]
    enum ResidueCommand {
        SetName,
        AddAtom,
        RemoveAtom,
        SwapAtoms,
        ShowResidue,
        QuitAndSave,
        QuitWithoutSaving,
    }

    pub fn user_menu() -> Result<ResidueBase> {
        let commands = command_parser!(
            ("n", ResidueCommand::SetName, "Set residue name"),
            ("at", ResidueCommand::AddAtom, "Add atom to residue"),
            ("r", ResidueCommand::RemoveAtom, "Remove atom from residue"),
            ("s", ResidueCommand::SwapAtoms, "Swap two atoms in list"),
            ("l", ResidueCommand::ShowResidue, "List current residue data"),
            ("f", ResidueCommand::QuitAndSave, "Finish and add residue to list"),
            ("a", ResidueCommand::QuitWithoutSaving, "Abort and discard changes")
        );

        println!("Creating a new residue.\n");

        let mut name = String::new();
        let mut atoms: Vec<Atom> = Vec::new();

        loop {
            commands.print_menu();
            let input = utils::get_input_string("Selection")?;
            println!("");

            if let Some((cmd, tail)) = commands.get_selection_and_tail(&input) {
                match cmd {
                    ResidueCommand::SetName => {
                        name = tail.to_uppercase().to_string();
                        println!("Set residue name to '{}'", &name);
                    },
                    ResidueCommand::AddAtom => {
                        match parse_string_for_atom(&tail) {
                            Ok(atom) => {
                                println!("Added atom '{}' to residue.", &atom.code);
                                atoms.push(atom);
                            },
                            Err(err) => println!("Could not add atom: {}", err.description()),
                        }

                    },
                    ResidueCommand::RemoveAtom => {
                        match utils::remove_item(&mut atoms, &tail) {
                            Ok(i) => println!("Removed atom with index {} from residue.", i),
                            Err(err) => println!("Could not remove atom: {}", err.description()),
                        }
                    },
                    ResidueCommand::SwapAtoms => {
                        match utils::swap_items(&mut atoms, &tail) {
                            Ok((i, j)) => println!("Swapped atoms at index {} with atom at {}.",
                                                   i, j),
                            Err(err) => println!("Could not swap atoms: {}", err.description()),
                        }
                    },
                    ResidueCommand::ShowResidue => {
                        describe_residue(&name, &atoms);
                    },
                    ResidueCommand::QuitAndSave => {
                        if name.is_empty() {
                            println!("Cannot add residue: No name is set");
                        } else if atoms.is_empty() {
                            println!("Cannot add residue: No atoms are set");
                        } else {
                            return Ok(ResidueBase {
                                code: name,
                                atoms: atoms,
                            });
                        }
                    }
                    ResidueCommand::QuitWithoutSaving => {
                        return Err(GrafenCliError::from(UIErrorKind::Abort));
                    },
                }
            } else {
                println!("Not a valid selection.");
            }

            println!("");
        }
    }

    fn parse_string_for_atom(input: &str) -> Result<Atom> {
        let mut iter = input.splitn(2, ' ');
        let name = iter.next().and_then(|s| {
                if s.is_empty() {
                    None
                } else {
                    Some(s)
                }
            })
            .ok_or(UIErrorKind::BadValue("No name was given".to_string()))?;

        let tail = iter.next().unwrap_or("");

        let coords = utils::parse_string(&tail)?;
        let &x = coords.get(0)
                       .ok_or(UIErrorKind::BadValue("3 positions are required".to_string()))?;
        let &y = coords.get(1)
                       .ok_or(UIErrorKind::BadValue("3 positions are required".to_string()))?;
        let &z = coords.get(2)
                       .ok_or(UIErrorKind::BadValue("3 positions are required".to_string()))?;

        Ok(Atom {
            code: name.to_uppercase().to_string(),
            position: Coord::new(x, y, z),
        })
    }

    fn describe_residue(name: &str, atoms: &[Atom]) {
        println!("Residue name: '{}'", name);
        println!("Atoms:");
        for (i, atom) in atoms.iter().enumerate() {
            let (x, y, z) = atom.position.to_tuple();
            println!("{:4}. {} at ({:.1}, {:.1}, {:.1})", i, atom.code, x, y, z);
        }
    }

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

        #[test]
        fn parse_atom_string() {
            let atom = Atom { code: "A1".to_string(), position: Coord::new(1.0, 2.0, 0.0) };
            assert_eq!(atom, parse_string_for_atom("A1 1 2 0").unwrap());
        }

        #[test]
        fn parse_atoms_without_name_or_some_values_is_error() {
            assert!(parse_string_for_atom("\t\n").is_err());
            assert!(parse_string_for_atom("\tname\n 1.0").is_err());
            assert!(parse_string_for_atom("\tname 1.0\t2.0").is_err());
            assert!(parse_string_for_atom("\tname 1.0 2.0 3").is_ok());
            assert!(parse_string_for_atom("\tname 1.0 2.0 a").is_err());
        }

        #[test]
        fn parse_atoms_sets_name_to_uppercase() {
            assert_eq!("AT1", parse_string_for_atom("at1 1 2 0").unwrap().code);
        }
    }
}

mod define_component {
    //! Define a new `SheetConfEntry`.

    use database::{AvailableComponents, CylinderConfEntry, SheetConfEntry};
    use error::{GrafenCliError, Result};
    use ui::utils;
    use ui::utils::CommandParser;

    use grafen::substrate::LatticeType;
    use grafen::system::ResidueBase;

    #[derive(Clone, Copy, Debug)]
    /// Available lattices to construct from. Each of these require
    /// a separate constructor since they have different qualities in
    /// their corresponding `LatticeType` unit.
    enum LatticeCommand {
        Triclinic,
        Hexagonal,
        PoissonDisc,
    }

    #[derive(Clone, Copy, Debug)]
    /// Available component types.
    enum ComponentSelect {
        Sheet,
        Cylinder,
    }

    pub fn user_menu(residue_list: &[ResidueBase]) -> Result<AvailableComponents> {
        match select_component_type() {
            Some(ComponentSelect::Sheet) => {
                let name = utils::get_input_string("Substrate name")
                    .and_then(|string| {
                        if string.is_empty() {
                            Err(GrafenCliError::UIError("No name was entered".to_string()))
                        } else {
                            Ok(string)
                        }
                    })
                    .map_err(|err| GrafenCliError::from(err))?;
                println!("");

                let residue = select_residue(&residue_list)?;
                println!("");
                let lattice = select_lattice()?;
                println!("");
                let std_z = select_deviation_along_z()?;
                println!("");

                Ok(AvailableComponents::Sheet(SheetConfEntry {
                    name,
                    lattice,
                    residue,
                    std_z,
                    size: None,
                    position: None
                }))
            },

            Some(ComponentSelect::Cylinder) => {
                let name = utils::get_input_string("Cylinder name")
                    .and_then(|string| {
                        if string.is_empty() {
                            Err(GrafenCliError::UIError("No name was entered".to_string()))
                        } else {
                            Ok(string)
                        }
                    })
                    .map_err(|err| GrafenCliError::from(err))?;
                println!("");

                let residue = select_residue(&residue_list)?;
                println!("");
                let lattice = select_lattice()?;
                println!("");

                Ok(AvailableComponents::Cylinder(CylinderConfEntry {
                    name,
                    lattice,
                    residue,
                    radius: None,
                    height: None,
                    position: None,
                }))
            },

            None => {
                Err(GrafenCliError::UIError("Could not select a component".to_string()))
            },
        }
    }

    fn select_component_type() -> Option<ComponentSelect> {
        let commands = command_parser!(
            ("s", ComponentSelect::Sheet, "Sheet"),
            ("c", ComponentSelect::Cylinder, "Cylinder")
        );
        commands.print_menu();
        utils::get_input_string("Selection").ok().and_then(|input| commands.get_selection(&input))
    }

    fn select_residue(residue_list: &[ResidueBase]) -> Result<ResidueBase> {
        println!("Available residues:");
        for (i, residue) in residue_list.iter().enumerate() {
            println!("{:4}. {}", i, residue.code);
        }
        println!("");

        let input = utils::get_input_string("Selection")?;
        let index = utils::parse_string_for_index(&input, &residue_list)?;

        Ok(residue_list[index].clone())
    }

    fn select_lattice() -> Result<LatticeType> {
        let lattice_list = vec![
            (LatticeCommand::Triclinic, "Triclinic lattice: two base vector lengths and an angle in-between"),
            (LatticeCommand::Hexagonal, "Hexagonal lattice: a honeycomb grid with a spacing"),
            (LatticeCommand::PoissonDisc, "Poisson disc: Randomly generated points with a density")
        ];

        println!("Available lattices:");
        for (i, lattice) in lattice_list.iter().enumerate() {
            println!("{:4}. {}", i, lattice.1);
        }
        println!("");

        let input = utils::get_input_string("Selection")?;
        let index = utils::parse_string_for_index(&input, &lattice_list)?;

        match lattice_list[index].0 {
            LatticeCommand::Triclinic => {
                println!("A triclinic lattice is constructed from two base ");
                println!("vectors of length a and b, separated by an angle γ.");
                println!("");

                let input = utils::get_input_string("Input length 'a' (nm)")?;
                let a = utils::parse_string_single(&input)?;
                let input = utils::get_input_string("Input length 'b' (nm)")?;
                let b = utils::parse_string_single(&input)?;
                let input = utils::get_input_string("Input angle 'γ' (deg.)")?;
                let gamma = utils::parse_string_single(&input)?;

                Ok(LatticeType::Triclinic { a, b, gamma })
            },

            LatticeCommand::Hexagonal => {
                println!("A hexagonal lattice is a honeycomb grid with an input side length.");
                println!("");

                let input = utils::get_input_string("Input side length (nm)")?;
                let a = utils::parse_string_single(&input)?;

                Ok(LatticeType::Hexagonal { a })
            },

            LatticeCommand::PoissonDisc => {
                println!("A Poisson disc is a generated set of points with an even distribution.");
                println!("They are generated with an input density in points per area.");
                println!("");

                let input = utils::get_input_string("Input density (1/nm^2)")?;
                let density = utils::parse_string_single(&input)?;

                Ok(LatticeType::PoissonDisc { density })
            },
        }
    }

    fn select_deviation_along_z() -> Result<Option<f64>> {
        let query = "Distribute residue positions along z with this deviation in nm (default: No)";
        let selection = utils::get_input_string(query)?;

        match utils::parse_string_single(&selection) {
            Ok(value) => Ok(Some(value)),
            _ => Ok(None),
        }
    }
}
<|endoftext|>


<commit_before>//! TODO documentation

use std::ptr;

use wlroots_sys::{wlr_output_cursor, wlr_output_cursor_create, wlr_output_cursor_destroy,
                  wlr_output_cursor_move, wlr_output_cursor_set_image,
                  wlr_output_cursor_set_surface};

use {render,
     output::{self, Output},
     surface::{self, Surface},
     utils::{HandleErr, Handleable}};

#[derive(Debug, Eq, PartialEq)]
pub struct Cursor {
    cursor: *mut wlr_output_cursor,
    output_handle: output::Handle
}

impl Cursor {
    /// Creates a new `output::Cursor` that's bound to the given `Output`.
    ///
    /// When the `Output` is destroyed, this can no longer be used.
    ///
    /// # Ergonomics
    ///
    /// To make this easier for you, I would suggest putting the `output::Cursor` in your
    /// `OutputHandler` implementor's state so that when the `Output` is removed you
    /// just don't have to think about it and it will clean itself up by itself.
    pub fn new(output: &mut Output) -> Option<Cursor> {
        unsafe {
            let output_handle = output.weak_reference();
            let cursor = wlr_output_cursor_create(output.as_ptr());
            if cursor.is_null() {
                None
            } else {
                Some(Cursor { cursor,
                                    output_handle })
            }
        }
    }

    /// Sets the hardware cursor's image.
    pub fn set_image(&mut self, image: &render::Image) -> bool {
        unsafe {
            let cursor = self.cursor;
            let res = self.output_handle.run(|_| {
                                                 wlr_output_cursor_set_image(cursor,
                                                                             image.pixels.as_ptr(),
                                                                             image.stride,
                                                                             image.width,
                                                                             image.height,
                                                                             image.hotspot_x,
                                                                             image.hotspot_y)
                                             });
            match res {
                Ok(res) => res,
                Err(HandleErr::AlreadyDropped) => false,
                err @ Err(HandleErr::AlreadyBorrowed) => panic!(err)
            }
        }
    }

    /// Sets the hardware cursor's surface.
    pub fn set_surface<T>(&mut self, surface: T, hotspot_x: i32, hotspot_y: i32)
        where T: Into<Option<Surface>>
    {
        unsafe {
            let surface_ptr = surface.into()
                                     .map(|surface| surface.as_ptr())
                                     .unwrap_or_else(|| ptr::null_mut());
            let cursor = self.cursor;
            let res = self.output_handle.run(|_| {
                                                 wlr_output_cursor_set_surface(cursor,
                                                                               surface_ptr,
                                                                               hotspot_x,
                                                                               hotspot_y)
                                             });
            match res {
                Ok(_) | Err(HandleErr::AlreadyDropped) => {}
                err @ Err(HandleErr::AlreadyBorrowed) => panic!(err)
            }
        }
    }

    /// Moves the hardware cursor to the desired location
    pub fn move_to(&mut self, x: f64, y: f64) -> bool {
        unsafe {
            let cursor = self.cursor;
            let res = self.output_handle.run(|_| wlr_output_cursor_move(cursor, x, y));
            match res {
                Ok(res) => res,
                Err(HandleErr::AlreadyDropped) => false,
                err @ Err(HandleErr::AlreadyBorrowed) => panic!(err)
            }
        }
    }

    /// Get the coordinates of the cursor.
    ///
    /// Returned value is in (x, y) format.
    pub fn coords(&self) -> (f64, f64) {
        unsafe { ((*self.cursor).x, (*self.cursor).y) }
    }

    /// Determines if the hardware cursor is enabled or not.
    pub fn enabled(&self) -> bool {
        unsafe { (*self.cursor).enabled }
    }

    /// Determines if the hardware cursor is visible or not.
    pub fn visible(&self) -> bool {
        unsafe { (*self.cursor).visible }
    }

    /// Gets the width and height of the hardware cursor.
    ///
    /// Returned value is in (width, height) format.
    pub fn size(&self) -> (u32, u32) {
        unsafe { ((*self.cursor).width, (*self.cursor).height) }
    }

    /// Gets the hotspot coordinates of the hardware cursor.
    ///
    /// Returned value is in (x, y) coordinates.
    pub fn hotspots(&self) -> (i32, i32) {
        unsafe { ((*self.cursor).hotspot_x, (*self.cursor).hotspot_y) }
    }

    /// Gets the texture for the cursor, if a software cursor is used without a
    /// surface.
    pub fn texture<'surface>(&'surface self) -> Option<render::Texture<'surface>> {
        unsafe {
            let texture = (*self.cursor).texture;
            if texture.is_null() {
                None
            } else {
                Some(render::Texture::from_ptr(texture))
            }
        }
    }

    /// Gets the surface for the cursor, if using a cursor surface.
    pub fn surface(&self) -> Option<surface::Handle> {
        unsafe {
            let surface = (*self.cursor).surface;
            if surface.is_null() {
                None
            } else {
                Some(surface::Handle::from_ptr(surface))
            }
        }
    }
}

impl Drop for Cursor {
    fn drop(&mut self) {
        unsafe { wlr_output_cursor_destroy(self.cursor) }
    }
}
<commit_msg>Formatting<commit_after>//! TODO documentation

use std::ptr;

use wlroots_sys::{wlr_output_cursor, wlr_output_cursor_create, wlr_output_cursor_destroy,
                  wlr_output_cursor_move, wlr_output_cursor_set_image,
                  wlr_output_cursor_set_surface};

use {render,
     output::{self, Output},
     surface::{self, Surface},
     utils::{HandleErr, Handleable}};

#[derive(Debug, Eq, PartialEq)]
pub struct Cursor {
    cursor: *mut wlr_output_cursor,
    output_handle: output::Handle
}

impl Cursor {
    /// Creates a new `output::Cursor` that's bound to the given `Output`.
    ///
    /// When the `Output` is destroyed, this can no longer be used.
    ///
    /// # Ergonomics
    ///
    /// To make this easier for you, I would suggest putting the `output::Cursor` in your
    /// `OutputHandler` implementor's state so that when the `Output` is removed you
    /// just don't have to think about it and it will clean itself up by itself.
    pub fn new(output: &mut Output) -> Option<Cursor> {
        unsafe {
            let output_handle = output.weak_reference();
            let cursor = wlr_output_cursor_create(output.as_ptr());
            if cursor.is_null() {
                None
            } else {
                Some(Cursor { cursor,
                              output_handle })
            }
        }
    }

    /// Sets the hardware cursor's image.
    pub fn set_image(&mut self, image: &render::Image) -> bool {
        unsafe {
            let cursor = self.cursor;
            let res = self.output_handle.run(|_| {
                wlr_output_cursor_set_image(cursor,
                                            image.pixels.as_ptr(),
                                            image.stride,
                                            image.width,
                                            image.height,
                                            image.hotspot_x,
                                            image.hotspot_y)
            });
            match res {
                Ok(res) => res,
                Err(HandleErr::AlreadyDropped) => false,
                err @ Err(HandleErr::AlreadyBorrowed) => panic!(err)
            }
        }
    }

    /// Sets the hardware cursor's surface.
    pub fn set_surface<T>(&mut self, surface: T, hotspot_x: i32, hotspot_y: i32)
    where T: Into<Option<Surface>>
    {
        unsafe {
            let surface_ptr = surface.into()
                .map(|surface| surface.as_ptr())
                .unwrap_or_else(|| ptr::null_mut());
            let cursor = self.cursor;
            let res = self.output_handle.run(|_| {
                wlr_output_cursor_set_surface(cursor,
                                              surface_ptr,
                                              hotspot_x,
                                              hotspot_y)
            });
            match res {
                Ok(_) | Err(HandleErr::AlreadyDropped) => {}
                err @ Err(HandleErr::AlreadyBorrowed) => panic!(err)
            }
        }
    }

    /// Moves the hardware cursor to the desired location
    pub fn move_to(&mut self, x: f64, y: f64) -> bool {
        unsafe {
            let cursor = self.cursor;
            let res = self.output_handle.run(|_| wlr_output_cursor_move(cursor, x, y));
            match res {
                Ok(res) => res,
                Err(HandleErr::AlreadyDropped) => false,
                err @ Err(HandleErr::AlreadyBorrowed) => panic!(err)
            }
        }
    }

    /// Get the coordinates of the cursor.
    ///
    /// Returned value is in (x, y) format.
    pub fn coords(&self) -> (f64, f64) {
        unsafe { ((*self.cursor).x, (*self.cursor).y) }
    }

    /// Determines if the hardware cursor is enabled or not.
    pub fn enabled(&self) -> bool {
        unsafe { (*self.cursor).enabled }
    }

    /// Determines if the hardware cursor is visible or not.
    pub fn visible(&self) -> bool {
        unsafe { (*self.cursor).visible }
    }

    /// Gets the width and height of the hardware cursor.
    ///
    /// Returned value is in (width, height) format.
    pub fn size(&self) -> (u32, u32) {
        unsafe { ((*self.cursor).width, (*self.cursor).height) }
    }

    /// Gets the hotspot coordinates of the hardware cursor.
    ///
    /// Returned value is in (x, y) coordinates.
    pub fn hotspots(&self) -> (i32, i32) {
        unsafe { ((*self.cursor).hotspot_x, (*self.cursor).hotspot_y) }
    }

    /// Gets the texture for the cursor, if a software cursor is used without a
    /// surface.
    pub fn texture<'surface>(&'surface self) -> Option<render::Texture<'surface>> {
        unsafe {
            let texture = (*self.cursor).texture;
            if texture.is_null() {
                None
            } else {
                Some(render::Texture::from_ptr(texture))
            }
        }
    }

    /// Gets the surface for the cursor, if using a cursor surface.
    pub fn surface(&self) -> Option<surface::Handle> {
        unsafe {
            let surface = (*self.cursor).surface;
            if surface.is_null() {
                None
            } else {
                Some(surface::Handle::from_ptr(surface))
            }
        }
    }
}

impl Drop for Cursor {
    fn drop(&mut self) {
        unsafe { wlr_output_cursor_destroy(self.cursor) }
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]

#![cfg_attr(not(feature = "with-syntex"), feature(proc_macro, plugin))]
#![cfg_attr(not(feature = "with-syntex"), plugin(indoc))]

#[cfg(not(feature = "with-syntex"))]
#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;
extern crate skeptic;

#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/test.rs"));

#[cfg(not(feature = "with-syntex"))]
include!("test.rs.in");

#[cfg(feature = "nightly-testing")]
mod skeptic_tests {
    #![cfg_attr(feature = "nightly-testing", allow(toplevel_ref_arg))]
    #![cfg_attr(feature = "nightly-testing", allow(useless_format))]

    include!(concat!(env!("OUT_DIR"), "/skeptic-tests.rs"));
}
<commit_msg>Remove the proc_macro feature gate<commit_after>#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]

#![cfg_attr(not(feature = "with-syntex"), feature(plugin))]
#![cfg_attr(not(feature = "with-syntex"), plugin(indoc))]

#[cfg(not(feature = "with-syntex"))]
#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;
extern crate skeptic;

#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/test.rs"));

#[cfg(not(feature = "with-syntex"))]
include!("test.rs.in");

#[cfg(feature = "nightly-testing")]
mod skeptic_tests {
    #![cfg_attr(feature = "nightly-testing", allow(toplevel_ref_arg))]
    #![cfg_attr(feature = "nightly-testing", allow(useless_format))]

    include!(concat!(env!("OUT_DIR"), "/skeptic-tests.rs"));
}
<|endoftext|>


<commit_before>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! `RESTful` API and corresponding utilities.

use std::ops::Deref;
use std::marker::PhantomData;
use std::io;
use std::collections::BTreeMap;
use std::fmt;
use std::str::FromStr;

use iron::IronError;
use iron::prelude::*;
use iron::status;
use iron::headers::Cookie;
use hyper::header::{ContentType, SetCookie};
use cookie::Cookie as CookiePair;
use router::Router;
use params;
use serde_json;
use serde::{Serialize, Serializer};
use serde::de::{self, Visitor, Deserialize, Deserializer};
use failure::Fail;

use crypto::{PublicKey, SecretKey, Hash};
use encoding::serialize::{FromHex, FromHexError, ToHex, encode_hex};
use storage;

pub mod public;
pub mod private;
#[cfg(test)]
mod tests;

/// List of possible Api errors.
#[derive(Fail, Debug)]
pub enum ApiError {
    /// Storage error.
    #[fail(display = "Storage error: {}", _0)]
    Storage(
        #[cause]
        storage::Error
    ),

    /// Input/output error.
    #[fail(display = "IO error: {}", _0)]
    Io(
        #[cause]
        ::std::io::Error
    ),

    /// File not found.
    #[fail(display = "File not found")]
    FileNotFound(Hash),

    /// Not found.
    #[fail(display = "Not found")]
    NotFound,

    /// File too big.
    #[fail(display = "File too big")]
    FileTooBig,

    /// File already exists.
    #[fail(display = "File exists")]
    FileExists(Hash),

    /// Bad request.
    #[fail(display = "Bad request: {}", _0)]
    BadRequest(String),

    /// Internal error.
    #[fail(display = "Internal server error: {}", _0)]
    InternalError(Box<::std::error::Error + Send + Sync>),

    /// Unauthorized error.
    #[fail(display = "Unauthorized")]
    Unauthorized,
}

impl From<io::Error> for ApiError {
    fn from(e: io::Error) -> ApiError {
        ApiError::Io(e)
    }
}

impl From<storage::Error> for ApiError {
    fn from(e: storage::Error) -> ApiError {
        ApiError::Storage(e)
    }
}

impl From<ApiError> for IronError {
    fn from(e: ApiError) -> IronError {
        let mut body = BTreeMap::new();
        body.insert("debug", format!("{:?}", e));
        body.insert("description", e.to_string());
        let code = match e {
            ApiError::FileExists(hash) |
            ApiError::FileNotFound(hash) => {
                body.insert("hash", encode_hex(&hash));
                status::Conflict
            }
            ApiError::BadRequest(..) => status::BadRequest,
            ApiError::InternalError(..) => status::InternalServerError,
            _ => status::Conflict,
        };
        IronError::new(e.compat(), (
            code,
            ::serde_json::to_string_pretty(&body).unwrap(),
        ))
    }
}

/// `Field` that is serialized/deserialized from/to hex.
#[derive(Clone, Debug)]
struct HexField<T: AsRef<[u8]> + Clone>(pub T);

impl<T> Deref for HexField<T>
where
    T: AsRef<[u8]> + Clone,
{
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> Serialize for HexField<T>
where
    T: AsRef<[u8]> + Clone,
{
    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        ser.serialize_str(&encode_hex(&self.0))
    }
}

struct HexVisitor<T>
where
    T: AsRef<[u8]> + Clone + FromHex<Error = FromHexError>,
{
    _p: PhantomData<T>,
}

impl<'v, T> Visitor<'v> for HexVisitor<T>
where
    T: AsRef<[u8]> + Clone + FromHex<Error = FromHexError>,
{
    type Value = HexField<T>;

    fn expecting(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "expected hex represented string")
    }

    fn visit_str<E>(self, s: &str) -> Result<HexField<T>, E>
    where
        E: de::Error,
    {
        let v = T::from_hex(s).map_err(|_| de::Error::custom("Invalid hex"))?;
        Ok(HexField(v))
    }
}

impl<'de, T> Deserialize<'de> for HexField<T>
where
    T: AsRef<[u8]>
        + FromHex<Error = FromHexError>
        + ToHex
        + Clone,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(HexVisitor { _p: PhantomData })
    }
}

/// `Api` trait defines `RESTful` API.
pub trait Api {
    /// Loads hex value from the cookies.
    fn load_hex_value_from_cookie<'a>(
        &self,
        request: &'a Request,
        key: &str,
    ) -> storage::Result<Vec<u8>> {
        if let Some(&Cookie(ref cookies)) = request.headers.get() {
            for cookie in cookies.iter() {
                if let Ok(c) = CookiePair::parse(cookie.as_str()) {
                    if c.name() == key {
                        if let Ok(value) = FromHex::from_hex(c.value()) {
                            return Ok(value);
                        }
                    }
                }
            }
        }
        Err(storage::Error::new(
            format!("Unable to find value with given key {}", key),
        ))
    }

    /// Loads public and secret key from the cookies.
    fn load_keypair_from_cookies(
        &self,
        request: &Request,
    ) -> Result<(PublicKey, SecretKey), ApiError> {
        let public_key = PublicKey::from_slice(
            self.load_hex_value_from_cookie(request, "public_key")?
                .as_ref(),
        );
        let secret_key = SecretKey::from_slice(
            self.load_hex_value_from_cookie(request, "secret_key")?
                .as_ref(),
        );

        let public_key = public_key.ok_or(ApiError::Unauthorized)?;
        let secret_key = secret_key.ok_or(ApiError::Unauthorized)?;
        Ok((public_key, secret_key))
    }

    //TODO: Remove duplicate code
    /// Returns NotFound and some response with cookies.
    fn not_found_response_with_cookies(
        &self,
        json: &serde_json::Value,
        cookies: Option<Vec<String>>,
    ) -> IronResult<Response> {
        let mut resp = Response::with((
            status::NotFound,
            serde_json::to_string_pretty(json).unwrap(),
        ));
        resp.headers.set(ContentType::json());
        if let Some(cookies) = cookies {
            resp.headers.set(SetCookie(cookies));
        }
        Ok(resp)
    }

    /// Returns OK and some response with cookies.
    fn ok_response_with_cookies(
        &self,
        json: &serde_json::Value,
        cookies: Option<Vec<String>>,
    ) -> IronResult<Response> {
        let mut resp = Response::with((status::Ok, serde_json::to_string_pretty(json).unwrap()));
        resp.headers.set(ContentType::json());
        if let Some(cookies) = cookies {
            resp.headers.set(SetCookie(cookies));
        }
        Ok(resp)
    }

    /// Returns OK and some response.
    fn ok_response(&self, json: &serde_json::Value) -> IronResult<Response> {
        self.ok_response_with_cookies(json, None)
    }
    /// Returns NotFound and some response.
    fn not_found_response(&self, json: &serde_json::Value) -> IronResult<Response> {
        self.not_found_response_with_cookies(json, None)
    }

    /// Used to extend Api.
    fn wire<'b>(&self, router: &'b mut Router);
}

fn url_fragment<T>(request: &Request, name: &str) -> Result<T, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    let params = request.extensions.get::<Router>().unwrap();
    let fragment = params.find(name).ok_or_else(|| {
        ApiError::BadRequest(format!("Required parameter '{}' is missing", name))
    })?;
    let value: T = T::from_str(fragment).map_err(|e| {
        ApiError::BadRequest(format!("Invalid '{}' parameter: {}", name, e))
    })?;
    Ok(value)
}

fn optional_param<T>(request: &mut Request, name: &str) -> Result<Option<T>, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    let map = request.get_ref::<params::Params>().unwrap();
    let value = match map.find(&[name]) {
        Some(&params::Value::String(ref param)) => {
            let value: T = T::from_str(param).map_err(|e| {
                ApiError::BadRequest(format!("Invalid '{}' parameter: {}", name, e))
            })?;
            Some(value)
        }
        _ => None,
    };
    Ok(value)
}

fn required_param<T>(request: &mut Request, name: &str) -> Result<T, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    optional_param(request, name)?.ok_or_else(|| {
        ApiError::BadRequest(format!("Required parameter '{}' is missing", name))
    })
}
<commit_msg>Use proper HTTP status codes<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! `RESTful` API and corresponding utilities.

use std::ops::Deref;
use std::marker::PhantomData;
use std::io;
use std::collections::BTreeMap;
use std::fmt;
use std::str::FromStr;

use iron::IronError;
use iron::prelude::*;
use iron::status;
use iron::headers::Cookie;
use hyper::header::{ContentType, SetCookie};
use cookie::Cookie as CookiePair;
use router::Router;
use params;
use serde_json;
use serde::{Serialize, Serializer};
use serde::de::{self, Visitor, Deserialize, Deserializer};
use failure::Fail;

use crypto::{PublicKey, SecretKey, Hash};
use encoding::serialize::{FromHex, FromHexError, ToHex, encode_hex};
use storage;

pub mod public;
pub mod private;
#[cfg(test)]
mod tests;

/// List of possible Api errors.
#[derive(Fail, Debug)]
pub enum ApiError {
    /// Storage error.
    #[fail(display = "Storage error: {}", _0)]
    Storage(
        #[cause]
        storage::Error
    ),

    /// Input/output error.
    #[fail(display = "IO error: {}", _0)]
    Io(
        #[cause]
        ::std::io::Error
    ),

    /// File not found.
    #[fail(display = "File not found")]
    FileNotFound(Hash),

    /// Not found.
    #[fail(display = "Not found")]
    NotFound,

    /// File too big.
    #[fail(display = "File too big")]
    FileTooBig,

    /// File already exists.
    #[fail(display = "File exists")]
    FileExists(Hash),

    /// Bad request.
    #[fail(display = "Bad request: {}", _0)]
    BadRequest(String),

    /// Internal error.
    #[fail(display = "Internal server error: {}", _0)]
    InternalError(Box<::std::error::Error + Send + Sync>),

    /// Unauthorized error.
    #[fail(display = "Unauthorized")]
    Unauthorized,
}

impl From<io::Error> for ApiError {
    fn from(e: io::Error) -> ApiError {
        ApiError::Io(e)
    }
}

impl From<storage::Error> for ApiError {
    fn from(e: storage::Error) -> ApiError {
        ApiError::Storage(e)
    }
}

impl From<ApiError> for IronError {
    fn from(e: ApiError) -> IronError {
        let code = match e {
            ApiError::FileExists(..) => status::Conflict,
            ApiError::FileNotFound(..) |
            ApiError::NotFound => status::NotFound,
            // Note that `status::Unauthorized` does not fit here, because
            //
            // > A server generating a 401 (Unauthorized) response MUST send a
            // > WWW-Authenticate header field containing at least one challenge.
            //
            // https://tools.ietf.org/html/rfc7235#section-4.1
            ApiError::Unauthorized => status::Forbidden,

            ApiError::BadRequest(..) |
            ApiError::FileTooBig => status::BadRequest,

            ApiError::Storage(..) |
            ApiError::Io(..) |
            ApiError::InternalError(..) => status::InternalServerError,
        };
        let body = {
            let mut map = BTreeMap::new();
            map.insert("debug", format!("{:?}", e));
            map.insert("description", e.to_string());
            match e {
                ApiError::FileExists(hash) |
                ApiError::FileNotFound(hash) => {
                    map.insert("hash", encode_hex(&hash));
                }
                _ => (),
            }
            ::serde_json::to_string_pretty(&map).unwrap()
        };
        IronError::new(e.compat(), (code, body))
    }
}

/// `Field` that is serialized/deserialized from/to hex.
#[derive(Clone, Debug)]
struct HexField<T: AsRef<[u8]> + Clone>(pub T);

impl<T> Deref for HexField<T>
where
    T: AsRef<[u8]> + Clone,
{
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> Serialize for HexField<T>
where
    T: AsRef<[u8]> + Clone,
{
    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        ser.serialize_str(&encode_hex(&self.0))
    }
}

struct HexVisitor<T>
where
    T: AsRef<[u8]> + Clone + FromHex<Error = FromHexError>,
{
    _p: PhantomData<T>,
}

impl<'v, T> Visitor<'v> for HexVisitor<T>
where
    T: AsRef<[u8]> + Clone + FromHex<Error = FromHexError>,
{
    type Value = HexField<T>;

    fn expecting(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "expected hex represented string")
    }

    fn visit_str<E>(self, s: &str) -> Result<HexField<T>, E>
    where
        E: de::Error,
    {
        let v = T::from_hex(s).map_err(|_| de::Error::custom("Invalid hex"))?;
        Ok(HexField(v))
    }
}

impl<'de, T> Deserialize<'de> for HexField<T>
where
    T: AsRef<[u8]>
        + FromHex<Error = FromHexError>
        + ToHex
        + Clone,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(HexVisitor { _p: PhantomData })
    }
}

/// `Api` trait defines `RESTful` API.
pub trait Api {
    /// Loads hex value from the cookies.
    fn load_hex_value_from_cookie<'a>(
        &self,
        request: &'a Request,
        key: &str,
    ) -> storage::Result<Vec<u8>> {
        if let Some(&Cookie(ref cookies)) = request.headers.get() {
            for cookie in cookies.iter() {
                if let Ok(c) = CookiePair::parse(cookie.as_str()) {
                    if c.name() == key {
                        if let Ok(value) = FromHex::from_hex(c.value()) {
                            return Ok(value);
                        }
                    }
                }
            }
        }
        Err(storage::Error::new(
            format!("Unable to find value with given key {}", key),
        ))
    }

    /// Loads public and secret key from the cookies.
    fn load_keypair_from_cookies(
        &self,
        request: &Request,
    ) -> Result<(PublicKey, SecretKey), ApiError> {
        let public_key = PublicKey::from_slice(
            self.load_hex_value_from_cookie(request, "public_key")?
                .as_ref(),
        );
        let secret_key = SecretKey::from_slice(
            self.load_hex_value_from_cookie(request, "secret_key")?
                .as_ref(),
        );

        let public_key = public_key.ok_or(ApiError::Unauthorized)?;
        let secret_key = secret_key.ok_or(ApiError::Unauthorized)?;
        Ok((public_key, secret_key))
    }

    //TODO: Remove duplicate code
    /// Returns NotFound and some response with cookies.
    fn not_found_response_with_cookies(
        &self,
        json: &serde_json::Value,
        cookies: Option<Vec<String>>,
    ) -> IronResult<Response> {
        let mut resp = Response::with((
            status::NotFound,
            serde_json::to_string_pretty(json).unwrap(),
        ));
        resp.headers.set(ContentType::json());
        if let Some(cookies) = cookies {
            resp.headers.set(SetCookie(cookies));
        }
        Ok(resp)
    }

    /// Returns OK and some response with cookies.
    fn ok_response_with_cookies(
        &self,
        json: &serde_json::Value,
        cookies: Option<Vec<String>>,
    ) -> IronResult<Response> {
        let mut resp = Response::with((status::Ok, serde_json::to_string_pretty(json).unwrap()));
        resp.headers.set(ContentType::json());
        if let Some(cookies) = cookies {
            resp.headers.set(SetCookie(cookies));
        }
        Ok(resp)
    }

    /// Returns OK and some response.
    fn ok_response(&self, json: &serde_json::Value) -> IronResult<Response> {
        self.ok_response_with_cookies(json, None)
    }
    /// Returns NotFound and some response.
    fn not_found_response(&self, json: &serde_json::Value) -> IronResult<Response> {
        self.not_found_response_with_cookies(json, None)
    }

    /// Used to extend Api.
    fn wire<'b>(&self, router: &'b mut Router);
}

fn url_fragment<T>(request: &Request, name: &str) -> Result<T, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    let params = request.extensions.get::<Router>().unwrap();
    let fragment = params.find(name).ok_or_else(|| {
        ApiError::BadRequest(format!("Required parameter '{}' is missing", name))
    })?;
    let value: T = T::from_str(fragment).map_err(|e| {
        ApiError::BadRequest(format!("Invalid '{}' parameter: {}", name, e))
    })?;
    Ok(value)
}

fn optional_param<T>(request: &mut Request, name: &str) -> Result<Option<T>, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    let map = request.get_ref::<params::Params>().unwrap();
    let value = match map.find(&[name]) {
        Some(&params::Value::String(ref param)) => {
            let value: T = T::from_str(param).map_err(|e| {
                ApiError::BadRequest(format!("Invalid '{}' parameter: {}", name, e))
            })?;
            Some(value)
        }
        _ => None,
    };
    Ok(value)
}

fn required_param<T>(request: &mut Request, name: &str) -> Result<T, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    optional_param(request, name)?.ok_or_else(|| {
        ApiError::BadRequest(format!("Required parameter '{}' is missing", name))
    })
}
<|endoftext|>


<commit_before>use super::{AggregateSignature, EthSpec, SignedRoot};
use crate::slot_data::SlotData;
use crate::{test_utils::TestRandom, BitVector, Hash256, Slot, SyncCommitteeMessage};
use safe_arith::ArithError;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;

#[derive(Debug, PartialEq)]
pub enum Error {
    SszTypesError(ssz_types::Error),
    AlreadySigned(usize),
    SubnetCountIsZero(ArithError),
}

/// An aggregation of `SyncCommitteeMessage`s, used in creating a `SignedContributionAndProof`.
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
#[serde(bound = "T: EthSpec")]
pub struct SyncCommitteeContribution<T: EthSpec> {
    pub slot: Slot,
    pub beacon_block_root: Hash256,
    pub subcommittee_index: u64,
    pub aggregation_bits: BitVector<T::SyncSubcommitteeSize>,
    pub signature: AggregateSignature,
}

impl<T: EthSpec> SyncCommitteeContribution<T> {
    /// Create a `SyncCommitteeContribution` from:
    ///
    /// - `message`: A single `SyncCommitteeMessage`.
    /// - `subcommittee_index`: The subcommittee this contribution pertains to out of the broader
    ///     sync committee. This can be determined from the `SyncSubnetId` of the gossip subnet
    ///     this message was seen on.
    /// - `validator_sync_committee_index`: The index of the validator **within** the subcommittee.
    pub fn from_message(
        message: &SyncCommitteeMessage,
        subcommittee_index: u64,
        validator_sync_committee_index: usize,
    ) -> Result<Self, Error> {
        let mut bits = BitVector::new();
        bits.set(validator_sync_committee_index, true)
            .map_err(Error::SszTypesError)?;
        Ok(Self {
            slot: message.slot,
            beacon_block_root: message.beacon_block_root,
            subcommittee_index,
            aggregation_bits: bits,
            signature: AggregateSignature::from(&message.signature),
        })
    }

    /// Are the aggregation bitfields of these sync contribution disjoint?
    pub fn signers_disjoint_from(&self, other: &Self) -> bool {
        self.aggregation_bits
            .intersection(&other.aggregation_bits)
            .is_zero()
    }

    /// Aggregate another `SyncCommitteeContribution` into this one.
    ///
    /// The aggregation bitfields must be disjoint, and the data must be the same.
    pub fn aggregate(&mut self, other: &Self) {
        debug_assert_eq!(self.slot, other.slot);
        debug_assert_eq!(self.beacon_block_root, other.beacon_block_root);
        debug_assert_eq!(self.subcommittee_index, other.subcommittee_index);
        debug_assert!(self.signers_disjoint_from(other));

        self.aggregation_bits = self.aggregation_bits.union(&other.aggregation_bits);
        self.signature.add_assign_aggregate(&other.signature);
    }
}

impl SignedRoot for Hash256 {}

/// This is not in the spec, but useful for determining uniqueness of sync committee contributions
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
pub struct SyncContributionData {
    pub slot: Slot,
    pub beacon_block_root: Hash256,
    pub subcommittee_index: u64,
}

impl SyncContributionData {
    pub fn from_contribution<T: EthSpec>(signing_data: &SyncCommitteeContribution<T>) -> Self {
        Self {
            slot: signing_data.slot,
            beacon_block_root: signing_data.beacon_block_root,
            subcommittee_index: signing_data.subcommittee_index,
        }
    }
}

impl<T: EthSpec> SlotData for SyncCommitteeContribution<T> {
    fn get_slot(&self) -> Slot {
        self.slot
    }
}

impl SlotData for SyncContributionData {
    fn get_slot(&self) -> Slot {
        self.slot
    }
}

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

    ssz_and_tree_hash_tests!(SyncCommitteeContribution<MainnetEthSpec>);
}
<commit_msg>Quote integers in sync committee contributions (#2515)<commit_after>use super::{AggregateSignature, EthSpec, SignedRoot};
use crate::slot_data::SlotData;
use crate::{test_utils::TestRandom, BitVector, Hash256, Slot, SyncCommitteeMessage};
use safe_arith::ArithError;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;

#[derive(Debug, PartialEq)]
pub enum Error {
    SszTypesError(ssz_types::Error),
    AlreadySigned(usize),
    SubnetCountIsZero(ArithError),
}

/// An aggregation of `SyncCommitteeMessage`s, used in creating a `SignedContributionAndProof`.
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
#[serde(bound = "T: EthSpec")]
pub struct SyncCommitteeContribution<T: EthSpec> {
    pub slot: Slot,
    pub beacon_block_root: Hash256,
    #[serde(with = "serde_utils::quoted_u64")]
    pub subcommittee_index: u64,
    pub aggregation_bits: BitVector<T::SyncSubcommitteeSize>,
    pub signature: AggregateSignature,
}

impl<T: EthSpec> SyncCommitteeContribution<T> {
    /// Create a `SyncCommitteeContribution` from:
    ///
    /// - `message`: A single `SyncCommitteeMessage`.
    /// - `subcommittee_index`: The subcommittee this contribution pertains to out of the broader
    ///     sync committee. This can be determined from the `SyncSubnetId` of the gossip subnet
    ///     this message was seen on.
    /// - `validator_sync_committee_index`: The index of the validator **within** the subcommittee.
    pub fn from_message(
        message: &SyncCommitteeMessage,
        subcommittee_index: u64,
        validator_sync_committee_index: usize,
    ) -> Result<Self, Error> {
        let mut bits = BitVector::new();
        bits.set(validator_sync_committee_index, true)
            .map_err(Error::SszTypesError)?;
        Ok(Self {
            slot: message.slot,
            beacon_block_root: message.beacon_block_root,
            subcommittee_index,
            aggregation_bits: bits,
            signature: AggregateSignature::from(&message.signature),
        })
    }

    /// Are the aggregation bitfields of these sync contribution disjoint?
    pub fn signers_disjoint_from(&self, other: &Self) -> bool {
        self.aggregation_bits
            .intersection(&other.aggregation_bits)
            .is_zero()
    }

    /// Aggregate another `SyncCommitteeContribution` into this one.
    ///
    /// The aggregation bitfields must be disjoint, and the data must be the same.
    pub fn aggregate(&mut self, other: &Self) {
        debug_assert_eq!(self.slot, other.slot);
        debug_assert_eq!(self.beacon_block_root, other.beacon_block_root);
        debug_assert_eq!(self.subcommittee_index, other.subcommittee_index);
        debug_assert!(self.signers_disjoint_from(other));

        self.aggregation_bits = self.aggregation_bits.union(&other.aggregation_bits);
        self.signature.add_assign_aggregate(&other.signature);
    }
}

impl SignedRoot for Hash256 {}

/// This is not in the spec, but useful for determining uniqueness of sync committee contributions
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
pub struct SyncContributionData {
    pub slot: Slot,
    pub beacon_block_root: Hash256,
    pub subcommittee_index: u64,
}

impl SyncContributionData {
    pub fn from_contribution<T: EthSpec>(signing_data: &SyncCommitteeContribution<T>) -> Self {
        Self {
            slot: signing_data.slot,
            beacon_block_root: signing_data.beacon_block_root,
            subcommittee_index: signing_data.subcommittee_index,
        }
    }
}

impl<T: EthSpec> SlotData for SyncCommitteeContribution<T> {
    fn get_slot(&self) -> Slot {
        self.slot
    }
}

impl SlotData for SyncContributionData {
    fn get_slot(&self) -> Slot {
        self.slot
    }
}

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

    ssz_and_tree_hash_tests!(SyncCommitteeContribution<MainnetEthSpec>);
}
<|endoftext|>


<commit_before>//
//
//
/// Returns true if the passed exppression matches the pattern
#[macro_export]
macro_rules! is
{
	($val:expr, $p:pat) => ( match $val { $p => true, _ => false } );
}

#[doc(hidden)]
#[macro_export]
macro_rules! _count
{
	() => {0};
	($a:expr) => {1};
	($a:expr, $($b:expr),+) => {1+_count!($($b),+)};
}

/// Define a kernel module (creates the module header, containg the name and dependency strings)
#[macro_export]
macro_rules! module_define
{
	($name:ident, [$($deps:ident),*], $init:path) => (
		//#[assume_reachable]
		#[doc(hidden)]
		#[link_section = ".MODULE_LIST"]
		#[linkage="external"]
		#[allow(dead_code)]
		pub static S_MODULE: $crate::modules::ModuleInfo = $crate::modules::ModuleInfo {
			name: stringify!($name),
			init: $init,
			deps: &S_DEPS,
			_rsvd: 0,
		};
		#[doc(hidden)]
		static S_DEPS: [&'static str; _count!($($deps),*)] = [$(stringify!($deps)),*];
	);
}

/// Ensure that a type implments the provided trait
///
/// Useful for "Send" and "Sync"
#[macro_export]
macro_rules! assert_trait
{
	($t:ty : $tr:ident) => { #[allow(warnings)] fn assert_trait<T: $tr>() { } #[allow(dead_code)] fn call_assert_trait() { assert_trait::<$t>() } }
}

#[doc(hidden)]
#[tag_safe(irq)]
pub fn type_name<T: ?::core::marker::Sized>() -> &'static str { unsafe { ::core::intrinsics::type_name::<T>() } }
/// A safe wrapper around the `type_name` intrinsic
#[macro_export]
macro_rules! type_name
{
	($t:ty) => ( $crate::macros::type_name::<$t>() );
}

/// Iterator helper, desugars to a.zip(b)
macro_rules! zip
{
	($a:expr, $b:expr) => ( $a.zip($b) );
}
/// Iterator helper, desugars to a.chain(b).chain(b2)
macro_rules! chain
{
	($b:expr, $($b:expr),+) => ( $a$(.chain($b))+ );
}

/// Provides a short and noticable "TODO: " message
#[macro_export]
macro_rules! todo
{
	( $s:expr ) => ( panic!( concat!("TODO: ",$s) ) );
	( $s:expr, $($v:tt)* ) => ( panic!( concat!("TODO: ",$s), $($v)* ) );
}

/// Provides a less boiler-plate way to implement fmt traits for simple types
///
/// Only supports non-generic types and unbounded types (due to challenges in matching generic definitions)
///
/// ```
/// impl_fmt! {
///     Debug(self, f) for Type {
///         write!(f, "Hello world!")
///     }
///     <T> Display(self, f) for Container {
///         write!(f, "Hello world!")
///     }
/// }
/// ```
#[macro_export]
macro_rules! impl_fmt
{
	( $( <$($g:ident),+> $tr:ident ($s:ident, $f:ident) for $ty:ty { $code:expr } )+ ) => { $(
		impl<$($g),+> ::core::fmt::$tr for $ty {
			fn fmt(&$s, $f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
				$code
			}
		}
		)+
		};

	( $( $tr:ident ($s:ident, $f:ident) for $ty:ty { $code:expr } )+ ) => { $(
		impl ::core::fmt::$tr for $ty {
			fn fmt(&$s, $f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
				$code
			}
		}
		)+
		};
}

// NOTE: This should really be in ::threads::wait_queue, but it also needs to be early in parse
/// Wait on a wait queue contained within a spinlock
///
/// Due to lifetime issues, the more erganomical `lock.queue.wait(lock)` does not pass borrow checking.
macro_rules! waitqueue_wait_ext {
	($lock:expr, $field:ident) => ({
		let mut lock: $crate::arch::sync::HeldSpinlock<_> = $lock;
		let irql = lock.$field.wait_int();
		::core::mem::drop(lock);
		::core::mem::drop(irql);
		$crate::threads::reschedule();
		});
}

// vim: ft=rust
<commit_msg>Core - Add a local copy of try! that uses the `From` trait<commit_after>//
//
//
/// Returns true if the passed exppression matches the pattern
#[macro_export]
macro_rules! is
{
	($val:expr, $p:pat) => ( match $val { $p => true, _ => false } );
}

#[doc(hidden)]
#[macro_export]
macro_rules! _count
{
	() => {0};
	($a:expr) => {1};
	($a:expr, $($b:expr),+) => {1+_count!($($b),+)};
}

/// Define a kernel module (creates the module header, containg the name and dependency strings)
#[macro_export]
macro_rules! module_define
{
	($name:ident, [$($deps:ident),*], $init:path) => (
		//#[assume_reachable]
		#[doc(hidden)]
		#[link_section = ".MODULE_LIST"]
		#[linkage="external"]
		#[allow(dead_code)]
		pub static S_MODULE: $crate::modules::ModuleInfo = $crate::modules::ModuleInfo {
			name: stringify!($name),
			init: $init,
			deps: &S_DEPS,
			_rsvd: 0,
		};
		#[doc(hidden)]
		static S_DEPS: [&'static str; _count!($($deps),*)] = [$(stringify!($deps)),*];
	);
}

/// Ensure that a type implments the provided trait
///
/// Useful for "Send" and "Sync"
#[macro_export]
macro_rules! assert_trait
{
	($t:ty : $tr:ident) => { #[allow(warnings)] fn assert_trait<T: $tr>() { } #[allow(dead_code)] fn call_assert_trait() { assert_trait::<$t>() } }
}

#[doc(hidden)]
#[tag_safe(irq)]
pub fn type_name<T: ?::core::marker::Sized>() -> &'static str { unsafe { ::core::intrinsics::type_name::<T>() } }
/// A safe wrapper around the `type_name` intrinsic
#[macro_export]
macro_rules! type_name
{
	($t:ty) => ( $crate::macros::type_name::<$t>() );
}

/// Iterator helper, desugars to a.zip(b)
macro_rules! zip
{
	($a:expr, $b:expr) => ( $a.zip($b) );
}
/// Iterator helper, desugars to a.chain(b).chain(b2)
macro_rules! chain
{
	($b:expr, $($b:expr),+) => ( $a$(.chain($b))+ );
}

/// Provides a short and noticable "TODO: " message
#[macro_export]
macro_rules! todo
{
	( $s:expr ) => ( panic!( concat!("TODO: ",$s) ) );
	( $s:expr, $($v:tt)* ) => ( panic!( concat!("TODO: ",$s), $($v)* ) );
}

/// Provides a less boiler-plate way to implement fmt traits for simple types
///
/// Only supports non-generic types and unbounded types (due to challenges in matching generic definitions)
///
/// ```
/// impl_fmt! {
///     Debug(self, f) for Type {
///         write!(f, "Hello world!")
///     }
///     <T> Display(self, f) for Container {
///         write!(f, "Hello world!")
///     }
/// }
/// ```
#[macro_export]
macro_rules! impl_fmt
{
	( $( <$($g:ident),+> $tr:ident ($s:ident, $f:ident) for $ty:ty { $code:expr } )+ ) => { $(
		impl<$($g),+> ::core::fmt::$tr for $ty {
			fn fmt(&$s, $f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
				$code
			}
		}
		)+
		};

	( $( $tr:ident ($s:ident, $f:ident) for $ty:ty { $code:expr } )+ ) => { $(
		impl ::core::fmt::$tr for $ty {
			fn fmt(&$s, $f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
				$code
			}
		}
		)+
		};
}

// NOTE: This should really be in ::threads::wait_queue, but it also needs to be early in parse
/// Wait on a wait queue contained within a spinlock
///
/// Due to lifetime issues, the more erganomical `lock.queue.wait(lock)` does not pass borrow checking.
macro_rules! waitqueue_wait_ext {
	($lock:expr, $field:ident) => ({
		let mut lock: $crate::arch::sync::HeldSpinlock<_> = $lock;
		let irql = lock.$field.wait_int();
		::core::mem::drop(lock);
		::core::mem::drop(irql);
		$crate::threads::reschedule();
		});
}

/// Override libcore's `try!` macro with one that backs onto `From`
macro_rules! try {
	($e:expr) => (
		match $e
		{
		Ok(v) => v,
		Err(e) => return Err(From::from(e)),
		}
		);
}

// vim: ft=rust
<|endoftext|>


<commit_before>use na::{self, DefaultAllocator};

use traits::{Number, Alloc, Dimension};
use aliases::TMat;

/// The sum of every components of the given matrix or vector.
///
/// # See also:
///
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`comp_mul`](fn.comp_mul.html)
pub fn comp_add<N: Number, R: Dimension, C: Dimension>(m: &TMat<N, R, C>) -> N
    where DefaultAllocator: Alloc<N, R, C> {
    m.iter().fold(N::zero(), |x, y| x + *y)
}

/// The maximum of every components of the given matrix or vector.
///
/// # See also:
///
/// * [`comp_add`](fn.comp_add.html)
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`max`](fn.max.html)
/// * [`max2`](fn.max2.html)
/// * [`max3`](fn.max3.html)
/// * [`max4`](fn.max4.html)
pub fn comp_max<N: Number, R: Dimension, C: Dimension>(m: &TMat<N, R, C>) -> N
    where DefaultAllocator: Alloc<N, R, C> {
    m.iter().fold(N::min_value(), |x, y| na::sup(&x, y))
}

/// The minimum of every components of the given matrix or vector.
///
/// # See also:
///
/// * [`comp_add`](fn.comp_add.html)
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_mul`](fn.comp_mul.html)
/// * [`min`](fn.min.html)
/// * [`min2`](fn.min2.html)
/// * [`min3`](fn.min3.html)
/// * [`min4`](fn.min4.html)
pub fn comp_min<N: Number, R: Dimension, C: Dimension>(m: &TMat<N, R, C>) -> N
    where DefaultAllocator: Alloc<N, R, C> {
    m.iter().fold(N::max_value(), |x, y| na::inf(&x, y))
}

/// The product of every components of the given matrix or vector.
///
/// # See also:
///
/// * [`comp_add`](fn.comp_add.html)
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
pub fn comp_mul<N: Number, R: Dimension, C: Dimension>(m: &TMat<N, R, C>) -> N
    where DefaultAllocator: Alloc<N, R, C> {
    m.iter().fold(N::one(), |x, y| x * *y)
}

//pub fn vec< L, floatType, Q > compNormalize (vec< L, T, Q > const &v)
//pub fn vec< L, T, Q > compScale (vec< L, floatType, Q > const &v)
<commit_msg>'every components' -> 'every component'<commit_after>use na::{self, DefaultAllocator};

use traits::{Number, Alloc, Dimension};
use aliases::TMat;

/// The sum of every component of the given matrix or vector.
///
/// # See also:
///
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`comp_mul`](fn.comp_mul.html)
pub fn comp_add<N: Number, R: Dimension, C: Dimension>(m: &TMat<N, R, C>) -> N
    where DefaultAllocator: Alloc<N, R, C> {
    m.iter().fold(N::zero(), |x, y| x + *y)
}

/// The maximum of every component of the given matrix or vector.
///
/// # See also:
///
/// * [`comp_add`](fn.comp_add.html)
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`max`](fn.max.html)
/// * [`max2`](fn.max2.html)
/// * [`max3`](fn.max3.html)
/// * [`max4`](fn.max4.html)
pub fn comp_max<N: Number, R: Dimension, C: Dimension>(m: &TMat<N, R, C>) -> N
    where DefaultAllocator: Alloc<N, R, C> {
    m.iter().fold(N::min_value(), |x, y| na::sup(&x, y))
}

/// The minimum of every component of the given matrix or vector.
///
/// # See also:
///
/// * [`comp_add`](fn.comp_add.html)
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_mul`](fn.comp_mul.html)
/// * [`min`](fn.min.html)
/// * [`min2`](fn.min2.html)
/// * [`min3`](fn.min3.html)
/// * [`min4`](fn.min4.html)
pub fn comp_min<N: Number, R: Dimension, C: Dimension>(m: &TMat<N, R, C>) -> N
    where DefaultAllocator: Alloc<N, R, C> {
    m.iter().fold(N::max_value(), |x, y| na::inf(&x, y))
}

/// The product of every component of the given matrix or vector.
///
/// # See also:
///
/// * [`comp_add`](fn.comp_add.html)
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
pub fn comp_mul<N: Number, R: Dimension, C: Dimension>(m: &TMat<N, R, C>) -> N
    where DefaultAllocator: Alloc<N, R, C> {
    m.iter().fold(N::one(), |x, y| x * *y)
}

//pub fn vec< L, floatType, Q > compNormalize (vec< L, T, Q > const &v)
//pub fn vec< L, T, Q > compScale (vec< L, floatType, Q > const &v)
<|endoftext|>


<commit_before>#![no_std]
#![feature(panic_implementation)]

extern crate labrador_ldpc;

use labrador_ldpc::LDPCCode;
use labrador_ldpc::decoder::DecodeFrom;
use core::slice;
use core::panic::PanicInfo;

#[panic_implementation]
fn panic(_info: &PanicInfo) -> ! { loop {} }

#[no_mangle]
pub extern fn labrador_ldpc_code_n(code: LDPCCode) -> usize {
    code.n()
}

#[no_mangle]
pub extern fn labrador_ldpc_code_k(code: LDPCCode) -> usize {
    code.k()
}

#[no_mangle]
pub extern fn labrador_ldpc_encode(code: LDPCCode, codeword: *mut u8) {
    if (codeword as usize) % 4 == 0 {
        let codeword: &mut[u32] = unsafe { slice::from_raw_parts_mut(codeword as *mut u32, code.n()/32) };
        code.encode(codeword);
    } else {
        let codeword: &mut[u8] = unsafe { slice::from_raw_parts_mut(codeword, code.n()/8) };
        code.encode(codeword);
    }
}

#[no_mangle]
pub extern fn labrador_ldpc_copy_encode(code: LDPCCode, data: *const u8, codeword: *mut u8) {
    let data: &[u8] = unsafe { slice::from_raw_parts(data, code.k()/8) };
    if (codeword as usize) % 4 == 0 {
        let codeword: &mut[u32] = unsafe { slice::from_raw_parts_mut(codeword as *mut u32, code.n()/32) };
        code.copy_encode(data, codeword);
    } else {
        let codeword: &mut[u8] = unsafe { slice::from_raw_parts_mut(codeword, code.n()/8) };
        code.copy_encode(data, codeword);
    }
}

#[no_mangle]
pub extern fn labrador_ldpc_bf_working_len(code: LDPCCode) -> usize {
    code.decode_bf_working_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_ms_working_len(code: LDPCCode) -> usize {
    code.decode_ms_working_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_ms_working_u8_len(code: LDPCCode) -> usize {
    code.decode_ms_working_u8_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_output_len(code: LDPCCode) -> usize {
    code.output_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_bf(code: LDPCCode, input: *const u8, output: *mut u8,
                                      working: *mut u8, max_iters: usize,
                                      iters_run: *mut usize) -> bool
{
    let input: &[u8] = unsafe { slice::from_raw_parts(input, code.n()/8) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.output_len()) };
    let working: &mut[u8] = unsafe { slice::from_raw_parts_mut(working, code.decode_bf_working_len()) };
    let (result, iters) = code.decode_bf(input, output, working, max_iters);
    if !iters_run.is_null() {
        unsafe { *iters_run = iters };
    }
    result
}

fn decode_ms<T: DecodeFrom>(code: LDPCCode, llrs: *const T, output: *mut u8, working: *mut T,
                            working_u8: *mut u8, max_iters: usize, iters_run: *mut usize) -> bool
{
    let llrs: &[T] = unsafe { slice::from_raw_parts(llrs, code.n()) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.output_len()) };
    let working: &mut[T] = unsafe { slice::from_raw_parts_mut(working, code.decode_ms_working_len()) };
    let working_u8: &mut[u8] = unsafe { slice::from_raw_parts_mut(working_u8, code.decode_ms_working_u8_len()) };
    let (result, iters) = code.decode_ms(llrs, output, working, working_u8, max_iters);
    if !iters_run.is_null() {
        unsafe { *iters_run = iters };
    }
    result
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_i8(code: LDPCCode, llrs: *const i8, output: *mut u8,
                                         working: *mut i8, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<i8>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_i16(code: LDPCCode, llrs: *const i16, output: *mut u8,
                                         working: *mut i16, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<i16>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_f32(code: LDPCCode, llrs: *const f32, output: *mut u8,
                                         working: *mut f32, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<f32>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_f64(code: LDPCCode, llrs: *const f64, output: *mut u8,
                                         working: *mut f64, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<f64>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

fn hard_to_llrs<T: DecodeFrom>(code: LDPCCode, input: *const u8, llrs: *mut T) {
    let input: &[u8] = unsafe { slice::from_raw_parts(input, code.n()/8) };
    let llrs: &mut[T] = unsafe { slice::from_raw_parts_mut(llrs, code.n()) };
    code.hard_to_llrs(input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_i8(code: LDPCCode, input: *const u8, llrs: *mut i8) {
    hard_to_llrs::<i8>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_i16(code: LDPCCode, input: *const u8, llrs: *mut i16) {
    hard_to_llrs::<i16>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_f32(code: LDPCCode, input: *const u8, llrs: *mut f32) {
    hard_to_llrs::<f32>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_f64(code: LDPCCode, input: *const u8, llrs: *mut f64) {
    hard_to_llrs::<f64>(code, input, llrs);
}

fn llrs_to_hard<T: DecodeFrom>(code: LDPCCode, llrs: *const T, output: *mut u8) {
    let llrs: &[T] = unsafe { slice::from_raw_parts(llrs, code.n()) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.n() / 8) };
    code.llrs_to_hard(llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_i8(code: LDPCCode, llrs: *const i8, output: *mut u8) {
    llrs_to_hard::<i8>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_i16(code: LDPCCode, llrs: *const i16, output: *mut u8) {
    llrs_to_hard::<i16>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_f32(code: LDPCCode, llrs: *const f32, output: *mut u8) {
    llrs_to_hard::<f32>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_f64(code: LDPCCode, llrs: *const f64, output: *mut u8) {
    llrs_to_hard::<f64>(code, llrs, output);
}
<commit_msg>Ensure panic implementation gets exported properly<commit_after>#![no_std]
#![feature(panic_implementation)]

extern crate labrador_ldpc;

use labrador_ldpc::LDPCCode;
use labrador_ldpc::decoder::DecodeFrom;
use core::slice;

#[panic_implementation]
#[no_mangle]
pub fn panic(_info: &core::panic::PanicInfo) -> ! {
    loop {}
}

#[no_mangle]
pub extern fn labrador_ldpc_code_n(code: LDPCCode) -> usize {
    code.n()
}

#[no_mangle]
pub extern fn labrador_ldpc_code_k(code: LDPCCode) -> usize {
    code.k()
}

#[no_mangle]
pub extern fn labrador_ldpc_encode(code: LDPCCode, codeword: *mut u8) {
    if (codeword as usize) % 4 == 0 {
        let codeword: &mut[u32] = unsafe { slice::from_raw_parts_mut(codeword as *mut u32, code.n()/32) };
        code.encode(codeword);
    } else {
        let codeword: &mut[u8] = unsafe { slice::from_raw_parts_mut(codeword, code.n()/8) };
        code.encode(codeword);
    }
}

#[no_mangle]
pub extern fn labrador_ldpc_copy_encode(code: LDPCCode, data: *const u8, codeword: *mut u8) {
    let data: &[u8] = unsafe { slice::from_raw_parts(data, code.k()/8) };
    if (codeword as usize) % 4 == 0 {
        let codeword: &mut[u32] = unsafe { slice::from_raw_parts_mut(codeword as *mut u32, code.n()/32) };
        code.copy_encode(data, codeword);
    } else {
        let codeword: &mut[u8] = unsafe { slice::from_raw_parts_mut(codeword, code.n()/8) };
        code.copy_encode(data, codeword);
    }
}

#[no_mangle]
pub extern fn labrador_ldpc_bf_working_len(code: LDPCCode) -> usize {
    code.decode_bf_working_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_ms_working_len(code: LDPCCode) -> usize {
    code.decode_ms_working_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_ms_working_u8_len(code: LDPCCode) -> usize {
    code.decode_ms_working_u8_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_output_len(code: LDPCCode) -> usize {
    code.output_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_bf(code: LDPCCode, input: *const u8, output: *mut u8,
                                      working: *mut u8, max_iters: usize,
                                      iters_run: *mut usize) -> bool
{
    let input: &[u8] = unsafe { slice::from_raw_parts(input, code.n()/8) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.output_len()) };
    let working: &mut[u8] = unsafe { slice::from_raw_parts_mut(working, code.decode_bf_working_len()) };
    let (result, iters) = code.decode_bf(input, output, working, max_iters);
    if !iters_run.is_null() {
        unsafe { *iters_run = iters };
    }
    result
}

fn decode_ms<T: DecodeFrom>(code: LDPCCode, llrs: *const T, output: *mut u8, working: *mut T,
                            working_u8: *mut u8, max_iters: usize, iters_run: *mut usize) -> bool
{
    let llrs: &[T] = unsafe { slice::from_raw_parts(llrs, code.n()) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.output_len()) };
    let working: &mut[T] = unsafe { slice::from_raw_parts_mut(working, code.decode_ms_working_len()) };
    let working_u8: &mut[u8] = unsafe { slice::from_raw_parts_mut(working_u8, code.decode_ms_working_u8_len()) };
    let (result, iters) = code.decode_ms(llrs, output, working, working_u8, max_iters);
    if !iters_run.is_null() {
        unsafe { *iters_run = iters };
    }
    result
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_i8(code: LDPCCode, llrs: *const i8, output: *mut u8,
                                         working: *mut i8, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<i8>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_i16(code: LDPCCode, llrs: *const i16, output: *mut u8,
                                         working: *mut i16, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<i16>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_f32(code: LDPCCode, llrs: *const f32, output: *mut u8,
                                         working: *mut f32, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<f32>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_f64(code: LDPCCode, llrs: *const f64, output: *mut u8,
                                         working: *mut f64, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<f64>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

fn hard_to_llrs<T: DecodeFrom>(code: LDPCCode, input: *const u8, llrs: *mut T) {
    let input: &[u8] = unsafe { slice::from_raw_parts(input, code.n()/8) };
    let llrs: &mut[T] = unsafe { slice::from_raw_parts_mut(llrs, code.n()) };
    code.hard_to_llrs(input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_i8(code: LDPCCode, input: *const u8, llrs: *mut i8) {
    hard_to_llrs::<i8>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_i16(code: LDPCCode, input: *const u8, llrs: *mut i16) {
    hard_to_llrs::<i16>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_f32(code: LDPCCode, input: *const u8, llrs: *mut f32) {
    hard_to_llrs::<f32>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_f64(code: LDPCCode, input: *const u8, llrs: *mut f64) {
    hard_to_llrs::<f64>(code, input, llrs);
}

fn llrs_to_hard<T: DecodeFrom>(code: LDPCCode, llrs: *const T, output: *mut u8) {
    let llrs: &[T] = unsafe { slice::from_raw_parts(llrs, code.n()) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.n() / 8) };
    code.llrs_to_hard(llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_i8(code: LDPCCode, llrs: *const i8, output: *mut u8) {
    llrs_to_hard::<i8>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_i16(code: LDPCCode, llrs: *const i16, output: *mut u8) {
    llrs_to_hard::<i16>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_f32(code: LDPCCode, llrs: *const f32, output: *mut u8) {
    llrs_to_hard::<f32>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_f64(code: LDPCCode, llrs: *const f64, output: *mut u8) {
    llrs_to_hard::<f64>(code, llrs, output);
}
<|endoftext|>