<commit_before>use super::super::{Y, X, Coord, Grid};
use grid_loop::{Edge, GridLoop, GridLoopField};
use super::*;

pub struct Field<'a> {
    grid_loop: GridLoop,
    clue: Grid<Clue>,
    dic: &'a Dictionary,
}
impl<'a> Field<'a> {
    pub fn new(clue: &Grid<Clue>, dic: &'a Dictionary) -> Field<'a> {
        let grid_loop = GridLoop::new(clue.height(), clue.width());

        Field {
            grid_loop: grid_loop,
            clue: clue.clone(),
            dic: dic,
        }
    }
    pub fn height(&self) -> i32 {
        self.clue.height()
    }
    pub fn width(&self) -> i32 {
        self.clue.width()
    }
    pub fn inconsistent(&self) -> bool {
        self.grid_loop.inconsistent()
    }
    pub fn set_inconsistent(&mut self) {
        self.grid_loop.set_inconsistent()
    }
    pub fn fully_solved(&self) -> bool {
        self.grid_loop.fully_solved()
    }
    pub fn check_all_cell(&mut self) {
        let height = self.height();
        let width = self.width();
        let mut handle = GridLoop::get_handle(self);
        for y in 0..height {
            for x in 0..width {
                let clue = handle.get_clue((Y(y), X(x)));
                if clue != NO_CLUE {
                    GridLoop::check(&mut *handle, (Y(y * 2 + 1), X(x * 2 + 1)));
                }
            }
        }
    }
    pub fn get_clue(&self, cd: Coord) -> Clue {
        self.clue[cd]
    }
    pub fn add_clue(&mut self, cd: Coord, clue: Clue) {
        if self.clue[cd] != NO_CLUE {
            if self.clue[cd] != clue {
                self.grid_loop.set_inconsistent();
            }
        } else {
            self.clue[cd] = clue;
            GridLoop::check(self, cd);
        }
    }
    pub fn get_edge(&mut self, cd: Coord) -> Edge {
        self.grid_loop.get_edge(cd)
    }
    pub fn get_edge_safe(&mut self, cd: Coord) -> Edge {
        self.grid_loop.get_edge_safe(cd)
    }

    fn inspect_technique(&mut self, (Y(y), X(x)): Coord) {
        if y % 2 == 1 && x % 2 == 1 {
            let clue = self.clue[(Y(y / 2), X(x / 2))];
            if clue == Clue(3) {
                let neighbor = [
                    (Y(1), X(0)),
                    (Y(0), X(1)),
                    (Y(-1), X(0)),
                    (Y(0), X(-1)),
                ];

                // adjacent 3
                for d in 0..4 {
                    let (Y(dy), X(dx)) = neighbor[d];
                    let cell2 = (Y(y / 2 + dy), X(x / 2 + dx));
                    if self.clue.is_valid_coord(cell2) && self.clue[cell2] == Clue(3) {
                        // Deriberately ignoring the possible small loop encircling the two 3's
                        GridLoop::decide_edge(self, (Y(y - dy), X(x - dx)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y + dy), X(x + dx)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y + 3 * dy), X(x + 3 * dx)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y + dy + 2 * dx), X(x + dx + 2 * dy)), Edge::Blank);
                        GridLoop::decide_edge(self, (Y(y + dy - 2 * dx), X(x + dx - 2 * dy)), Edge::Blank);
                    }
                }

                // diagonal 3
                for d in 0..4 {
                    let (Y(dy1), X(dx1)) = neighbor[d];
                    let (Y(dy2), X(dx2)) = neighbor[(d + 1) % 4];
                    let cell2 = (Y(y / 2 + dy1 + dy2), X(x / 2 + dx1 + dx2));
                    if self.clue.is_valid_coord(cell2) && self.clue[cell2] == Clue(3) {
                        GridLoop::decide_edge(self, (Y(y - dy1), X(x - dx1)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y - dy2), X(x - dx2)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y + 2 * dy1 + 3 * dy2), X(x + 2 * dx1 + 3 * dx2)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y + 3 * dy1 + 2 * dy2), X(x + 3 * dx1 + 2 * dx2)), Edge::Line);
                    }
                }
            }
        }
    }
}
impl<'a> GridLoopField for Field<'a> {
    fn grid_loop(&mut self) -> &mut GridLoop {
        &mut self.grid_loop
    }
    fn check_neighborhood(&mut self, (Y(y), X(x)): Coord) {
        if y % 2 == 1 {
            GridLoop::check(self, (Y(y - 1), X(x)));
            GridLoop::check(self, (Y(y + 1), X(x)));

            GridLoop::check(self, (Y(y), X(x - 1)));
            GridLoop::check(self, (Y(y), X(x + 1)));
            GridLoop::check(self, (Y(y - 2), X(x - 1)));
            GridLoop::check(self, (Y(y - 2), X(x + 1)));
            GridLoop::check(self, (Y(y + 2), X(x - 1)));
            GridLoop::check(self, (Y(y + 2), X(x + 1)));
        } else {
            GridLoop::check(self, (Y(y), X(x - 1)));
            GridLoop::check(self, (Y(y), X(x + 1)));

            GridLoop::check(self, (Y(y - 1), X(x)));
            GridLoop::check(self, (Y(y + 1), X(x)));
            GridLoop::check(self, (Y(y - 1), X(x - 2)));
            GridLoop::check(self, (Y(y + 1), X(x - 2)));
            GridLoop::check(self, (Y(y - 1), X(x + 2)));
            GridLoop::check(self, (Y(y + 1), X(x + 2)));
        }
    }
    fn inspect(&mut self, (Y(y), X(x)): Coord) {
        if y % 2 == 1 && x % 2 == 1 {
            let clue = self.clue[(Y(y / 2), X(x / 2))];
            if clue == NO_CLUE { return; }

            let mut neighbors = [Edge::Undecided; DICTIONARY_NEIGHBOR_SIZE];
            for i in 0..DICTIONARY_NEIGHBOR_SIZE {
                let (Y(dy), X(dx)) = DICTIONARY_EDGE_OFFSET[i];
                neighbors[i] = self.grid_loop.get_edge_safe((Y(y + dy), X(x + dx)));
            }

            if self.dic.consult(clue, &mut neighbors) {
                self.grid_loop.set_inconsistent();
                return;
            }

            for i in 0..DICTIONARY_NEIGHBOR_SIZE {
                if neighbors[i] != Edge::Undecided {
                    let (Y(dy), X(dx)) = DICTIONARY_EDGE_OFFSET[i];
                    GridLoop::decide_edge(self, (Y(y + dy), X(x + dx)), neighbors[i]);
                }
            }

            self.inspect_technique((Y(y), X(x)));
        }
    }
}

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

    fn run_problem_test(dic: &Dictionary, input: &[&str], fully_solved: bool) {
        let height = (input.len() / 2) as i32;
        let width = (input[0].len() / 2) as i32;

        let mut clue = Grid::new(height, width, NO_CLUE);
        for y in 0..height {
            let mut row_iter = input[(y * 2 + 1) as usize].chars();

            for x in 0..width {
                row_iter.next();
                let c = row_iter.next().unwrap();
                if '0' <= c && c <= '3' {
                    clue[(Y(y), X(x))] = Clue(((c as u8) - ('0' as u8)) as i32);
                }
            }
        }

        let mut field = Field::new(&clue, dic);
        field.check_all_cell();

        assert_eq!(field.inconsistent(), false);
        assert_eq!(field.fully_solved(), fully_solved);

        for y in 0..(input.len() as i32) {
            let mut row_iter = input[y as usize].chars();

            for x in 0..(input[0].len() as i32) {
                let ch = row_iter.next().unwrap();

                if !field.grid_loop().is_edge((Y(y), X(x))) {
                    continue;
                }

                let expected_edge = match ch {
                    '|' | '-' => Edge::Line,
                    'x' => Edge::Blank,
                    _ => Edge::Undecided,
                };

                assert_eq!(field.get_edge((Y(y), X(x))), expected_edge, "Comparing at y={}, x={}", y, x);
            }
        }
    }

    #[test]
    fn test_problem() {
        let dic = Dictionary::complete();

        run_problem_test(&dic, &[
            "+x+-+-+ +",
            "x | x    ",
            "+x+-+x+ +",
            "x0x3|    ",
            "+x+-+x+ +",
            "x | x    ",
            "+x+-+-+ +",
        ], false);
        run_problem_test(&dic, &[
            "+x+-+x+x+",
            "x |3| x x",
            "+x+x+-+-+",
            "x | x x3|",
            "+x+-+x+-+",
            "x0x2| | x",
            "+x+x+-+x+",
        ], true);
        run_problem_test(&dic, &[
            "+-+-+-+-+",
            "|3x x x |",
            "+-+ +-+x+",
            "x     | |",
            "+x+ +x+-+",
            "x x x0x1x",
            "+x+x+x+x+",
        ], false);
        run_problem_test(&dic, &[
            "+ +-+-+x+",
            " 2  x2| x",
            "+ +x+x+-+",
            "| x x0x |",
            "+ + +x+ +",
            "         ",
            "+ + + + +",
        ], false);
        run_problem_test(&dic, &[
            "+ +-+ +x+",
            "   3   1x",
            "+x+-+x+ +",
            "   3  |  ",
            "+ +-+ + +",
            "         ",
            "+ + + + +",
        ], false);
        run_problem_test(&dic, &[
            "+-+-+ + +",
            "|2x      ",
            "+x+-+ + +",
            "| |3     ",
            "+ + + + +",
            "     3| x",
            "+ + +-+x+",
        ], false);
    }
}
<commit_msg>Slitherlink: &mut self -> &self in get_edge and get_edge_safe<commit_after>use super::super::{Y, X, Coord, Grid};
use grid_loop::{Edge, GridLoop, GridLoopField};
use super::*;

pub struct Field<'a> {
    grid_loop: GridLoop,
    clue: Grid<Clue>,
    dic: &'a Dictionary,
}
impl<'a> Field<'a> {
    pub fn new(clue: &Grid<Clue>, dic: &'a Dictionary) -> Field<'a> {
        let grid_loop = GridLoop::new(clue.height(), clue.width());

        Field {
            grid_loop: grid_loop,
            clue: clue.clone(),
            dic: dic,
        }
    }
    pub fn height(&self) -> i32 {
        self.clue.height()
    }
    pub fn width(&self) -> i32 {
        self.clue.width()
    }
    pub fn inconsistent(&self) -> bool {
        self.grid_loop.inconsistent()
    }
    pub fn set_inconsistent(&mut self) {
        self.grid_loop.set_inconsistent()
    }
    pub fn fully_solved(&self) -> bool {
        self.grid_loop.fully_solved()
    }
    pub fn check_all_cell(&mut self) {
        let height = self.height();
        let width = self.width();
        let mut handle = GridLoop::get_handle(self);
        for y in 0..height {
            for x in 0..width {
                let clue = handle.get_clue((Y(y), X(x)));
                if clue != NO_CLUE {
                    GridLoop::check(&mut *handle, (Y(y * 2 + 1), X(x * 2 + 1)));
                }
            }
        }
    }
    pub fn get_clue(&self, cd: Coord) -> Clue {
        self.clue[cd]
    }
    pub fn add_clue(&mut self, cd: Coord, clue: Clue) {
        if self.clue[cd] != NO_CLUE {
            if self.clue[cd] != clue {
                self.grid_loop.set_inconsistent();
            }
        } else {
            self.clue[cd] = clue;
            GridLoop::check(self, cd);
        }
    }
    pub fn get_edge(&self, cd: Coord) -> Edge {
        self.grid_loop.get_edge(cd)
    }
    pub fn get_edge_safe(&self, cd: Coord) -> Edge {
        self.grid_loop.get_edge_safe(cd)
    }

    fn inspect_technique(&mut self, (Y(y), X(x)): Coord) {
        if y % 2 == 1 && x % 2 == 1 {
            let clue = self.clue[(Y(y / 2), X(x / 2))];
            if clue == Clue(3) {
                let neighbor = [
                    (Y(1), X(0)),
                    (Y(0), X(1)),
                    (Y(-1), X(0)),
                    (Y(0), X(-1)),
                ];

                // adjacent 3
                for d in 0..4 {
                    let (Y(dy), X(dx)) = neighbor[d];
                    let cell2 = (Y(y / 2 + dy), X(x / 2 + dx));
                    if self.clue.is_valid_coord(cell2) && self.clue[cell2] == Clue(3) {
                        // Deriberately ignoring the possible small loop encircling the two 3's
                        GridLoop::decide_edge(self, (Y(y - dy), X(x - dx)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y + dy), X(x + dx)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y + 3 * dy), X(x + 3 * dx)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y + dy + 2 * dx), X(x + dx + 2 * dy)), Edge::Blank);
                        GridLoop::decide_edge(self, (Y(y + dy - 2 * dx), X(x + dx - 2 * dy)), Edge::Blank);
                    }
                }

                // diagonal 3
                for d in 0..4 {
                    let (Y(dy1), X(dx1)) = neighbor[d];
                    let (Y(dy2), X(dx2)) = neighbor[(d + 1) % 4];
                    let cell2 = (Y(y / 2 + dy1 + dy2), X(x / 2 + dx1 + dx2));
                    if self.clue.is_valid_coord(cell2) && self.clue[cell2] == Clue(3) {
                        GridLoop::decide_edge(self, (Y(y - dy1), X(x - dx1)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y - dy2), X(x - dx2)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y + 2 * dy1 + 3 * dy2), X(x + 2 * dx1 + 3 * dx2)), Edge::Line);
                        GridLoop::decide_edge(self, (Y(y + 3 * dy1 + 2 * dy2), X(x + 3 * dx1 + 2 * dx2)), Edge::Line);
                    }
                }
            }
        }
    }
}
impl<'a> GridLoopField for Field<'a> {
    fn grid_loop(&mut self) -> &mut GridLoop {
        &mut self.grid_loop
    }
    fn check_neighborhood(&mut self, (Y(y), X(x)): Coord) {
        if y % 2 == 1 {
            GridLoop::check(self, (Y(y - 1), X(x)));
            GridLoop::check(self, (Y(y + 1), X(x)));

            GridLoop::check(self, (Y(y), X(x - 1)));
            GridLoop::check(self, (Y(y), X(x + 1)));
            GridLoop::check(self, (Y(y - 2), X(x - 1)));
            GridLoop::check(self, (Y(y - 2), X(x + 1)));
            GridLoop::check(self, (Y(y + 2), X(x - 1)));
            GridLoop::check(self, (Y(y + 2), X(x + 1)));
        } else {
            GridLoop::check(self, (Y(y), X(x - 1)));
            GridLoop::check(self, (Y(y), X(x + 1)));

            GridLoop::check(self, (Y(y - 1), X(x)));
            GridLoop::check(self, (Y(y + 1), X(x)));
            GridLoop::check(self, (Y(y - 1), X(x - 2)));
            GridLoop::check(self, (Y(y + 1), X(x - 2)));
            GridLoop::check(self, (Y(y - 1), X(x + 2)));
            GridLoop::check(self, (Y(y + 1), X(x + 2)));
        }
    }
    fn inspect(&mut self, (Y(y), X(x)): Coord) {
        if y % 2 == 1 && x % 2 == 1 {
            let clue = self.clue[(Y(y / 2), X(x / 2))];
            if clue == NO_CLUE { return; }

            let mut neighbors = [Edge::Undecided; DICTIONARY_NEIGHBOR_SIZE];
            for i in 0..DICTIONARY_NEIGHBOR_SIZE {
                let (Y(dy), X(dx)) = DICTIONARY_EDGE_OFFSET[i];
                neighbors[i] = self.grid_loop.get_edge_safe((Y(y + dy), X(x + dx)));
            }

            if self.dic.consult(clue, &mut neighbors) {
                self.grid_loop.set_inconsistent();
                return;
            }

            for i in 0..DICTIONARY_NEIGHBOR_SIZE {
                if neighbors[i] != Edge::Undecided {
                    let (Y(dy), X(dx)) = DICTIONARY_EDGE_OFFSET[i];
                    GridLoop::decide_edge(self, (Y(y + dy), X(x + dx)), neighbors[i]);
                }
            }

            self.inspect_technique((Y(y), X(x)));
        }
    }
}

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

    fn run_problem_test(dic: &Dictionary, input: &[&str], fully_solved: bool) {
        let height = (input.len() / 2) as i32;
        let width = (input[0].len() / 2) as i32;

        let mut clue = Grid::new(height, width, NO_CLUE);
        for y in 0..height {
            let mut row_iter = input[(y * 2 + 1) as usize].chars();

            for x in 0..width {
                row_iter.next();
                let c = row_iter.next().unwrap();
                if '0' <= c && c <= '3' {
                    clue[(Y(y), X(x))] = Clue(((c as u8) - ('0' as u8)) as i32);
                }
            }
        }

        let mut field = Field::new(&clue, dic);
        field.check_all_cell();

        assert_eq!(field.inconsistent(), false);
        assert_eq!(field.fully_solved(), fully_solved);

        for y in 0..(input.len() as i32) {
            let mut row_iter = input[y as usize].chars();

            for x in 0..(input[0].len() as i32) {
                let ch = row_iter.next().unwrap();

                if !field.grid_loop().is_edge((Y(y), X(x))) {
                    continue;
                }

                let expected_edge = match ch {
                    '|' | '-' => Edge::Line,
                    'x' => Edge::Blank,
                    _ => Edge::Undecided,
                };

                assert_eq!(field.get_edge((Y(y), X(x))), expected_edge, "Comparing at y={}, x={}", y, x);
            }
        }
    }

    #[test]
    fn test_problem() {
        let dic = Dictionary::complete();

        run_problem_test(&dic, &[
            "+x+-+-+ +",
            "x | x    ",
            "+x+-+x+ +",
            "x0x3|    ",
            "+x+-+x+ +",
            "x | x    ",
            "+x+-+-+ +",
        ], false);
        run_problem_test(&dic, &[
            "+x+-+x+x+",
            "x |3| x x",
            "+x+x+-+-+",
            "x | x x3|",
            "+x+-+x+-+",
            "x0x2| | x",
            "+x+x+-+x+",
        ], true);
        run_problem_test(&dic, &[
            "+-+-+-+-+",
            "|3x x x |",
            "+-+ +-+x+",
            "x     | |",
            "+x+ +x+-+",
            "x x x0x1x",
            "+x+x+x+x+",
        ], false);
        run_problem_test(&dic, &[
            "+ +-+-+x+",
            " 2  x2| x",
            "+ +x+x+-+",
            "| x x0x |",
            "+ + +x+ +",
            "         ",
            "+ + + + +",
        ], false);
        run_problem_test(&dic, &[
            "+ +-+ +x+",
            "   3   1x",
            "+x+-+x+ +",
            "   3  |  ",
            "+ +-+ + +",
            "         ",
            "+ + + + +",
        ], false);
        run_problem_test(&dic, &[
            "+-+-+ + +",
            "|2x      ",
            "+x+-+ + +",
            "| |3     ",
            "+ + + + +",
            "     3| x",
            "+ + +-+x+",
        ], false);
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>minor changes, still incomplete<commit_after>use std::io::{self, Write};

fn emit_prompt() {
    print!("temp> ");
    io::stdout().flush().unwrap();
} // end emit_prompt

/*fn to_celsius(temp: f64) -> f64 {
    0.0
}

fn to_fahrenheit(temp: f64) -> f64 {
    0.0
}

fn to_kelvin(temp: f64) -> f64 {
    0.0
}
*/
fn main() {
    println!("Temperature Converter");
    println!("please enter a temperature followed by a letter for the units.");
    println!("Examples: 23f, 12.6c, 42.0k (Fahrenheit, Celsius, Kelvin)");

    loop {
        emit_prompt();

        let mut value = String::new();
        io::stdin().read_line(&mut value)
            .expect("Failed to read line");
        let value = value.trim();

        // allow a graceful exit from the program.
        if value == "quit" {
            break;
        } else if value == "exit" {
            break;
        }

        println!("You gave me: {}", value);
    }
}
<|endoftext|>


<commit_before>use {ffi, ColumnDescriptor, Raii, Return, Handle, Statement, Result, Prepared, Allocated,
     NoResult, ResultSetState};

impl<'a, 'b> Statement<'a, 'b, Allocated, NoResult> {
    /// Prepares a statement for execution. Executing a prepared statement is faster than directly
    /// executing an unprepared statement, since it is already compiled into an Access Plan. This
    /// makes preparing statement a good idea if you want to repeatedly execute a query with a
    /// different set of parameters and care about performance.
    ///
    /// # Example
    ///
    /// ```rust
    /// # use odbc::*;
    /// # fn doc() -> Result<()>{
    /// let env = create_environment_v3().map_err(|e| e.unwrap())?;
    /// let conn = env.connect("TestDataSource", "", "")?;
    /// let stmt = Statement::with_parent(&conn)?;
    /// let mut stmt = stmt.prepare("SELECT TITLE FROM MOVIES WHERE YEAR = ?")?;
    ///
    /// fn print_one_movie_from<'a> (year: u16, stmt: Statement<'a,'a, Prepared, NoResult>) -> Result<Statement<'a, 'a, Prepared, NoResult>>{
    ///    let stmt = stmt.bind_parameter(1, &year)?;
    ///    let stmt = if let Data(mut stmt) = stmt.execute()?{
    ///        if let Some(mut cursor) = stmt.fetch()?{
    ///            println!("{}", cursor.get_data::<String>(1)?.unwrap());
    ///        }
    ///        stmt.close_cursor()?
    ///    } else {
    ///       panic!("SELECT statement returned no result set");
    ///    };
    ///    stmt.reset_parameters()
    /// };
    ///
    /// for year in 1990..2010{
    ///     stmt = print_one_movie_from(year, stmt)?
    /// }
    ///
    /// # Ok(())
    /// # }
    /// ```
    pub fn prepare(mut self, sql_text: &str) -> Result<Statement<'a, 'b, Prepared, NoResult>> {
        self.raii.prepare(sql_text).into_result(&mut self)?;
        Ok(Statement::with_raii(self.raii))
    }

    /// Prepares a statement for execution. Executing a prepared statement is faster than directly
    /// executing an unprepared statement, since it is already compiled into an Access Plan. This
    /// makes preparing statement a good idea if you want to repeatedly execute a query with a
    /// different set of parameters and care about performance.
    ///
    /// # Example
    ///
    /// ```rust
    /// # use odbc::*;
    /// # fn doc() -> Result<()>{
    /// let env = create_environment_v3().map_err(|e| e.unwrap())?;
    /// let conn = env.connect("TestDataSource", "", "")?;
    /// let stmt = Statement::with_parent(&conn)?;
    /// // need encode_rs crate
    /// // let mut stmt = stmt.prepare_bytes(&GB2312.encode("select '你好' as hello").0)?;
    ///
    /// ```
    pub fn prepare_bytes(mut self, bytes: &[u8]) -> Result<Statement<'a, 'b, Prepared, NoResult>> {
        self.raii.prepare_byte(bytes).into_result(&mut self)?;
        Ok(Statement::with_raii(self.raii))
    }
}

impl<'a, 'b> Statement<'a, 'b, Prepared, NoResult> {
    /// The number of columns in a result set
    ///
    /// Can be called successfully only when the statement is in the prepared, executed, or
    /// positioned state. If the statement does not return columns the result will be 0.
    pub fn num_result_cols(&self) -> Result<i16> {
        self.raii.num_result_cols().into_result(self)
    }

    /// Returns description struct for result set column with a given index. Note: indexing is starting from 1.
    pub fn describe_col(&self, idx: u16) -> Result<ColumnDescriptor> {
        self.raii.describe_col(idx).into_result(self)
    }

    /// Executes a prepared statement.
    pub fn execute(mut self) -> Result<ResultSetState<'a, 'b, Prepared>> {
        if self.raii.execute().into_result(&mut self)? {
            let num_cols = self.raii.num_result_cols().into_result(&self)?;
            if num_cols > 0 {
                Ok(ResultSetState::Data(Statement::with_raii(self.raii)))
            } else {
                Ok(ResultSetState::NoData(Statement::with_raii(self.raii)))
            }
        } else {
            Ok(ResultSetState::NoData(Statement::with_raii(self.raii)))
        }
    }
}

impl Raii<ffi::Stmt> {
    fn prepare(&mut self, sql_text: &str) -> Return<()> {
        match unsafe {
            ffi::SQLPrepare(
                self.handle(),
                sql_text.as_bytes().as_ptr(),
                sql_text.as_bytes().len() as ffi::SQLINTEGER,
            )
        } {
            ffi::SQL_SUCCESS => Return::Success(()),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
            ffi::SQL_ERROR => Return::Error,
            r => panic!("SQLPrepare returned unexpected result: {:?}", r),
        }
    }

    fn prepare_byte(&mut self, bytes: &[u8]) -> Return<()> {
        match unsafe {
            ffi::SQLPrepare(
                self.handle(),
                bytes.as_ptr(),
                bytes.len() as ffi::SQLINTEGER,
            )
        } {
            ffi::SQL_SUCCESS => Return::Success(()),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
            ffi::SQL_ERROR => Return::Error,
            r => panic!("SQLPrepare returned unexpected result: {:?}", r),
        }
    }

    fn execute(&mut self) -> Return<bool> {
        match unsafe { ffi::SQLExecute(self.handle()) } {
            ffi::SQL_SUCCESS => Return::Success(true),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(true),
            ffi::SQL_ERROR => Return::Error,
            ffi::SQL_NO_DATA => Return::Success(false),
            r => panic!("SQLExecute returned unexpected result: {:?}", r),
        }
    }
}
<commit_msg>modify prepare_bytes doc<commit_after>use {ffi, ColumnDescriptor, Raii, Return, Handle, Statement, Result, Prepared, Allocated,
     NoResult, ResultSetState};

impl<'a, 'b> Statement<'a, 'b, Allocated, NoResult> {
    /// Prepares a statement for execution. Executing a prepared statement is faster than directly
    /// executing an unprepared statement, since it is already compiled into an Access Plan. This
    /// makes preparing statement a good idea if you want to repeatedly execute a query with a
    /// different set of parameters and care about performance.
    ///
    /// # Example
    ///
    /// ```rust
    /// # use odbc::*;
    /// # fn doc() -> Result<()>{
    /// let env = create_environment_v3().map_err(|e| e.unwrap())?;
    /// let conn = env.connect("TestDataSource", "", "")?;
    /// let stmt = Statement::with_parent(&conn)?;
    /// let mut stmt = stmt.prepare("SELECT TITLE FROM MOVIES WHERE YEAR = ?")?;
    ///
    /// fn print_one_movie_from<'a> (year: u16, stmt: Statement<'a,'a, Prepared, NoResult>) -> Result<Statement<'a, 'a, Prepared, NoResult>>{
    ///    let stmt = stmt.bind_parameter(1, &year)?;
    ///    let stmt = if let Data(mut stmt) = stmt.execute()?{
    ///        if let Some(mut cursor) = stmt.fetch()?{
    ///            println!("{}", cursor.get_data::<String>(1)?.unwrap());
    ///        }
    ///        stmt.close_cursor()?
    ///    } else {
    ///       panic!("SELECT statement returned no result set");
    ///    };
    ///    stmt.reset_parameters()
    /// };
    ///
    /// for year in 1990..2010{
    ///     stmt = print_one_movie_from(year, stmt)?
    /// }
    ///
    /// # Ok(())
    /// # }
    /// ```
    pub fn prepare(mut self, sql_text: &str) -> Result<Statement<'a, 'b, Prepared, NoResult>> {
        self.raii.prepare(sql_text).into_result(&mut self)?;
        Ok(Statement::with_raii(self.raii))
    }

    /// Prepares a statement for execution. Executing a prepared statement is faster than directly
    /// executing an unprepared statement, since it is already compiled into an Access Plan. This
    /// makes preparing statement a good idea if you want to repeatedly execute a query with a
    /// different set of parameters and care about performance.
    ///
    /// # Example
    ///
    /// ```rust
    /// # use odbc::*;
    /// # fn doc() -> Result<()>{
    /// let env = create_environment_v3().map_err(|e| e.unwrap())?;
    /// let conn = env.connect("TestDataSource", "", "")?;
    /// let stmt = Statement::with_parent(&conn)?;
    /// // need encode_rs crate
    /// // let mut stmt = stmt.prepare_bytes(&GB2312.encode("select '你好' as hello").0)?;
    ///
    /// # Ok(())
    /// # }
    /// ```
    pub fn prepare_bytes(mut self, bytes: &[u8]) -> Result<Statement<'a, 'b, Prepared, NoResult>> {
        self.raii.prepare_byte(bytes).into_result(&mut self)?;
        Ok(Statement::with_raii(self.raii))
    }
}

impl<'a, 'b> Statement<'a, 'b, Prepared, NoResult> {
    /// The number of columns in a result set
    ///
    /// Can be called successfully only when the statement is in the prepared, executed, or
    /// positioned state. If the statement does not return columns the result will be 0.
    pub fn num_result_cols(&self) -> Result<i16> {
        self.raii.num_result_cols().into_result(self)
    }

    /// Returns description struct for result set column with a given index. Note: indexing is starting from 1.
    pub fn describe_col(&self, idx: u16) -> Result<ColumnDescriptor> {
        self.raii.describe_col(idx).into_result(self)
    }

    /// Executes a prepared statement.
    pub fn execute(mut self) -> Result<ResultSetState<'a, 'b, Prepared>> {
        if self.raii.execute().into_result(&mut self)? {
            let num_cols = self.raii.num_result_cols().into_result(&self)?;
            if num_cols > 0 {
                Ok(ResultSetState::Data(Statement::with_raii(self.raii)))
            } else {
                Ok(ResultSetState::NoData(Statement::with_raii(self.raii)))
            }
        } else {
            Ok(ResultSetState::NoData(Statement::with_raii(self.raii)))
        }
    }
}

impl Raii<ffi::Stmt> {
    fn prepare(&mut self, sql_text: &str) -> Return<()> {
        match unsafe {
            ffi::SQLPrepare(
                self.handle(),
                sql_text.as_bytes().as_ptr(),
                sql_text.as_bytes().len() as ffi::SQLINTEGER,
            )
        } {
            ffi::SQL_SUCCESS => Return::Success(()),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
            ffi::SQL_ERROR => Return::Error,
            r => panic!("SQLPrepare returned unexpected result: {:?}", r),
        }
    }

    fn prepare_byte(&mut self, bytes: &[u8]) -> Return<()> {
        match unsafe {
            ffi::SQLPrepare(
                self.handle(),
                bytes.as_ptr(),
                bytes.len() as ffi::SQLINTEGER,
            )
        } {
            ffi::SQL_SUCCESS => Return::Success(()),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
            ffi::SQL_ERROR => Return::Error,
            r => panic!("SQLPrepare returned unexpected result: {:?}", r),
        }
    }

    fn execute(&mut self) -> Return<bool> {
        match unsafe { ffi::SQLExecute(self.handle()) } {
            ffi::SQL_SUCCESS => Return::Success(true),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(true),
            ffi::SQL_ERROR => Return::Error,
            ffi::SQL_NO_DATA => Return::Success(false),
            r => panic!("SQLExecute returned unexpected result: {:?}", r),
        }
    }
}
<|endoftext|>


<commit_before>use board::std_board::PieceType;
use board::std_board::Square;
use board::std_board::ChessBoard;
use pgn_traits::pgn::PgnBoard;
use board_game_traits::board::Board;
use board::std_move::ChessMove;
use tests::tools;

#[test]
fn from_alg_test() {
    assert_eq!(Square::from_alg("a8").unwrap(), Square(0));
    assert_eq!(Square::from_alg("b8").unwrap(), Square(1));
    assert_eq!(Square::from_alg("g1").unwrap(), Square(62));
}

#[test]
fn to_san_test() {
    let board = ChessBoard::start_board();
    assert_eq!(board.move_to_san(&ChessMove::new(Square::from_alg("e2").unwrap(),
                                                 Square::from_alg("e4").unwrap())), "e4");
    assert_eq!(board.move_to_san(&ChessMove::new(Square::from_alg("g1").unwrap(),
                                                 Square::from_alg("f3").unwrap())), "Nf3");
}

#[test]
fn to_san_capture_promote_check_test() {
    let board = ChessBoard::from_fen("q6k/1P6/8/8/8/8/8/K7 w - - 0 1").unwrap();
    assert_eq!(board.move_to_san(&ChessMove::new_prom(Square::from_alg("b7").unwrap(),
                                                      Square::from_alg("a8").unwrap(),
                                                      PieceType::Queen)),
               "bxa8=Q+");
    assert_eq!(board.move_to_san(&ChessMove::new(Square::from_alg("a1").unwrap(),
                                                 Square::from_alg("a2").unwrap())),
               "Ka2");
}

#[test]
fn to_san_castles_checkkmate_test() {
    let board = ChessBoard::from_fen("rn3r2/pbppq1p1/1p2pN2/8/3P2NP/6P1/PPP1BP1R/R3K1k1 w Q - 5 18").unwrap();
    assert_eq!(board.move_to_san(&ChessMove::new(Square::from_alg("e1").unwrap(),
                                                      Square::from_alg("c1").unwrap())),
               "0-0-0#");
}

#[test]
fn from_san_test() {
    let mut board = ChessBoard::start_board();
    let mut moves = vec![];

    for mv in ["e4", "d5", "Nc3", "Nf6", "Bb5", "Nbd7", "Nge2", "dxe4", "0-0"].iter() {
        board.generate_moves(&mut moves);
        for &mv in moves.iter() {
            assert_eq!(board.move_from_san(&board.move_to_san(&mv)).unwrap(), mv)
        }
        moves.clear();

        let mv = board.move_from_san(mv).unwrap();
        board.do_move(mv);
    };
}

#[test]
fn san_lan_test() {
    for _ in 0..10 {
        tools::test_san_lan_with_random_game(ChessBoard::start_board());
    }
}<commit_msg>Add failing tests for detecting chess repetitions<commit_after>use board::std_board::PieceType;
use board::std_board::Square;
use board::std_board::ChessBoard;
use pgn_traits::pgn::PgnBoard;
use board_game_traits::board::{Board, Color, GameResult};
use board::std_move::ChessMove;
use tests::tools;
use search_algorithms::alpha_beta::{AlphaBeta};
use uci;
use uci_engine::UciEngine;

#[test]
fn repetitions_test1() {
    let mut board = ChessBoard::from_fen("r3k2r/1bp4p/p3p1N1/5pNQ/1p2p3/1P2P3/P1K2qPP/R7 w kq - 0 20").unwrap();
    for mv_str in "Kb1 Qe1+ Kc2 Qf2+ Kb1 Qe1+ Kb2".split_whitespace() {
        let mv = board.move_from_san(mv_str).unwrap();
        board.do_move(mv);
    }

    // Check that the engine does not play a move that allows a repetition
    let engine = AlphaBeta::init();
    let (_, mv) =
        engine.best_move(board.clone(),
                         uci::TimeRestriction::Depth(5),
                         None).unwrap();

    assert_ne!(mv, board.move_from_san("Qf2+").unwrap());

    board.do_move(board.move_from_san("Qf2+").unwrap());

    // Check that it plays the draw by repetition
    let engine = AlphaBeta::init();
    let (score, mv) =
        engine.best_move(board.clone(),
                         uci::TimeRestriction::Depth(5),
                         None).unwrap();

    assert_eq!(score.to_cp(Color::White), 0);
    assert_eq!(mv, board.move_from_san("Kb1").unwrap());

    board.do_move(board.move_from_san("Kb1").unwrap());

    assert_eq!(board.game_result(), Some(GameResult::Draw));
}

#[test]
fn repetitions_test2() {
    let mut board = ChessBoard::from_fen("1r2r3/Q4pkp/5bp1/3P1p2/2P5/1P6/P3NPPP/1R3RK1 b - - 0 24").unwrap();
    for mv_str in " Ra8 Qb7 Rab8 Qc7 Rbc8 Qb7 Rb8 Qc7 Rbc8".split_whitespace() {
        let mv = board.move_from_san(mv_str).unwrap();
        board.do_move(mv);
    }

    // Check that the engine does not play a move that allows a repetition
    let engine = AlphaBeta::init();
    let (_, mv) =
        engine.best_move(board.clone(),
                         uci::TimeRestriction::Depth(5),
                         None).unwrap();

    assert_ne!(mv, board.move_from_san("Qb7").unwrap());

    board.do_move(board.move_from_san("Qb7").unwrap());

    // Check that it plays the draw by repetition
    let engine = AlphaBeta::init();
    let (score, mv) =
        engine.best_move(board.clone(),
                         uci::TimeRestriction::Depth(5),
                         None).unwrap();

    assert_eq!(score.to_cp(Color::Black), 0);
    assert_eq!(mv, board.move_from_san("Rb8").unwrap());

    board.do_move(board.move_from_san("Rb8").unwrap());

    assert_eq!(board.game_result(), Some(GameResult::Draw));
}

#[test]
fn from_alg_test() {
    assert_eq!(Square::from_alg("a8").unwrap(), Square(0));
    assert_eq!(Square::from_alg("b8").unwrap(), Square(1));
    assert_eq!(Square::from_alg("g1").unwrap(), Square(62));
}

#[test]
fn to_san_test() {
    let board = ChessBoard::start_board();
    assert_eq!(board.move_to_san(&ChessMove::new(Square::from_alg("e2").unwrap(),
                                                 Square::from_alg("e4").unwrap())), "e4");
    assert_eq!(board.move_to_san(&ChessMove::new(Square::from_alg("g1").unwrap(),
                                                 Square::from_alg("f3").unwrap())), "Nf3");
}

#[test]
fn to_san_capture_promote_check_test() {
    let board = ChessBoard::from_fen("q6k/1P6/8/8/8/8/8/K7 w - - 0 1").unwrap();
    assert_eq!(board.move_to_san(&ChessMove::new_prom(Square::from_alg("b7").unwrap(),
                                                      Square::from_alg("a8").unwrap(),
                                                      PieceType::Queen)),
               "bxa8=Q+");
    assert_eq!(board.move_to_san(&ChessMove::new(Square::from_alg("a1").unwrap(),
                                                 Square::from_alg("a2").unwrap())),
               "Ka2");
}

#[test]
fn to_san_castles_checkkmate_test() {
    let board = ChessBoard::from_fen("rn3r2/pbppq1p1/1p2pN2/8/3P2NP/6P1/PPP1BP1R/R3K1k1 w Q - 5 18").unwrap();
    assert_eq!(board.move_to_san(&ChessMove::new(Square::from_alg("e1").unwrap(),
                                                      Square::from_alg("c1").unwrap())),
               "0-0-0#");
}

#[test]
fn from_san_test() {
    let mut board = ChessBoard::start_board();
    let mut moves = vec![];

    for mv in ["e4", "d5", "Nc3", "Nf6", "Bb5", "Nbd7", "Nge2", "dxe4", "0-0"].iter() {
        board.generate_moves(&mut moves);
        for &mv in moves.iter() {
            assert_eq!(board.move_from_san(&board.move_to_san(&mv)).unwrap(), mv)
        }
        moves.clear();

        let mv = board.move_from_san(mv).unwrap();
        board.do_move(mv);
    };
}

#[test]
fn san_lan_test() {
    for _ in 0..10 {
        tools::test_san_lan_with_random_game(ChessBoard::start_board());
    }
}<|endoftext|>


<commit_before>//! Descriptions of intervals of partially ordered times.

/// Describes an interval of partially ordered times.
///
/// A `Description` indicates a set of partially ordered times, and a moment at which they are
/// observed. The `lower` and `upper` frontiers bound the times contained within, and the `since`
/// frontier indicates a moment at which the times were observed. If `since` is strictly in
/// advance of `lower`, the contained times may be "advanced" to times which appear equivalent to
/// any time after `since`.
#[derive(Clone, Debug)]
pub struct Description<Time> {
	/// lower frontier of contained updates.
	lower: Vec<Time>,
	/// upper frontier of contained updates.
	upper: Vec<Time>,
	/// frontier used for update compaction.
	since: Vec<Time>,
}

impl<Time: Clone> Description<Time> {
	/// Returns a new description from its component parts.
	pub fn new(lower: &[Time], upper: &[Time], since: &[Time]) -> Self {
		assert!(lower.len() > 0);	// this should always be true.
		// assert!(upper.len() > 0);	// this may not always be true.
		Description {
			lower: lower.to_vec(),
			upper: upper.to_vec(),
			since: since.to_vec(),
		}
	}
}

impl<Time> Description<Time> {
	/// The lower envelope for times in the interval.
	pub fn lower(&self) -> &[Time] { &self.lower[..] }
	/// The upper envelope for times in the interval.
	pub fn upper(&self) -> &[Time] { &self.upper[..] }
	/// Times from whose future the interval may be observed.
	pub fn since(&self) -> &[Time] { &self.since[..] }
}<commit_msg>said lots about descriptions<commit_after>//! Descriptions of intervals of partially ordered times.
//!
//! A description provides what intends to be an unambiguous characterization of a batch of
//! updates. We do assume that these updates are in the context of a known computation and
//! known input, so there is a well-defined "correct answer" for the full set of updates.
//!
//!      full = { (data, time, diff) }
//!
//! Our aim with a description is to specify a subset of these updates unambiguously.
//!
//! Each description contains three frontiers, sets of mutually incomparable partially ordered
//! times. The first two frontiers are `lower` and `upper`, and they indicate the subset of
//! `full` represented in the batch: those updates whose times are greater or equal to some
//! element of `lower` but not greater or equal to any element of `upper`.
//!
//!     subset = { (data, time, diff) in full | lower.any(|t| t.le(time)) &&
//! 										   !upper.any(|t| t.le(time)) }
//!
//! The third frontier `since` is used to indicate that the times presented by the batch may
//! no longer reflect the values in `subset` above. Although the updates are precisely those
//! bound by `lower` and `upper`, we may have *advanced* some of the times.
//!
//! The guarantee provided by a batch is that for any time greater or equal to some element of
//! `since`, the accumulated weight of batch updates before that time is identical to the accumulated
//! weights of updates from `full` at times greater or equal to an element of `lower`, greater
//! or equal to no element of `upper`, and less or equal to the query time.
//!
//!     for all times t1:
//!
//!        if since.any(|t2| t2.less_equal(t1)) then:
//!
//!            for all data:
//!
//!                sum x where (data, t2, x) in batch and t2.less_equal(t1)
//!            ==
//!                sum x where (data, t2, x) in full and  t2.less_equal(t1)
//!                                                  and  lower.any(|t3| t3.less_equal(t2))
//!                                                  and !upper.any(|t3| t3.less_equal(t2))
//!
//! Very importantly, this equality does not make any other guarantees about the contents of
//! the batch when one iterates through it. There are some consequences of the math that can
//! be relied upon, though.
//!
//! The most important consequence is that when `since <= lower` the contents of the batch
//! must be equivalent to range of updates in `full`. If it is ever the case that `since` is
//! in advance of `lower`, consumers of the batch must take care that they not use the times
//! observed in the batch without ensuring that they are appropriately advanced (typically by
//! `since`). Failing to do so may produce updates that are not in advance of `since`, which
//! will often be a logic bug, as `since` does not advance without a corresponding advance in
//! times at which data may possibly be sent.

/// Describes an interval of partially ordered times.
///
/// A `Description` indicates a set of partially ordered times, and a moment at which they are
/// observed. The `lower` and `upper` frontiers bound the times contained within, and the `since`
/// frontier indicates a moment at which the times were observed. If `since` is strictly in
/// advance of `lower`, the contained times may be "advanced" to times which appear equivalent to
/// any time after `since`.
#[derive(Clone, Debug)]
pub struct Description<Time> {
	/// lower frontier of contained updates.
	lower: Vec<Time>,
	/// upper frontier of contained updates.
	upper: Vec<Time>,
	/// frontier used for update compaction.
	since: Vec<Time>,
}

impl<Time: Clone> Description<Time> {
	/// Returns a new description from its component parts.
	pub fn new(lower: &[Time], upper: &[Time], since: &[Time]) -> Self {
		assert!(lower.len() > 0);	// this should always be true.
		// assert!(upper.len() > 0);	// this may not always be true.
		Description {
			lower: lower.to_vec(),
			upper: upper.to_vec(),
			since: since.to_vec(),
		}
	}
}

impl<Time> Description<Time> {
	/// The lower envelope for times in the interval.
	pub fn lower(&self) -> &[Time] { &self.lower[..] }
	/// The upper envelope for times in the interval.
	pub fn upper(&self) -> &[Time] { &self.upper[..] }
	/// Times from whose future the interval may be observed.
	pub fn since(&self) -> &[Time] { &self.since[..] }
}<|endoftext|>


<commit_before>#[macro_use]
pub mod engine_macro;
pub mod router;
pub mod serializer;

pub use self::router::{Router, Endpoint, extract_endpoints};
pub use self::serializer::{Serializer};

use std::cell::{RefCell};
use std::collections::{HashMap};
use std::net::{SocketAddr};
use std::rc::{Rc};

use super::error::{Result};

use futures::sync::{mpsc};
use json::{JsonValue};
use tungstenite::{Message};
use uuid::{Uuid};

type ActiveConnections = Rc<RefCell<HashMap<SocketAddr, mpsc::UnboundedSender<Message>>>>;

pub struct Engine {
    router: Box<Router>
}

impl Engine {
    pub fn new(router: Box<Router>) -> Engine {
        Engine {
            router: router
        }
    }

    pub fn handle(&self, message: &Message, client: &SocketAddr, connections: &ActiveConnections) {
        let transmitter = &connections.borrow_mut()[&client];

        let request = match self.prepare_request(message) {
            Ok(json_object) => json_object,
            Err(err) => {
                let formatted_error = format!("{}", err);
                let error_message = self.wrap_an_error(formatted_error.as_str());
                transmitter.unbounded_send(error_message).unwrap();
                return
            }
        };

        println!("{}", request);
        let response = self.prepare_response(request);
        transmitter.unbounded_send(response).unwrap();
    }

    pub fn wrap_an_error(&self, err: &str) -> Message {
        let json_error_message = object!("details" => err);
        let serializer = Serializer::new();
        serializer.serialize(json_error_message.dump()).unwrap()
    }

    pub fn serialize_message(&self, json: Box<JsonValue>) -> Message {
        let serializer = Serializer::new();
        serializer.serialize(json.dump()).unwrap()
    }

    pub fn deserialize_message(&self, message: &Message) -> Result<Box<JsonValue>> {
        let serializer = Serializer::new();
        serializer.deserialize(message)
    }

    fn prepare_request(&self, message: &Message) -> Result<Box<JsonValue>> {
        let json = self.deserialize_message(message)?;
        let mut request = Box::new(object!{
            "headers" => object!{},
            "content" => object!{}
        });

        self.generate_request_headers(&mut request, json);
        Ok(request)
    }

    fn prepare_response(&self, json: Box<JsonValue>) -> Message {
        self.serialize_message(json)
    }

    fn generate_request_headers(&self, request: &mut Box<JsonValue>, from_json: Box<JsonValue>) {
        request["headers"]["request-id"] = format!("{}", Uuid::new_v4()).into();

        let url = from_json["url"].as_str().unwrap();
        match self.router.match_url(url) {
            Ok(endpoint) => {
                request["headers"]["microservice-name"] = endpoint.get_microservice().into();
                request["headers"]["request-url"] = endpoint.get_url().into();
            },
            Err(_) => {
                request["headers"]["microservice-name"] = self.convert_url_into_microservice(url).into();
                request["headers"]["request-url"] = url.into();
            }
        }
    }

    fn convert_url_into_microservice(&self, url: &str) -> String {
        let mut external_url = url.clone();
        external_url = external_url.trim_left_matches("/");
        external_url = external_url.trim_right_matches("/");
        external_url.replace("/", ".")
    }
}
<commit_msg>Added documentation for engine/mod.rs<commit_after>//! Proxy engine
//!
//! This module is intended for processing incoming requests from clients,
//! handling occurred errors during a work, communicating with a message
//! broker and preparing appropriate responses in the certain format.
//!

#[macro_use]
pub mod engine_macro;
pub mod router;
pub mod serializer;

pub use self::router::{Router, Endpoint, extract_endpoints};
pub use self::serializer::{Serializer};

use std::cell::{RefCell};
use std::collections::{HashMap};
use std::net::{SocketAddr};
use std::rc::{Rc};

use super::error::{Result};

use futures::sync::{mpsc};
use json::{JsonValue};
use tungstenite::{Message};
use uuid::{Uuid};

/// Type alias for dictionary with `SocketAddr` as a key and `UnboundedSender<Message>` as a value.
pub type ActiveConnections = Rc<RefCell<HashMap<SocketAddr, mpsc::UnboundedSender<Message>>>>;

/// Proxy engine for processing messages, handling errors and communicating with a message broker.
pub struct Engine {
    router: Box<Router>
}

impl Engine {
    /// Returns a new instance of `Engine`.
    pub fn new(router: Box<Router>) -> Engine {
        Engine {
            router: router
        }
    }

    /// Main handler for generating response per each incoming request.
    pub fn handle(&self, message: &Message, client: &SocketAddr, connections: &ActiveConnections) {
        let transmitter = &connections.borrow_mut()[&client];

        let request = match self.prepare_request(message) {
            Ok(json_object) => json_object,
            Err(err) => {
                let formatted_error = format!("{}", err);
                let error_message = self.wrap_an_error(formatted_error.as_str());
                transmitter.unbounded_send(error_message).unwrap();
                return
            }
        };

        println!("{}", request);
        let response = self.prepare_response(request);
        transmitter.unbounded_send(response).unwrap();
    }

    /// Transforms an error (which is a string) into JSON object in the special format.
    pub fn wrap_an_error(&self, err: &str) -> Message {
        let json_error_message = object!("details" => err);
        let serializer = Serializer::new();
        serializer.serialize(json_error_message.dump()).unwrap()
    }

    /// Serialize a JSON object into message.
    pub fn serialize_message(&self, json: Box<JsonValue>) -> Message {
        let serializer = Serializer::new();
        serializer.serialize(json.dump()).unwrap()
    }

    /// Deserialize a message into JSON object.
    pub fn deserialize_message(&self, message: &Message) -> Result<Box<JsonValue>> {
        let serializer = Serializer::new();
        serializer.deserialize(message)
    }

    /// Converts a `tungstenite::Message` message into the JSON object.
    fn prepare_request(&self, message: &Message) -> Result<Box<JsonValue>> {
        let json = self.deserialize_message(message)?;
        let mut request = Box::new(object!{
            "headers" => object!{},
            "content" => object!{}
        });

        self.generate_request_headers(&mut request, json);
        Ok(request)
    }

    /// Converts a JSON object into the `tungstenite::Message` message.
    fn prepare_response(&self, json: Box<JsonValue>) -> Message {
        self.serialize_message(json)
    }

    /// Transforms a request to the appropriate format for a further processing by a microservice.
    fn generate_request_headers(&self, request: &mut Box<JsonValue>, from_json: Box<JsonValue>) {
        request["headers"]["request-id"] = format!("{}", Uuid::new_v4()).into();

        let url = from_json["url"].as_str().unwrap();
        match self.router.match_url(url) {
            Ok(endpoint) => {
                request["headers"]["microservice-name"] = endpoint.get_microservice().into();
                request["headers"]["request-url"] = endpoint.get_url().into();
            },
            Err(_) => {
                request["headers"]["microservice-name"] = self.convert_url_into_microservice(url).into();
                request["headers"]["request-url"] = url.into();
            }
        }
    }

    /// Converts a URL to the certain microservice name, so that it will be used as a queue/topic name futher.
    fn convert_url_into_microservice(&self, url: &str) -> String {
        let mut external_url = url.clone();
        external_url = external_url.trim_left_matches("/");
        external_url = external_url.trim_right_matches("/");
        external_url.replace("/", ".")
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::str;
use std::fmt::{Result};

static NO_NAME : &'static str = "<none>";

// NOTE: Uncomment when https://github.com/mozilla/rust/issues/13703 is fixed.
// pub struct PreOrderNodes<'a, 'b> {
//   queue: Vec<&'a Node<'b>>
// }
//
// impl<'a, 'b> Iterator<&'a Node<'b>> for PreOrderNodes<'a, 'b> {
//   fn next( &mut self ) -> Option<&'a Node<'b>> {
//     match self.queue.pop() {
//       ex @ Some( node ) => {
//         match node.contents {
//           Children( ref x ) => {
//             for child in x.as_slice().iter().rev() {
//               self.queue.push( child )
//             }
//           }
//           _ => ()
//         };
//         ex
//       }
//       _ => None
//     }
//   }
// }

#[deriving(Show, PartialEq)]
pub enum NodeContents<'a> {
  /// A `&[u8]` byte slice this node matched in the parse input. Only leaf nodes
  /// have `Data` contents.
  Data( &'a [u8] ),

  /// Children of the node, if any. Only non-leaf nodes have `Children`
  /// contents.
  Children( Vec<Node<'a>> )
}

#[deriving(PartialEq)]
pub struct Node<'a> {
  /// The name of the node.
  pub name: &'static str,

  /// The (inclusive) start index of the range this node matches. It's the byte
  /// (NOT char) offset of the parse input.
  pub start: uint,

  /// The (exclusive) end index of the range this node matches. It's the byte
  /// (NOT char) offset of the parse input.
  pub end: uint,

  /// The contents of the node; this can be either children nodes or a matched
  /// `&[u8]` slice.
  pub contents: NodeContents<'a>
}

fn indent( formatter: &mut fmt::Formatter, indent_spaces: int )
    -> fmt::Result {
  for _ in range( 0, indent_spaces ) {
    try!( write!( formatter, " " ) )
  }
  Ok(())
}

impl<'a> Node<'a> {
  fn format( &self, formatter: &mut fmt::Formatter, indent_spaces: int )
      -> fmt::Result {
    try!( indent( formatter, indent_spaces ) );
    try!( write!( formatter,
                  "Node {{name: {0}, start: {1}, end: {2}",
                  self.displayName(), self.start, self.end ) );

    match self.contents {
      Data( data ) => {
        match str::from_utf8( data ) {
          Some( string ) => {
            try!( writeln!( formatter,
                            ", contents: \"{0}\" }}",
                            string ) );
          }
          _ => {
            try!( writeln!( formatter,
                            ", contents: \"{0}\" }}",
                            data ) );
          }
        }
      }
      Children( ref children ) => {
        try!( writeln!( formatter, " }}" ) );
        for child in children.iter() {
          try!( child.format( formatter, indent_spaces + 1) )
        }
      }
    };

    Ok(())
  }

  /// The node name if set, or "<none>" if unset.
  pub fn displayName( &self ) -> &'static str {
    if !self.name.is_empty() {
      self.name
    } else {
      NO_NAME
    }
  }

  /// Creates a `Node` with an empty name.
  pub fn withoutName( start: uint, end: uint, contents: NodeContents<'a> )
      -> Node<'a> {
    Node { name: "", start: start, end: end, contents: contents }
  }

  /// Creates a `Node` with the provided `name` and makes it a parent of the
  /// provided `children`.
  pub fn withChildren( name: &'static str, mut children: Vec<Node<'a>> )
      -> Node<'a> {
    // In case 'children' has only one node with an empty name, our new Node
    // will take the guts of the child with the new 'name'.
    if children.len() == 1 && children.get( 0 ).name.is_empty() {
      match children.pop() {
        Some( mut child ) => {
          child.name = name;
          return child;
        }
        _ => ()
      }
    }

    let start = if children.len() != 0 {
      children.get( 0 ).start
    } else {
      0
    };

    let end = match children.last() {
      Some( ref node ) => node.end,
      _ => 0
    };

    Node { name: name,
           start: start,
           end: end,
           contents: Children( children ) }
  }

  /// Traverses the tree rooted at the node with pre-order traversal. `visitor`
  /// is called on every node and traversal stops when `visitor` returns `false`.
  ///
  /// Normally this function would return an iterator instead of taking a
  /// visitor function, but a `rustc` bug is preventing that implementation.
  #[allow(dead_code)]
  pub fn preOrder( &self, visitor: |&Node| -> bool ) {
    fn inner( node: &Node, visitor: |&Node| -> bool ) -> bool {
      if !visitor( node ) {
        return false;
      }

      match node.contents {
        Children( ref x ) => {
          for node in x.iter() {
            if !inner( node, |x| visitor( x ) ) {
              return false;
            }
          }
        }
        _ => ()
      };

      true
    }
    inner( self, visitor );
  }

  // NOTE: Uncomment when https://github.com/mozilla/rust/issues/13703 is fixed.
  // pub fn preOrder<'b>( &'b self ) -> PreOrderNodes<'b, 'a> {
  //   PreOrderNodes { queue: vec!( self ) }
  // }

  #[allow(dead_code)]
  fn matchedData( &self ) -> Vec<u8> {
    match self.contents {
      Data( x ) => Vec::from_slice( x ),
      Children( _ ) => {
        // TODO: implement
        vec!()
      }
    }
  }

  // TODO: methods in_order/pre_order/post_order that yield
  // iterators for walking the node tree structure
}

impl<'a> fmt::Show for Node<'a> {
  fn fmt( &self, formatter: &mut fmt::Formatter ) -> fmt::Result {
    self.format( formatter, 0 )
  }
}

#[cfg(test)]
mod tests {
  use super::{Node, Data};

  fn nameOnly( name: &'static str ) -> Node {
    Node { name: name, start: 0, end: 0, contents: Data( b"" ) }
  }

  fn testTree() -> Node {
    // Tree looks like the following:
    //        a
    //   b    c    d
    //  e f   g
    Node::withChildren( "a", vec!(
        Node::withChildren( "b", vec!( nameOnly( "e" ), nameOnly( "f" ) ) ),
        Node::withChildren( "c", vec!( nameOnly( "g" ) ) ),
        nameOnly( "d" ) ) )
  }

  #[test]
  fn preOrder_FullIteration() {
    let root = testTree();
    let mut names : Vec<char> = vec!();
    root.preOrder( |ref x| {
      names.push( x.name.char_at( 0 ) );
      true
    });

    assert_eq!( names, vec!( 'a', 'b', 'e', 'f', 'c', 'g', 'd' ) )
  }

  #[test]
  fn preOrder_PartialIteration() {
    let root = testTree();
    let mut names : Vec<char> = vec!();
    root.preOrder( |ref x| {
      let ch =  x.name.char_at( 0 );
      names.push( ch );
      if ch == 'f' { false } else { true }
    });

    assert_eq!( names, vec!( 'a', 'b', 'e', 'f' ) )
  }
}
<commit_msg>Implemented matchedData for Node<commit_after>use std::fmt;
use std::str;
use std::fmt::{Result};

static NO_NAME : &'static str = "<none>";

// NOTE: Uncomment when https://github.com/mozilla/rust/issues/13703 is fixed.
// pub struct PreOrderNodes<'a, 'b> {
//   queue: Vec<&'a Node<'b>>
// }
//
// impl<'a, 'b> Iterator<&'a Node<'b>> for PreOrderNodes<'a, 'b> {
//   fn next( &mut self ) -> Option<&'a Node<'b>> {
//     match self.queue.pop() {
//       ex @ Some( node ) => {
//         match node.contents {
//           Children( ref x ) => {
//             for child in x.as_slice().iter().rev() {
//               self.queue.push( child )
//             }
//           }
//           _ => ()
//         };
//         ex
//       }
//       _ => None
//     }
//   }
// }

#[deriving(Show, PartialEq)]
pub enum NodeContents<'a> {
  /// A `&[u8]` byte slice this node matched in the parse input. Only leaf nodes
  /// have `Data` contents.
  Data( &'a [u8] ),

  /// Children of the node, if any. Only non-leaf nodes have `Children`
  /// contents.
  Children( Vec<Node<'a>> )
}

#[deriving(PartialEq)]
pub struct Node<'a> {
  /// The name of the node.
  pub name: &'static str,

  /// The (inclusive) start index of the range this node matches. It's the byte
  /// (NOT char) offset of the parse input.
  pub start: uint,

  /// The (exclusive) end index of the range this node matches. It's the byte
  /// (NOT char) offset of the parse input.
  pub end: uint,

  /// The contents of the node; this can be either children nodes or a matched
  /// `&[u8]` slice.
  pub contents: NodeContents<'a>
}

fn indent( formatter: &mut fmt::Formatter, indent_spaces: int )
    -> fmt::Result {
  for _ in range( 0, indent_spaces ) {
    try!( write!( formatter, " " ) )
  }
  Ok(())
}

impl<'a> Node<'a> {
  fn format( &self, formatter: &mut fmt::Formatter, indent_spaces: int )
      -> fmt::Result {
    try!( indent( formatter, indent_spaces ) );
    try!( write!( formatter,
                  "Node {{name: {0}, start: {1}, end: {2}",
                  self.displayName(), self.start, self.end ) );

    match self.contents {
      Data( data ) => {
        match str::from_utf8( data ) {
          Some( string ) => {
            try!( writeln!( formatter,
                            ", contents: \"{0}\" }}",
                            string ) );
          }
          _ => {
            try!( writeln!( formatter,
                            ", contents: \"{0}\" }}",
                            data ) );
          }
        }
      }
      Children( ref children ) => {
        try!( writeln!( formatter, " }}" ) );
        for child in children.iter() {
          try!( child.format( formatter, indent_spaces + 1) )
        }
      }
    };

    Ok(())
  }

  /// The node name if set, or "<none>" if unset.
  pub fn displayName( &self ) -> &'static str {
    if !self.name.is_empty() {
      self.name
    } else {
      NO_NAME
    }
  }

  /// Creates a `Node` with an empty name.
  pub fn withoutName( start: uint, end: uint, contents: NodeContents<'a> )
      -> Node<'a> {
    Node { name: "", start: start, end: end, contents: contents }
  }

  /// Creates a `Node` with the provided `name` and makes it a parent of the
  /// provided `children`.
  pub fn withChildren( name: &'static str, mut children: Vec<Node<'a>> )
      -> Node<'a> {
    // In case 'children' has only one node with an empty name, our new Node
    // will take the guts of the child with the new 'name'.
    if children.len() == 1 && children.get( 0 ).name.is_empty() {
      match children.pop() {
        Some( mut child ) => {
          child.name = name;
          return child;
        }
        _ => ()
      }
    }

    let start = if children.len() != 0 {
      children.get( 0 ).start
    } else {
      0
    };

    let end = match children.last() {
      Some( ref node ) => node.end,
      _ => 0
    };

    Node { name: name,
           start: start,
           end: end,
           contents: Children( children ) }
  }

  /// Traverses the tree rooted at the node with pre-order traversal. `visitor`
  /// is called on every node and traversal stops when `visitor` returns `false`.
  ///
  /// Normally this function would return an iterator instead of taking a
  /// visitor function, but a `rustc` bug is preventing that implementation.
  #[allow(dead_code)]
  pub fn preOrder( &self, visitor: |&Node| -> bool ) {
    fn inner( node: &Node, visitor: |&Node| -> bool ) -> bool {
      if !visitor( node ) {
        return false;
      }

      match node.contents {
        Children( ref x ) => {
          for node in x.iter() {
            if !inner( node, |x| visitor( x ) ) {
              return false;
            }
          }
        }
        _ => ()
      };

      true
    }
    inner( self, visitor );
  }

  // NOTE: Uncomment when https://github.com/mozilla/rust/issues/13703 is fixed.
  // pub fn preOrder<'b>( &'b self ) -> PreOrderNodes<'b, 'a> {
  //   PreOrderNodes { queue: vec!( self ) }
  // }

  /// Concatenates and returns all `&[u8]` data in the leaf nodes beneath
  /// the current node.
  #[allow(dead_code)]
  fn matchedData( &self ) -> Vec<u8> {
    match self.contents {
      Data( x ) => Vec::from_slice( x ),
      Children( ref children ) => {
        let mut out : Vec<u8> = vec!();
        for child in children.iter() {
          out.push_all( child.matchedData().as_slice() );
        }
        out
      }
    }
  }

  // TODO: methods in_order/pre_order/post_order that yield
  // iterators for walking the node tree structure
}

impl<'a> fmt::Show for Node<'a> {
  fn fmt( &self, formatter: &mut fmt::Formatter ) -> fmt::Result {
    self.format( formatter, 0 )
  }
}

#[cfg(test)]
mod tests {
  use super::{Node, Data};

  fn nameOnly( name: &'static str ) -> Node {
    Node { name: name, start: 0, end: 0, contents: Data( b"" ) }
  }

  fn contentsOnly( contents: &'static [u8] ) -> Node {
    Node { name: "", start: 0, end: 0, contents: Data( contents ) }
  }

  fn testTree() -> Node {
    // Tree looks like the following:
    //        a
    //   b    c    d
    //  e f   g
    Node::withChildren( "a", vec!(
        Node::withChildren( "b", vec!( nameOnly( "e" ), nameOnly( "f" ) ) ),
        Node::withChildren( "c", vec!( nameOnly( "g" ) ) ),
        nameOnly( "d" ) ) )
  }

  fn testTreeWithContents() -> Node {
    // Tree looks like the following (nodes with ' have contents):
    //          a
    //    b     c     'd
    // 'e  'f  'g
    Node::withChildren( "a", vec!(
        Node::withChildren(
          "b", vec!( contentsOnly( b"e" ), contentsOnly( b"f" ) ) ),
        Node::withChildren( "c", vec!( contentsOnly( b"g" ) ) ),
        contentsOnly( b"d" ) ) )
  }

  #[test]
  fn preOrder_FullIteration() {
    let root = testTree();
    let mut names : Vec<char> = vec!();
    root.preOrder( |ref x| {
      names.push( x.name.char_at( 0 ) );
      true
    });

    assert_eq!( names, vec!( 'a', 'b', 'e', 'f', 'c', 'g', 'd' ) )
  }

  #[test]
  fn preOrder_PartialIteration() {
    let root = testTree();
    let mut names : Vec<char> = vec!();
    root.preOrder( |ref x| {
      let ch =  x.name.char_at( 0 );
      names.push( ch );
      if ch == 'f' { false } else { true }
    });

    assert_eq!( names, vec!( 'a', 'b', 'e', 'f' ) )
  }

  #[test]
  fn matchedData_FullTree() {
    let root = testTreeWithContents();
    assert_eq!( b"efgd", root.matchedData().as_slice() )
  }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use generate_format::Corpus;
use serde_reflection::Registry;

#[test]
fn test_that_recorded_formats_did_not_change() {
    for corpus in Corpus::values() {
        let registry = corpus.get_registry();

        // Some corpus may not be recorded on disk.
        if let Some(path) = corpus.output_file() {
            let content = std::fs::read_to_string(path).unwrap();
            let expected = serde_yaml::from_str::<Registry>(content.as_str()).unwrap();
            assert_registry_has_not_changed(&corpus.to_string(), path, registry, expected);
        }
    }
}

fn message(name: &str) -> String {
    format!(
        r#"
You may run `cargo run -p generate-format -- --corpus {} --record` to refresh the records.
Please verify the changes to the recorded file(s) and consider tagging your pull-request as `breaking`."#,
        name
    )
}

fn assert_registry_has_not_changed(name: &str, path: &str, registry: Registry, expected: Registry) {
    for (key, value) in expected.iter() {
        assert_eq!(
            Some(value),
            registry.get(key),
            r#"
----
The recorded format for type `{}` was removed or does not match the recorded value in {}.{}
----
"#,
            key,
            path,
            message(name),
        );
    }

    for key in registry.keys() {
        assert!(
            expected.contains_key(key),
            r#"
----
Type `{}` was added and has no recorded format in {} yet.{}
----
"#,
            key,
            path,
            message(name),
        );
    }
}

#[test]
fn test_we_can_detect_changes_in_yaml() {
    let yaml1 = r#"---
Person:
  ENUM:
    0:
      NickName:
        NEWTYPE:
          STR
"#;

    let yaml2 = r#"---
Person:
  ENUM:
    0:
      NickName:
        NEWTYPE:
          STR
    1:
      FullName: UNIT
"#;

    let value1 = serde_yaml::from_str::<Registry>(yaml1).unwrap();
    let value2 = serde_yaml::from_str::<Registry>(yaml2).unwrap();
    assert_ne!(value1, value2);
    assert_ne!(value1.get("Person").unwrap(), value2.get("Person").unwrap());
}
<commit_msg>[generate-format] Verify consistency between corpuses<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use generate_format::Corpus;
use serde_reflection::Registry;
use std::collections::{btree_map::Entry, BTreeMap};

#[test]
fn analyze_serde_formats() {
    let mut all_corpuses = BTreeMap::new();

    for corpus in Corpus::values() {
        // Compute the Serde formats of this corpus by analyzing the codebase.
        let registry = corpus.get_registry();

        // If the corpus was recorded on disk, test that the formats have not changed since then.
        if let Some(path) = corpus.output_file() {
            let content = std::fs::read_to_string(path).unwrap();
            let expected = serde_yaml::from_str::<Registry>(content.as_str()).unwrap();
            assert_registry_has_not_changed(&corpus.to_string(), path, registry.clone(), expected);
        }

        // Test that the definitions in all corpus are unique.
        for (key, value) in registry {
            match all_corpuses.entry(key.clone()) {
                Entry::Vacant(e) => {
                    e.insert(value);
                }
                Entry::Occupied(e) => assert_eq!(
                    e.get(),
                    &value,
                    "Type {} in corpus {} differs with previous definition in another corpus: {:?} vs {:?}",
                    key,
                    corpus.to_string(),
                    e.get(),
                    &value,
                ),
            }
        }
    }
}

fn message(name: &str) -> String {
    format!(
        r#"
You may run `cargo run -p generate-format -- --corpus {} --record` to refresh the records.
Please verify the changes to the recorded file(s) and consider tagging your pull-request as `breaking`."#,
        name
    )
}

fn assert_registry_has_not_changed(name: &str, path: &str, registry: Registry, expected: Registry) {
    for (key, value) in expected.iter() {
        assert_eq!(
            Some(value),
            registry.get(key),
            r#"
----
The recorded format for type `{}` was removed or does not match the recorded value in {}.{}
----
"#,
            key,
            path,
            message(name),
        );
    }

    for key in registry.keys() {
        assert!(
            expected.contains_key(key),
            r#"
----
Type `{}` was added and has no recorded format in {} yet.{}
----
"#,
            key,
            path,
            message(name),
        );
    }
}

#[test]
fn test_we_can_detect_changes_in_yaml() {
    let yaml1 = r#"---
Person:
  ENUM:
    0:
      NickName:
        NEWTYPE:
          STR
"#;

    let yaml2 = r#"---
Person:
  ENUM:
    0:
      NickName:
        NEWTYPE:
          STR
    1:
      FullName: UNIT
"#;

    let value1 = serde_yaml::from_str::<Registry>(yaml1).unwrap();
    let value2 = serde_yaml::from_str::<Registry>(yaml2).unwrap();
    assert_ne!(value1, value2);
    assert_ne!(value1.get("Person").unwrap(), value2.get("Person").unwrap());
}
<|endoftext|>


<commit_before>
//! Common types for the Cretonne code generator.

use std::fmt::{self, Display, Formatter, Write};

/// The type of an SSA value.
///
/// The `VOID` type is only used for instructions that produce no value. It can't be part of a SIMD
/// vector.
///
/// Basic integer types: `I8`, `I16`, `I32`, and `I64`. These types are sign-agnostic.
///
/// Basic floating point types: `F32` and `F64`. IEEE single and double precision.
///
/// Boolean types: `B1`, `B8`, `B16`, `B32`, and `B64`. These all encode 'true' or 'false'. The
/// larger types use redundant bits.
///
/// SIMD vector types have power-of-two lanes, up to 256. Lanes can be any int/float/bool type.
///
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Type(u8);

/// No type. Used for functions without a return value. Can't be loaded or stored. Can't be part of
/// a SIMD vector.
pub const VOID: Type = Type(0);

/// Integer type with 8 bits.
pub const I8: Type = Type(1);

/// Integer type with 16 bits.
pub const I16: Type = Type(2);

/// Integer type with 32 bits.
pub const I32: Type = Type(3);

/// Integer type with 64 bits.
pub const I64: Type = Type(4);

/// IEEE single precision floating point type.
pub const F32: Type = Type(5);

/// IEEE double precision floating point type.
pub const F64: Type = Type(6);

/// Boolean type. Can't be loaded or stored, but can be used to form SIMD vectors.
pub const B1: Type = Type(7);

/// Boolean type using 8 bits to represent true/false.
pub const B8: Type = Type(8);

/// Boolean type using 16 bits to represent true/false.
pub const B16: Type = Type(9);

/// Boolean type using 32 bits to represent true/false.
pub const B32: Type = Type(10);

/// Boolean type using 64 bits to represent true/false.
pub const B64: Type = Type(11);

impl Type {
    /// Get the lane type of this SIMD vector type.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it returns itself.
    pub fn lane_type(self) -> Type {
        Type(self.0 & 0x0f)
    }

    /// Get the number of bits in a lane.
    pub fn lane_bits(self) -> u8 {
        match self.lane_type() {
            B1 => 1,
            B8 | I8 => 8,
            B16 | I16 => 16,
            B32 | I32 | F32 => 32,
            B64 | I64 | F64 => 64,
            _ => 0,
        }
    }

    /// Is this the VOID type?
    pub fn is_void(self) -> bool {
        self == VOID
    }

    /// Is this a scalar boolean type?
    pub fn is_bool(self) -> bool {
        match self {
            B1 | B8 | B16 | B32 | B64 => true,
            _ => false,
        }
    }

    /// Is this a scalar integer type?
    pub fn is_int(self) -> bool {
        match self {
            I8 | I16 | I32 | I64 => true,
            _ => false,
        }
    }

    /// Is this a scalar floating point type?
    pub fn is_float(self) -> bool {
        match self {
            F32 | F64 => true,
            _ => false,
        }
    }

    /// Get log2 of the number of lanes in this SIMD vector type.
    ///
    /// All SIMD types have a lane count that is a power of two and no larger than 256, so this
    /// will be a number in the range 0-8.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it return 0.
    pub fn log2_lane_count(self) -> u8 {
        self.0 >> 4
    }

    /// Is this a scalar type? (That is, not a SIMD vector type).
    ///
    /// A scalar type is the same as a SIMD vector type with one lane.
    pub fn is_scalar(self) -> bool {
        self.log2_lane_count() == 0
    }

    /// Get the number of lanes in this SIMD vector type.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it returns 1.
    pub fn lane_count(self) -> u16 {
        1 << self.log2_lane_count()
    }

    /// Get the total number of bits used to represent this type.
    pub fn bits(self) -> u16 {
        self.lane_bits() as u16 * self.lane_count()
    }

    /// Get a SIMD vector type with `n` times more lanes than this one.
    ///
    /// If this is a scalar type, this produces a SIMD type with this as a lane type and `n` lanes.
    ///
    /// If this is already a SIMD vector type, this produces a SIMD vector type with `n *
    /// self.lane_count()` lanes.
    pub fn by(self, n: u16) -> Type {
        debug_assert!(self.lane_bits() > 0,
                      "Can't make SIMD vectors with void lanes.");
        debug_assert!(n.is_power_of_two(),
                      "Number of SIMD lanes must be a power of two");
        let log2_lanes: u32 = n.trailing_zeros();
        let new_type = self.0 as u32 + (log2_lanes << 4);
        assert!(new_type < 0x90, "No more than 256 SIMD lanes supported");
        Type(new_type as u8)
    }

    /// Get a SIMD vector with half the number of lanes.
    pub fn half_vector(self) -> Type {
        assert!(!self.is_scalar(), "Expecting a proper SIMD vector type.");
        Type(self.0 - 0x10)
    }
}

impl Display for Type {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        if self.is_void() {
            write!(f, "void")
        } else if self.is_bool() {
            write!(f, "b{}", self.lane_bits())
        } else if self.is_int() {
            write!(f, "i{}", self.lane_bits())
        } else if self.is_float() {
            write!(f, "f{}", self.lane_bits())
        } else if !self.is_scalar() {
            write!(f, "{}x{}", self.lane_type(), self.lane_count())
        } else {
            panic!("Invalid Type(0x{:x})", self.0)
        }
    }
}

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

    #[test]
    fn basic_scalars() {
        assert_eq!(VOID, VOID.lane_type());
        assert_eq!(0, VOID.bits());
        assert_eq!(B1, B1.lane_type());
        assert_eq!(B8, B8.lane_type());
        assert_eq!(B16, B16.lane_type());
        assert_eq!(B32, B32.lane_type());
        assert_eq!(B64, B64.lane_type());
        assert_eq!(I8, I8.lane_type());
        assert_eq!(I16, I16.lane_type());
        assert_eq!(I32, I32.lane_type());
        assert_eq!(I64, I64.lane_type());
        assert_eq!(F32, F32.lane_type());
        assert_eq!(F64, F64.lane_type());

        assert_eq!(VOID.lane_bits(), 0);
        assert_eq!(B1.lane_bits(), 1);
        assert_eq!(B8.lane_bits(), 8);
        assert_eq!(B16.lane_bits(), 16);
        assert_eq!(B32.lane_bits(), 32);
        assert_eq!(B64.lane_bits(), 64);
        assert_eq!(I8.lane_bits(), 8);
        assert_eq!(I16.lane_bits(), 16);
        assert_eq!(I32.lane_bits(), 32);
        assert_eq!(I64.lane_bits(), 64);
        assert_eq!(F32.lane_bits(), 32);
        assert_eq!(F64.lane_bits(), 64);
    }

    #[test]
    fn vectors() {
        let big = F64.by(256);
        assert_eq!(big.lane_bits(), 64);
        assert_eq!(big.lane_count(), 256);
        assert_eq!(big.bits(), 64 * 256);

        assert_eq!(format!("{}", big.half_vector()), "f64x128");
        assert_eq!(format!("{}", B1.by(2).half_vector()), "b1");
    }

    #[test]
    fn format_scalars() {
        assert_eq!(format!("{}", VOID), "void");
        assert_eq!(format!("{}", B1), "b1");
        assert_eq!(format!("{}", B8), "b8");
        assert_eq!(format!("{}", B16), "b16");
        assert_eq!(format!("{}", B32), "b32");
        assert_eq!(format!("{}", B64), "b64");
        assert_eq!(format!("{}", I8), "i8");
        assert_eq!(format!("{}", I16), "i16");
        assert_eq!(format!("{}", I32), "i32");
        assert_eq!(format!("{}", I64), "i64");
        assert_eq!(format!("{}", F32), "f32");
        assert_eq!(format!("{}", F64), "f64");
    }

    #[test]
    fn format_vectors() {
        assert_eq!(format!("{}", B1.by(8)), "b1x8");
        assert_eq!(format!("{}", B8.by(1)), "b8");
        assert_eq!(format!("{}", B16.by(256)), "b16x256");
        assert_eq!(format!("{}", B32.by(4).by(2)), "b32x8");
        assert_eq!(format!("{}", B64.by(8)), "b64x8");
        assert_eq!(format!("{}", I8.by(64)), "i8x64");
        assert_eq!(format!("{}", F64.by(2)), "f64x2");
    }
}
<commit_msg>Add function signatures.<commit_after>
//! Common types for the Cretonne code generator.

use std::fmt::{self, Display, Formatter, Write};

// ====--------------------------------------------------------------------------------------====//
//
// Value types
//
// ====--------------------------------------------------------------------------------------====//

/// The type of an SSA value.
///
/// The `VOID` type is only used for instructions that produce no value. It can't be part of a SIMD
/// vector.
///
/// Basic integer types: `I8`, `I16`, `I32`, and `I64`. These types are sign-agnostic.
///
/// Basic floating point types: `F32` and `F64`. IEEE single and double precision.
///
/// Boolean types: `B1`, `B8`, `B16`, `B32`, and `B64`. These all encode 'true' or 'false'. The
/// larger types use redundant bits.
///
/// SIMD vector types have power-of-two lanes, up to 256. Lanes can be any int/float/bool type.
///
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Type(u8);

/// No type. Used for functions without a return value. Can't be loaded or stored. Can't be part of
/// a SIMD vector.
pub const VOID: Type = Type(0);

/// Integer type with 8 bits.
pub const I8: Type = Type(1);

/// Integer type with 16 bits.
pub const I16: Type = Type(2);

/// Integer type with 32 bits.
pub const I32: Type = Type(3);

/// Integer type with 64 bits.
pub const I64: Type = Type(4);

/// IEEE single precision floating point type.
pub const F32: Type = Type(5);

/// IEEE double precision floating point type.
pub const F64: Type = Type(6);

/// Boolean type. Can't be loaded or stored, but can be used to form SIMD vectors.
pub const B1: Type = Type(7);

/// Boolean type using 8 bits to represent true/false.
pub const B8: Type = Type(8);

/// Boolean type using 16 bits to represent true/false.
pub const B16: Type = Type(9);

/// Boolean type using 32 bits to represent true/false.
pub const B32: Type = Type(10);

/// Boolean type using 64 bits to represent true/false.
pub const B64: Type = Type(11);

impl Type {
    /// Get the lane type of this SIMD vector type.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it returns itself.
    pub fn lane_type(self) -> Type {
        Type(self.0 & 0x0f)
    }

    /// Get the number of bits in a lane.
    pub fn lane_bits(self) -> u8 {
        match self.lane_type() {
            B1 => 1,
            B8 | I8 => 8,
            B16 | I16 => 16,
            B32 | I32 | F32 => 32,
            B64 | I64 | F64 => 64,
            _ => 0,
        }
    }

    /// Is this the VOID type?
    pub fn is_void(self) -> bool {
        self == VOID
    }

    /// Is this a scalar boolean type?
    pub fn is_bool(self) -> bool {
        match self {
            B1 | B8 | B16 | B32 | B64 => true,
            _ => false,
        }
    }

    /// Is this a scalar integer type?
    pub fn is_int(self) -> bool {
        match self {
            I8 | I16 | I32 | I64 => true,
            _ => false,
        }
    }

    /// Is this a scalar floating point type?
    pub fn is_float(self) -> bool {
        match self {
            F32 | F64 => true,
            _ => false,
        }
    }

    /// Get log2 of the number of lanes in this SIMD vector type.
    ///
    /// All SIMD types have a lane count that is a power of two and no larger than 256, so this
    /// will be a number in the range 0-8.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it return 0.
    pub fn log2_lane_count(self) -> u8 {
        self.0 >> 4
    }

    /// Is this a scalar type? (That is, not a SIMD vector type).
    ///
    /// A scalar type is the same as a SIMD vector type with one lane.
    pub fn is_scalar(self) -> bool {
        self.log2_lane_count() == 0
    }

    /// Get the number of lanes in this SIMD vector type.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it returns 1.
    pub fn lane_count(self) -> u16 {
        1 << self.log2_lane_count()
    }

    /// Get the total number of bits used to represent this type.
    pub fn bits(self) -> u16 {
        self.lane_bits() as u16 * self.lane_count()
    }

    /// Get a SIMD vector type with `n` times more lanes than this one.
    ///
    /// If this is a scalar type, this produces a SIMD type with this as a lane type and `n` lanes.
    ///
    /// If this is already a SIMD vector type, this produces a SIMD vector type with `n *
    /// self.lane_count()` lanes.
    pub fn by(self, n: u16) -> Type {
        debug_assert!(self.lane_bits() > 0,
                      "Can't make SIMD vectors with void lanes.");
        debug_assert!(n.is_power_of_two(),
                      "Number of SIMD lanes must be a power of two");
        let log2_lanes: u32 = n.trailing_zeros();
        let new_type = self.0 as u32 + (log2_lanes << 4);
        assert!(new_type < 0x90, "No more than 256 SIMD lanes supported");
        Type(new_type as u8)
    }

    /// Get a SIMD vector with half the number of lanes.
    pub fn half_vector(self) -> Type {
        assert!(!self.is_scalar(), "Expecting a proper SIMD vector type.");
        Type(self.0 - 0x10)
    }
}

impl Display for Type {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        if self.is_void() {
            write!(f, "void")
        } else if self.is_bool() {
            write!(f, "b{}", self.lane_bits())
        } else if self.is_int() {
            write!(f, "i{}", self.lane_bits())
        } else if self.is_float() {
            write!(f, "f{}", self.lane_bits())
        } else if !self.is_scalar() {
            write!(f, "{}x{}", self.lane_type(), self.lane_count())
        } else {
            panic!("Invalid Type(0x{:x})", self.0)
        }
    }
}

// ====--------------------------------------------------------------------------------------====//
//
// Function signatures
//
// ====--------------------------------------------------------------------------------------====//

/// Function argument extension options.
///
/// On some architectures, small integer function arguments are extended to the width of a
/// general-purpose register.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ArgumentExtension {
    /// No extension, high bits are indeterminate.
    None,
    /// Unsigned extension: high bits in register are 0.
    Uext,
    /// Signed extension: high bits in register replicate sign bit.
    Sext,
}

/// Function argument or return value type.
///
/// This describes the value type being passed to or from a function along with flags that affect
/// how the argument is passed.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct ArgumentType {
    pub value_type: Type,
    pub extension: ArgumentExtension,
    /// Place this argument in a register if possible.
    pub inreg: bool,
}

/// Function signature.
///
/// The function signature describes the types of arguments and return values along with other
/// details that are needed to call a function correctly.
pub struct Signature {
    pub argument_types: Vec<ArgumentType>,
    pub return_types: Vec<ArgumentType>,
}

impl ArgumentType {
    pub fn new(vt: Type) -> ArgumentType {
        ArgumentType {
            value_type: vt,
            extension: ArgumentExtension::None,
            inreg: false,
        }
    }
}

impl Display for ArgumentType {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.value_type));
        match self.extension {
            ArgumentExtension::None => {}
            ArgumentExtension::Uext => try!(write!(f, " uext")),
            ArgumentExtension::Sext => try!(write!(f, " sext")),
        }
        if self.inreg {
            try!(write!(f, " inreg"));
        }
        Ok(())
    }
}

impl Signature {
    pub fn new() -> Signature {
        Signature {
            argument_types: Vec::new(),
            return_types: Vec::new(),
        }
    }
}

fn write_list(f: &mut Formatter, args: &Vec<ArgumentType>) -> fmt::Result {
    match args.split_first() {
        None => {}
        Some((first, rest)) => {
            try!(write!(f, "{}", first));
            for arg in rest {
                try!(write!(f, ", {}", arg));
            }
        }
    }
    Ok(())
}

impl Display for Signature {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        try!(write!(f, "("));
        try!(write_list(f, &self.argument_types));
        try!(write!(f, ")"));
        if !self.return_types.is_empty() {
            try!(write!(f, " -> "));
            try!(write_list(f, &self.return_types));
        }
        Ok(())
    }
}

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

    #[test]
    fn basic_scalars() {
        assert_eq!(VOID, VOID.lane_type());
        assert_eq!(0, VOID.bits());
        assert_eq!(B1, B1.lane_type());
        assert_eq!(B8, B8.lane_type());
        assert_eq!(B16, B16.lane_type());
        assert_eq!(B32, B32.lane_type());
        assert_eq!(B64, B64.lane_type());
        assert_eq!(I8, I8.lane_type());
        assert_eq!(I16, I16.lane_type());
        assert_eq!(I32, I32.lane_type());
        assert_eq!(I64, I64.lane_type());
        assert_eq!(F32, F32.lane_type());
        assert_eq!(F64, F64.lane_type());

        assert_eq!(VOID.lane_bits(), 0);
        assert_eq!(B1.lane_bits(), 1);
        assert_eq!(B8.lane_bits(), 8);
        assert_eq!(B16.lane_bits(), 16);
        assert_eq!(B32.lane_bits(), 32);
        assert_eq!(B64.lane_bits(), 64);
        assert_eq!(I8.lane_bits(), 8);
        assert_eq!(I16.lane_bits(), 16);
        assert_eq!(I32.lane_bits(), 32);
        assert_eq!(I64.lane_bits(), 64);
        assert_eq!(F32.lane_bits(), 32);
        assert_eq!(F64.lane_bits(), 64);
    }

    #[test]
    fn vectors() {
        let big = F64.by(256);
        assert_eq!(big.lane_bits(), 64);
        assert_eq!(big.lane_count(), 256);
        assert_eq!(big.bits(), 64 * 256);

        assert_eq!(format!("{}", big.half_vector()), "f64x128");
        assert_eq!(format!("{}", B1.by(2).half_vector()), "b1");
    }

    #[test]
    fn format_scalars() {
        assert_eq!(format!("{}", VOID), "void");
        assert_eq!(format!("{}", B1), "b1");
        assert_eq!(format!("{}", B8), "b8");
        assert_eq!(format!("{}", B16), "b16");
        assert_eq!(format!("{}", B32), "b32");
        assert_eq!(format!("{}", B64), "b64");
        assert_eq!(format!("{}", I8), "i8");
        assert_eq!(format!("{}", I16), "i16");
        assert_eq!(format!("{}", I32), "i32");
        assert_eq!(format!("{}", I64), "i64");
        assert_eq!(format!("{}", F32), "f32");
        assert_eq!(format!("{}", F64), "f64");
    }

    #[test]
    fn format_vectors() {
        assert_eq!(format!("{}", B1.by(8)), "b1x8");
        assert_eq!(format!("{}", B8.by(1)), "b8");
        assert_eq!(format!("{}", B16.by(256)), "b16x256");
        assert_eq!(format!("{}", B32.by(4).by(2)), "b32x8");
        assert_eq!(format!("{}", B64.by(8)), "b64x8");
        assert_eq!(format!("{}", I8.by(64)), "i8x64");
        assert_eq!(format!("{}", F64.by(2)), "f64x2");
    }

    #[test]
    fn argument_type() {
        let mut t = ArgumentType::new(I32);
        assert_eq!(format!("{}", t), "i32");
        t.extension = ArgumentExtension::Uext;
        assert_eq!(format!("{}", t), "i32 uext");
        t.inreg = true;
        assert_eq!(format!("{}", t), "i32 uext inreg");
    }

    #[test]
    fn signatures() {
        let mut sig = Signature::new();
        assert_eq!(format!("{}", sig), "()");
        sig.argument_types.push(ArgumentType::new(I32));
        assert_eq!(format!("{}", sig), "(i32)");
        sig.return_types.push(ArgumentType::new(F32));
        assert_eq!(format!("{}", sig), "(i32) -> f32");
        sig.argument_types.push(ArgumentType::new(I32.by(4)));
        assert_eq!(format!("{}", sig), "(i32, i32x4) -> f32");
        sig.return_types.push(ArgumentType::new(B8));
        assert_eq!(format!("{}", sig), "(i32, i32x4) -> f32, b8");
    }
}
<|endoftext|>