<commit_before>/* Copyright (C)  2016 nokaa <nokaa@cock.li>
 * This software is licensed under the terms of the
 * GNU Affero General Public License. You should have
 * received a copy of this license with this software.
 * The license may also be found at https://gnu.org/licenses/agpl.txt
 */

mod command;
mod cursor;
mod insert;

use rustty::{self, Event, Color};
use editor;

/// `Term` represents our client application. This allows
/// us to work with the filesystem and the UI.
pub struct Term<'a> {
    /// Represents the location of the cursor in our UI
    cursor: cursor::Cursor,
    /// Contains file information; allows us to work with
    /// the filesystem
    editor: &'a mut editor::Editor<'a>,
    /// This is the UI itself
    term: rustty::Terminal,
    /// Represents the running status
    quit: bool,
    /// Represents the topmost line in our UI
    line: usize,
    /// Represents the total number of lines in the currently
    /// open file
    total_lines: usize,
}

impl<'a> Term<'a> {
    pub fn new(editor: &'a mut editor::Editor<'a>) -> Term<'a> {
        let total_lines = editor.contents.len();
        Term {
            cursor: cursor::Cursor::new(Color::Red),
            editor: editor,
            term: rustty::Terminal::new().unwrap(),
            quit: false,
            line: 0,
            total_lines: total_lines,
        }
    }

    /// Launches the terminal.
    pub fn run(&mut self) {
        self.term[self.cursor.current_pos()].set_bg(self.cursor.color);
        self.print_file();
        self.prompt();
        self.term.swap_buffers().unwrap();

        while !self.quit {
            let evt = self.term.get_event(100).unwrap();
            if let Some(Event::Key(ch)) = evt {
                if self.editor.command_mode() {
                    command::handle(self, ch);
                } else {
                    insert::handle(self, ch);
                }

                if self.cursor.pos.x >= self.term.cols() - 1 {
                    self.term[self.cursor.last_pos()].set_bg(Color::Default);
                    self.cursor.save_pos();
                    self.cursor.pos.x = 0;
                    self.cursor.pos.y += 1;
                }
                if self.cursor.pos.y >= self.term.rows() - 1 {
                    self.term[self.cursor.last_pos()].set_bg(Color::Default);
                    self.cursor.save_pos();
                    self.cursor.pos.x = 0;
                    self.cursor.pos.y = 0;
                }

                self.term[self.cursor.last_pos()].set_bg(Color::Default);
                self.term[self.cursor.current_pos()].set_bg(self.cursor.color);
                self.term.swap_buffers().unwrap();
            }
        }
    }

    /// Prints our prompt to the UI.
    pub fn prompt(&mut self) {
        let w = self.term.cols();
        let h = self.term.rows();

        for i in 0..w {
            self.term[(i, h - 2)].set_bg(Color::Red);
        }

        for (i, c) in self.editor.filename().chars().enumerate() {
            self.term[(i, h - 2)].set_ch(c);
        }
    }

    /// Prints our editor's contents to the UI.
    fn print_file(&mut self) {
        let mut i = 0;
        let mut j = 0;
        for line in &self.editor.contents {
            for b in line {
                self.term[(j, i)].set_ch(*b as char);
                j += 1;
            }
            i += 1;
            j = 0;
            if i == self.term.rows() - 2 {
                break;
            }
        }
    }

    pub fn move_cursor(&mut self, direction: cursor::Direction) {
        match direction {
            cursor::Direction::Up => {
                if self.cursor.pos.y != 0 {
                    self.cursor.save_pos();
                    self.cursor.pos.y -= 1;
                } else if self.current_line() != 0 {
                    let current_line = self.current_line();
                    self.set_current_line(current_line - 1);
                    self.redraw_file();
                }
            }
            cursor::Direction::Down => {
                if self.total_lines() <= self.term.rows() - 3 {
                    if self.cursor.pos.y != self.term.rows() - 3 &&
                       self.cursor.pos.y < self.total_lines() - 1
                    {
                        self.cursor.save_pos();
                        self.cursor.pos.y += 1;
                    }
                } else {
                    if self.cursor.pos.y != self.term.rows() - 3 {
                        self.cursor.save_pos();
                        self.cursor.pos.y += 1;
                    } else if self.cursor.pos.y + self.current_line() < self.total_lines() {
                        let current_line = self.current_line();
                        self.set_current_line(current_line + 1);
                        self.redraw_file();
                    }
                }
            }
            cursor::Direction::Left => {
                if self.cursor.pos.x != 0 {
                    self.cursor.save_pos();
                    self.cursor.pos.x -= 1;
                }
            }
            cursor::Direction::Right => {
                // TODO(nokaa): We don't want to extend beyond the
                // line length here, but we first need a way to
                // determine a given line's length.
                let curr = self.cursor.pos.y + self.current_line();
                if self.cursor.pos.x != self.editor.contents[curr].len() - 1 {
                    self.cursor.save_pos();
                    self.cursor.pos.x += 1;
                }
            }
        }
    }

    /// Changes the value of the `quit` attribute to `true`.
    pub fn quit(&mut self) {
        self.quit = true;
    }

    /// Returns the total lines in our file
    pub fn total_lines(&self) -> usize {
        self.total_lines
    }

    /// Allows us to modify the total number of lines
    /// in our file, e.g. if a new line is added.
    pub fn set_total_lines(&mut self, change: isize) {
        let new = self.total_lines as isize + change;
        self.total_lines = new as usize;
    }

    /// Gives the current line at the top of our UI
    pub fn current_line(&self) -> usize {
        self.line
    }

    /// Allows us to change what the topmost line in the UI is
    pub fn set_current_line(&mut self, line: usize) {
        self.line = line;
    }

    /// This function redraws the portion of our UI displaying
    /// file contents. E.g. this is called when the current line
    /// changes.
    pub fn redraw_file(&mut self) {
        println!("redraw!");
    }
}
<commit_msg>Implemented file scrolling in UI<commit_after>/* Copyright (C)  2016 nokaa <nokaa@cock.li>
 * This software is licensed under the terms of the
 * GNU Affero General Public License. You should have
 * received a copy of this license with this software.
 * The license may also be found at https://gnu.org/licenses/agpl.txt
 */

mod command;
mod cursor;
mod insert;

use rustty::{self, Event, Color};
use editor;

/// `Term` represents our client application. This allows
/// us to work with the filesystem and the UI.
pub struct Term<'a> {
    /// Represents the location of the cursor in our UI
    cursor: cursor::Cursor,
    /// Contains file information; allows us to work with
    /// the filesystem
    editor: &'a mut editor::Editor<'a>,
    /// This is the UI itself
    term: rustty::Terminal,
    /// Represents the running status
    quit: bool,
    /// Represents the topmost line in our UI
    line: usize,
    /// Represents the total number of lines in the currently
    /// open file
    total_lines: usize,
}

impl<'a> Term<'a> {
    pub fn new(editor: &'a mut editor::Editor<'a>) -> Term<'a> {
        let total_lines = editor.contents.len();
        Term {
            cursor: cursor::Cursor::new(Color::Red),
            editor: editor,
            term: rustty::Terminal::new().unwrap(),
            quit: false,
            line: 0,
            total_lines: total_lines,
        }
    }

    /// Launches the terminal.
    pub fn run(&mut self) {
        self.term[self.cursor.current_pos()].set_bg(self.cursor.color);
        let current_line = self.current_line();
        self.print_file(current_line);
        self.prompt();
        self.term.swap_buffers().unwrap();

        while !self.quit {
            let evt = self.term.get_event(100).unwrap();
            if let Some(Event::Key(ch)) = evt {
                if self.editor.command_mode() {
                    command::handle(self, ch);
                } else {
                    insert::handle(self, ch);
                }

                if self.cursor.pos.x >= self.term.cols() - 1 {
                    self.term[self.cursor.last_pos()].set_bg(Color::Default);
                    self.cursor.save_pos();
                    self.cursor.pos.x = 0;
                    self.cursor.pos.y += 1;
                }
                if self.cursor.pos.y >= self.term.rows() - 1 {
                    self.term[self.cursor.last_pos()].set_bg(Color::Default);
                    self.cursor.save_pos();
                    self.cursor.pos.x = 0;
                    self.cursor.pos.y = 0;
                }

                self.term[self.cursor.last_pos()].set_bg(Color::Default);
                self.term[self.cursor.current_pos()].set_bg(self.cursor.color);
                self.term.swap_buffers().unwrap();
            }
        }
    }

    /// Prints our prompt to the UI.
    pub fn prompt(&mut self) {
        let w = self.term.cols();
        let h = self.term.rows();

        for i in 0..w {
            self.term[(i, h - 2)].set_bg(Color::Red);
        }

        for (i, c) in self.editor.filename().chars().enumerate() {
            self.term[(i, h - 2)].set_ch(c);
        }
    }

    /// Prints our editor's contents to the UI.
    fn print_file(&mut self, start: usize) {
        let w = self.term.cols();
        let mut i = 0;
        let mut j = 0;
        for line in &self.editor.contents {
            if i < start {
                i += 1;
                continue;
            }

            for b in line {
                self.term[(j, i - start)].set_ch(*b as char);
                j += 1;
            }
            while j < w {
                self.term[(j, i - start)].set_ch(' ');
                j += 1;
            }

            i += 1;
            j = 0;
            if i - start == self.term.rows() - 2 {
                break;
            }
        }
    }

    pub fn move_cursor(&mut self, direction: cursor::Direction) {
        match direction {
            cursor::Direction::Up => {
                if self.cursor.pos.y != 0 {
                    self.cursor.save_pos();
                    self.cursor.pos.y -= 1;
                } else if self.current_line() != 0 {
                    let current_line = self.current_line();
                    self.set_current_line(current_line - 1);
                    self.redraw_file();
                }
            }
            cursor::Direction::Down => {
                if self.total_lines() <= self.term.rows() - 3 {
                    if self.cursor.pos.y != self.term.rows() - 3 &&
                       self.cursor.pos.y < self.total_lines() - 1
                    {
                        self.cursor.save_pos();
                        self.cursor.pos.y += 1;
                    }
                } else {
                    if self.cursor.pos.y != self.term.rows() - 3 {
                        self.cursor.save_pos();
                        self.cursor.pos.y += 1;
                    } else if self.cursor.pos.y + self.current_line() < self.total_lines() - 1 {
                        let current_line = self.current_line();
                        self.set_current_line(current_line + 1);
                        self.redraw_file();
                    }
                }
            }
            cursor::Direction::Left => {
                if self.cursor.pos.x != 0 {
                    self.cursor.save_pos();
                    self.cursor.pos.x -= 1;
                }
            }
            cursor::Direction::Right => {
                let curr = self.cursor.pos.y + self.current_line();
                if self.cursor.pos.x != self.editor.contents[curr].len() - 1 {
                    self.cursor.save_pos();
                    self.cursor.pos.x += 1;
                }
            }
        }
    }

    /// Changes the value of the `quit` attribute to `true`.
    pub fn quit(&mut self) {
        self.quit = true;
    }

    /// Returns the total lines in our file
    pub fn total_lines(&self) -> usize {
        self.total_lines
    }

    /// Allows us to modify the total number of lines
    /// in our file, e.g. if a new line is added.
    pub fn set_total_lines(&mut self, change: isize) {
        let new = self.total_lines as isize + change;
        self.total_lines = new as usize;
    }

    /// Gives the current line at the top of our UI
    pub fn current_line(&self) -> usize {
        self.line
    }

    /// Allows us to change what the topmost line in the UI is
    pub fn set_current_line(&mut self, line: usize) {
        self.line = line;
    }

    /// This function redraws the portion of our UI displaying
    /// file contents. E.g. this is called when the current line
    /// changes.
    pub fn redraw_file(&mut self) {
        let current_line = self.current_line();
        self.print_file(current_line);
    }
}
<|endoftext|>


<commit_before>use libc::system;
use std::ffi::CString;

static TMUX_NAME: &'static str = "tmux";

fn call(command: String) {
    let system_call = CString::new(format!("{} {}", TMUX_NAME, command)).unwrap();
    unsafe { system(system_call.as_ptr()); };
}

pub fn open(session_name: String) -> () {
    call(format!("attach -t {}", session_name));
}

pub fn new_session(session_name: String, first_window: String) -> () {
    call(format!("new -d -s {} -n {}", session_name, first_window));
}

static SELECT_LAYOUT: &'static str = "select-layout";
pub fn select_layout(window: String, layout: String) -> () {
    call(format!("{} -t {} {}", SELECT_LAYOUT, window, layout));
}

pub fn new_window(session_name: String, window_name: String) -> () {
    call(format!("new-window -t {} -n {}", session_name, window_name));
}
<commit_msg>Break the single line out in to multiple.<commit_after>use libc::system;
use std::ffi::CString;

static TMUX_NAME: &'static str = "tmux";

fn call(command: String) -> () {
    let line = format!("{} {}", TMUX_NAME, command);
    let system_call = CString::new(line.clone()).unwrap();
    //println!("{}", line.clone());
    unsafe { system(system_call.as_ptr()); };
}

pub fn open(session_name: String) -> () {
    call(format!("attach -t {}", session_name));
}

pub fn new_session(session_name: String, first_window: String) -> () {
    call(format!("new -d -s {} -n {}", session_name, first_window));
}

static SELECT_LAYOUT: &'static str = "select-layout";
pub fn select_layout(window: String, layout: String) -> () {
    call(format!("{} -t {} {}", SELECT_LAYOUT, window, layout));
}

pub fn new_window(session_name: String, window_name: String) -> () {
    call(format!("new-window -t {} -n {}", session_name, window_name));
}
<|endoftext|>


<commit_before>//! module for topologcal vector space
//!

use std::iter::Sum;
use ndarray::{ArrayBase, Data, Dimension, LinalgScalar, IntoDimension};
use num_traits::Float;

pub fn inf<A, Distance, S1, S2, D>(a: &ArrayBase<S1, D>, b: &ArrayBase<S2, D>) -> Result<Distance, String>
    where A: LinalgScalar + Squared<Output = Distance>,
          Distance: Float + Sum,
          S1: Data<Elem = A>,
          S2: Data<Elem = A>,
          D: Dimension
{
    if a.shape() != b.shape() {
        return Err("Shapes are different".into());
    }
    let mut max_tol = Distance::zero();
    for (idx, val) in a.indexed_iter() {
        let t = b[idx.into_dimension()];
        let tol = (*val - t).sq_abs();
        if tol > max_tol {
            max_tol = tol;
        }
    }
    Ok(max_tol)
}

pub fn l1<A, Distance, S1, S2, D>(a: &ArrayBase<S1, D>, b: &ArrayBase<S2, D>) -> Result<Distance, String>
    where A: LinalgScalar + Squared<Output = Distance>,
          Distance: Float + Sum,
          S1: Data<Elem = A>,
          S2: Data<Elem = A>,
          D: Dimension
{
    if a.shape() != b.shape() {
        return Err("Shapes are different".into());
    }
    Ok(a.indexed_iter().map(|(idx, val)| (b[idx.into_dimension()] - *val).sq_abs()).sum())
}

pub fn l2<A, Distance, S1, S2, D>(a: &ArrayBase<S1, D>, b: &ArrayBase<S2, D>) -> Result<Distance, String>
    where A: LinalgScalar + Squared<Output = Distance>,
          Distance: Float + Sum,
          S1: Data<Elem = A>,
          S2: Data<Elem = A>,
          D: Dimension
{
    if a.shape() != b.shape() {
        return Err("Shapes are different".into());
    }
    Ok(a.indexed_iter().map(|(idx, val)| (b[idx.into_dimension()] - *val).squared()).sum::<Distance>().sqrt())
}

#[derive(Debug)]
pub enum NotCloseError<Tol> {
    ShapeMismatch(String),
    LargeDeviation(Tol),
}

pub fn all_close_inf<A, Tol, S1, S2, D>(a: &ArrayBase<S1, D>,
                                        b: &ArrayBase<S2, D>,
                                        atol: Tol)
                                        -> Result<Tol, NotCloseError<Tol>>
    where A: LinalgScalar + Squared<Output = Tol>,
          Tol: Float + Sum,
          S1: Data<Elem = A>,
          S2: Data<Elem = A>,
          D: Dimension
{
    if a.shape() != b.shape() {
        return Err(NotCloseError::ShapeMismatch("Shapes are different".into()));
    }
    let mut max_tol = Tol::zero();
    for (idx, val) in a.indexed_iter() {
        let t = b[idx.into_dimension()];
        let tol = (*val - t).sq_abs();
        if tol > atol {
            return Err(NotCloseError::LargeDeviation(tol));
        }
        if tol > max_tol {
            max_tol = tol;
        }
    }
    Ok(max_tol)
}

pub fn all_close_l1<A, Tol, S1, S2, D>(a: &ArrayBase<S1, D>,
                                       b: &ArrayBase<S2, D>,
                                       rtol: Tol)
                                       -> Result<Tol, NotCloseError<Tol>>
    where A: LinalgScalar + Squared<Output = Tol>,
          Tol: Float + Sum,
          S1: Data<Elem = A>,
          S2: Data<Elem = A>,
          D: Dimension
{
    if a.shape() != b.shape() {
        return Err(NotCloseError::ShapeMismatch("Shapes are different".into()));
    }
    let nrm: Tol = b.iter().map(|x| x.sq_abs()).sum();
    let dev: Tol = a.indexed_iter().map(|(idx, val)| (b[idx.into_dimension()] - *val).sq_abs()).sum();
    if dev / nrm > rtol {
        Err(NotCloseError::LargeDeviation(dev / nrm))
    } else {
        Ok(dev / nrm)
    }
}

pub fn all_close_l2<A, Tol, S1, S2, D>(a: &ArrayBase<S1, D>,
                                       b: &ArrayBase<S2, D>,
                                       rtol: Tol)
                                       -> Result<Tol, NotCloseError<Tol>>
    where A: LinalgScalar + Squared<Output = Tol>,
          Tol: Float + Sum,
          S1: Data<Elem = A>,
          S2: Data<Elem = A>,
          D: Dimension
{
    if a.shape() != b.shape() {
        return Err(NotCloseError::ShapeMismatch("Shapes are different".into()));
    }
    let nrm: Tol = b.iter().map(|x| x.squared()).sum();
    let dev: Tol = a.indexed_iter().map(|(idx, val)| (b[idx.into_dimension()] - *val).squared()).sum();
    let d = (dev / nrm).sqrt();
    if d > rtol {
        Err(NotCloseError::LargeDeviation(d))
    } else {
        Ok(d)
    }
}

pub trait Squared {
    type Output;
    fn squared(&self) -> Self::Output;
    fn sq_abs(&self) -> Self::Output;
}

impl<A: Float> Squared for A {
    type Output = A;
    fn squared(&self) -> A {
        *self * *self
    }
    fn sq_abs(&self) -> A {
        self.abs()
    }
}
<commit_msg>Reimplement all_close_{l1,l2,max} using Vector trait<commit_after>//! module for topologcal vector space
//!

use std::iter::Sum;
use ndarray::{ArrayBase, Data, Dimension, LinalgScalar};
use num_traits::Float;
use super::vector::*;

pub fn all_close_max<A, Tol, S1, S2, D>(test: &ArrayBase<S1, D>,
                                        truth: &ArrayBase<S2, D>,
                                        atol: Tol)
                                        -> Result<Tol, Tol>
    where A: LinalgScalar + Squared<Output = Tol>,
          Tol: Float + Sum,
          S1: Data<Elem = A>,
          S2: Data<Elem = A>,
          D: Dimension
{
    let tol = (test - truth).norm_max();
    if tol < atol { Ok(tol) } else { Err(tol) }
}

pub fn all_close_l1<A, Tol, S1, S2, D>(test: &ArrayBase<S1, D>, truth: &ArrayBase<S2, D>, rtol: Tol) -> Result<Tol, Tol>
    where A: LinalgScalar + Squared<Output = Tol>,
          Tol: Float + Sum,
          S1: Data<Elem = A>,
          S2: Data<Elem = A>,
          D: Dimension
{
    let tol = (test - truth).norm_l1() / truth.norm_l1();
    if tol < rtol { Ok(tol) } else { Err(tol) }
}

pub fn all_close_l2<A, Tol, S1, S2, D>(test: &ArrayBase<S1, D>, truth: &ArrayBase<S2, D>, rtol: Tol) -> Result<Tol, Tol>
    where A: LinalgScalar + Squared<Output = Tol>,
          Tol: Float + Sum,
          S1: Data<Elem = A>,
          S2: Data<Elem = A>,
          D: Dimension
{
    let tol = (test - truth).norm_l2() / truth.norm_l2();
    if tol < rtol { Ok(tol) } else { Err(tol) }
}
<|endoftext|>


<commit_before>
#[macro_use]
extern crate basen;

#[cfg(test)]
mod test {
    use basen::BaseN;

    #[test]
    fn test_convert_base() {

        let expected: BaseN = BaseN::with_existing(
            10,
            vec![9, 6, 3, 4]
        );
        let x: BaseN = BaseN::with_existing(
            16,
            vec![1, 1, 1, 1]
        );

        assert_eq!( expected, x.to_base(10).unwrap() );
    }

    #[test]
    fn test_from_usize() {

        let val10 = 4369;
        let new_base = 16;

        let expected: BaseN = BaseN::with_existing(
            16,
            vec![1, 1, 1, 1]
        );

        assert_eq!( expected, BaseN::from_usize(new_base, val10).unwrap() );
    }

    #[test]
    fn test_add_same_base() {

        let expected: BaseN = BaseN::with_existing(
            10,
            vec![3, 3, 3, 3]
        );
        let x: BaseN = BaseN::with_existing(
            10,
            vec![1, 1, 1, 1]
        );
        let y: BaseN = BaseN::with_existing(
            10,
            vec![2, 2, 2, 2]
        );

        let z: BaseN = (x + y).unwrap();

        //assert!(true);
        assert_eq!( expected, z );
    }

    #[test]
    fn test_add_different_base() {

        let expected: BaseN = BaseN::with_existing(
            16,
            vec![15, 11, 9, 1]
        );
        let x: BaseN = BaseN::with_existing(
            16,
            vec![1, 1, 1, 1]
        );
        let y: BaseN = BaseN::with_existing(
            10,
            vec![2, 2, 2, 2]
        );

        let z: BaseN = (x + y.to_base(16).unwrap()).unwrap();

        //assert!(true);
        assert_eq!( expected, z );
    }

    #[test]
    fn test_sub_same_base() {

        let x: BaseN = BaseN::with_existing(
            10,
            vec![3, 3, 3, 3]
        );
        let y: BaseN = BaseN::with_existing(
            10,
            vec![1, 1, 1, 1]
        );
        let expected: BaseN = BaseN::with_existing(
            10,
            vec![2, 2, 2, 2]
        );

        let z: BaseN = (x - y).unwrap();

        //assert!(true);
        assert_eq!( expected, z );
    }

    #[test]
    fn test_sub_different_base() {

        let x: BaseN = BaseN::with_existing(
            16,
            vec![15, 11, 9, 1]
        );
        let expected: BaseN = BaseN::with_existing(
            16,
            vec![1, 1, 1, 1]
        );
        let y: BaseN = BaseN::with_existing(
            10,
            vec![2, 2, 2, 2]
        );

        let z: BaseN = (x - y.to_base(16).unwrap()).unwrap();

        //assert!(true);
        assert_eq!( expected, z );
    }

}
<commit_msg>Add tests for eq<commit_after>
#[macro_use]
extern crate basen;

#[cfg(test)]
mod test {
    use basen::BaseN;

    #[test]
    fn test_convert_base() {

        let expected: BaseN = BaseN::with_existing(
            10,
            vec![9, 6, 3, 4]
        );
        let x: BaseN = BaseN::with_existing(
            16,
            vec![1, 1, 1, 1]
        );

        assert_eq!( expected, x.to_base(10).unwrap() );
    }

    #[test]
    fn test_from_usize() {

        let val10 = 4369;
        let new_base = 16;

        let expected: BaseN = BaseN::with_existing(
            16,
            vec![1, 1, 1, 1]
        );

        assert_eq!( expected, BaseN::from_usize(new_base, val10).unwrap() );
    }

    #[test]
    fn test_add_same_base() {

        let expected: BaseN = BaseN::with_existing(
            10,
            vec![3, 3, 3, 3]
        );
        let x: BaseN = BaseN::with_existing(
            10,
            vec![1, 1, 1, 1]
        );
        let y: BaseN = BaseN::with_existing(
            10,
            vec![2, 2, 2, 2]
        );

        let z: BaseN = (x + y).unwrap();

        //assert!(true);
        assert_eq!( expected, z );
    }

    #[test]
    fn test_add_different_base() {

        let expected: BaseN = BaseN::with_existing(
            16,
            vec![15, 11, 9, 1]
        );
        let x: BaseN = BaseN::with_existing(
            16,
            vec![1, 1, 1, 1]
        );
        let y: BaseN = BaseN::with_existing(
            10,
            vec![2, 2, 2, 2]
        );

        let z: BaseN = (x + y.to_base(16).unwrap()).unwrap();

        //assert!(true);
        assert_eq!( expected, z );
    }

    #[test]
    fn test_sub_same_base() {

        let x: BaseN = BaseN::with_existing(
            10,
            vec![3, 3, 3, 3]
        );
        let y: BaseN = BaseN::with_existing(
            10,
            vec![1, 1, 1, 1]
        );
        let expected: BaseN = BaseN::with_existing(
            10,
            vec![2, 2, 2, 2]
        );

        let z: BaseN = (x - y).unwrap();

        //assert!(true);
        assert_eq!( expected, z );
    }

    #[test]
    fn test_sub_different_base() {

        let x: BaseN = BaseN::with_existing(
            16,
            vec![15, 11, 9, 1]
        );
        let expected: BaseN = BaseN::with_existing(
            16,
            vec![1, 1, 1, 1]
        );
        let y: BaseN = BaseN::with_existing(
            10,
            vec![2, 2, 2, 2]
        );

        let z: BaseN = (x - y.to_base(16).unwrap()).unwrap();

        //assert!(true);
        assert_eq!( expected, z );
    }

    #[test]
    fn test_eq_same_base() {

        let x: BaseN = BaseN::with_existing(
            16,
            vec![3, 3, 3, 3]
        );
        let y: BaseN = BaseN::with_existing(
            16,
            vec![3, 3, 3, 3]
        );

        assert_eq!( x==y, true );
    }

    #[test]
    fn test_eq_different_base() {

        let x: BaseN = BaseN::with_existing(
            10,
            vec![3, 3, 3, 3]
        );
        let y: BaseN = BaseN::with_existing(
            16,
            vec![5, 0, 13]
        );

        assert_eq!( x==y, true );

    }

    #[test]
    fn test_ne_same_base() {

        let x: BaseN = BaseN::with_existing(
            16,
            vec![3, 3, 3, 3]
        );
        let y: BaseN = BaseN::with_existing(
            16,
            vec![4, 4, 4, 4]
        );

        assert_eq!( x!=y, true );
    }

    #[test]
    fn test_ne_different_base() {

        let x: BaseN = BaseN::with_existing(
            10,
            vec![3, 3, 3, 3]
        );
        let y: BaseN = BaseN::with_existing(
            16,
            vec![6, 1, 14]
        );

        assert_eq!( x!=y, true );

    }

}
<|endoftext|>


<commit_before>extern crate tokio_core;
extern crate futures;
extern crate serde;

extern crate reqwest;
#[macro_use]
extern crate lazy_static;

extern crate influxdb;

use std::error::Error;
use std::sync::Mutex;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::thread;
use std::time::Duration;

use futures::Future;

use influxdb::{AsyncDb, AsyncUdpDb, QueryResponse, InfluxServerError};

const HTTP_BASE_URL: &'static str = "http://localhost:8086/";

const UDP_IP_AND_PORT: &'static str = "127.0.0.1:8089";
const UDP_DB_NAME: &'static str = "influxdb_rs_udp";
const UDP_BATCH_TIMEOUT_MS: u64 = 50;

#[test]
fn query_asynchronously() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();

    let response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HTTP_BASE_URL, &db.name).unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
    });

    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

#[test]
fn add_data_asynchronously() {
    let db = fresh_db();

    with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HTTP_BASE_URL, &db.name).unwrap();

        async_db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
    });

    let response: QueryResponse = db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#).unwrap();

    assert_eq!(response.results[0].error, None);
    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

#[test]
fn add_data_asynchronously_udp() {
    let test_db = with_udp_db(|async_db| {
        async_db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
    });

    thread::sleep(Duration::from_millis(2 * UDP_BATCH_TIMEOUT_MS));

    let response: QueryResponse = test_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#).unwrap();

    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

#[test]
#[ignore] // TODO: handle errors returned in the response instead of status code
fn query_nonexistent_db() {
    let response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HTTP_BASE_URL, "does_not_exist").unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
    });

    assert_eq!(response.results[0].error, Some(String::from("database not found: does_not_exist")));
}

#[test]
fn multiple_queries() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();
    db.add_data("cpu_load_short,host=server02,region=us-west value=0.8")
        .unwrap();
    db.add_data("cpu_load_short,host=server01,region=us-west value=0.4")
        .unwrap();

    let mut response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HTTP_BASE_URL, &db.name).unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'; SELECT "value" FROM "cpu_load_short" WHERE "host"='server01'"#)
    });

    response.results.sort_by_key(|k| k.statement_id);

    assert_eq!(response.results[0].statement_id, 0);
    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));

    assert_eq!(response.results[1].statement_id, 1);
    assert_eq!(response.results[1].series[0].name, "cpu_load_short");
    assert_eq!(response.results[1].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[1].series[0].values[1][1].as_f64(), Some(0.4));
}

#[test]
fn multiple_queries_to_nonexistent_database() {
    let response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HTTP_BASE_URL, "does_not_exist").unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'; SELECT "value" FROM "cpu_load_short" WHERE "host"='server01'"#)
    });

    assert_eq!(response.results.len(), 1);
    assert_eq!(response.results[0].statement_id, 0);
    assert_eq!(response.results[0].series.len(), 0);
    assert_eq!(response.results[0].error, Some(String::from("not executed")));
}

#[test]
fn test_infrastructure() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();

    let response: QueryResponse =
        db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
        .unwrap();

    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

fn fresh_db() -> TestingDb {
    static DB_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;

    let id = DB_COUNTER.fetch_add(1, Ordering::SeqCst);
    let name = format!("influxdb_rs_{}", id);
    fresh_db_named(name)
}

fn fresh_db_named<S>(name: S) -> TestingDb
    where S: Into<String>,
{
    let db = TestingDb::new(HTTP_BASE_URL, name)
        .expect("Unable to create test database");
    db.create_db()
        .expect("Unable to create test database");

    // The InfluxDB created isn't ready immediately; this prevents
    // intermittent failures.
    thread::sleep(Duration::from_millis(5));
    db
}

// The InfluxDB UDP ingestion matches one UDP port to one
// database. Since we aren't starting a server for each test, and we
// want each test to be isolated, we can only have one UDP test at a
// time.
fn with_udp_db<F, T>(f: F) -> TestingDb
    where F: FnOnce(AsyncUdpDb) -> T,
          T: Future,
          T::Error: std::fmt::Debug,
{
    lazy_static! {
        static ref MUTEX: Mutex<()> = Mutex::new(());
    }

    let _lock = MUTEX.lock().expect("Unable to lock for UDP test");
    let test_db = fresh_db_named(UDP_DB_NAME);

    with_core(|core| {
        let db = AsyncUdpDb::new(core.handle(), UDP_IP_AND_PORT)
            .expect("Unable to create UDP database");
        f(db)
    });

    test_db
}

fn with_core<F, T>(f: F) -> T::Item
    where F: FnOnce(&mut tokio_core::reactor::Core) -> T,
          T: Future,
          T::Error: std::fmt::Debug,
{
    let mut core = tokio_core::reactor::Core::new()
        .expect("Unable to create reactor core for testing");

    let future = f(&mut core);

    core.run(future).expect("Unable to run future to completion")
}

struct TestingDb {
    name: String,
    client: reqwest::Client,
    query_endpoint: reqwest::Url,
    write_endpoint: reqwest::Url,
}

impl TestingDb {
    /// `base_url` should include the protocol, host, and port (`http://localhost:8086`)
    fn new<S>(base_url: &str, name: S) -> Result<Self, Box<Error>>
        where S: Into<String>,
    {
        let name = name.into();

        let base_url = reqwest::Url::parse(base_url)?;
        let query_endpoint = base_url.join("/query")?;
        let mut write_endpoint = base_url.join("/write")?;
        write_endpoint.query_pairs_mut()
            .append_pair("db", &name);

        let client = reqwest::Client::new()?;

        Ok(TestingDb {
            name: name,
            client: client,
            query_endpoint: query_endpoint,
            write_endpoint: write_endpoint,
        })
    }

    fn create_db(&self) -> Result<(), Box<Error>> {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("q", &format!("CREATE DATABASE {}", self.name));
        let mut res = self.client.post(u).send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn drop_db(&self) -> Result<(), Box<Error>> {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("q", &format!("DROP DATABASE {}", self.name));
        let mut res = self.client.post(u).send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn add_data(&self, data: &str) -> Result<(), Box<Error>> {
        let mut res = self.client.post(self.write_endpoint.clone())
            .body(data)
            .send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn query<T>(&self, query: &str) -> Result<T, Box<Error>>
        where T: serde::Deserialize,
    {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("db", &self.name)
            .append_pair("q", query);
        let mut res = self.client.get(u).send()?;

        check_result(&mut res)?;
        let val = res.json()?;
        Ok(val)
    }
}

impl Drop for TestingDb {
    fn drop(&mut self) {
        // Influx does not care if we drop a database that doesn't exist
        self.drop_db().unwrap_or_else(|e| panic!("Unable to drop database {}: {}", self.name, e));
    }
}

fn check_result(res: &mut reqwest::Response) -> Result<(), Box<Error>> {
    let status = *res.status();

    if status.is_success() {
        Ok(())
    } else if status.is_client_error() {
        Err(parse_influx_server_error(res, "Client error").into())
    } else if status.is_server_error() {
        Err(parse_influx_server_error(res, "Server error").into())
    } else {
        Err(parse_influx_server_error(res, "Unknown error").into())
    }
}

fn parse_influx_server_error(res: &mut reqwest::Response, kind: &str) -> String {
    match res.json::<InfluxServerError>() {
        Ok(e) => format!("{}: {}", kind, e.error),
        Err(_) => format!("{}: (unable to parse error message)", kind),
    }
}
<commit_msg>Add a test for batched insert of lines<commit_after>extern crate tokio_core;
extern crate futures;
extern crate serde;

extern crate reqwest;
#[macro_use]
extern crate lazy_static;

extern crate influxdb;

use std::error::Error;
use std::sync::Mutex;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::thread;
use std::time::Duration;

use futures::Future;

use influxdb::{AsyncDb, AsyncUdpDb, QueryResponse, InfluxServerError};

const HTTP_BASE_URL: &'static str = "http://localhost:8086/";

const UDP_IP_AND_PORT: &'static str = "127.0.0.1:8089";
const UDP_DB_NAME: &'static str = "influxdb_rs_udp";
const UDP_BATCH_TIMEOUT_MS: u64 = 50;

#[test]
fn query_asynchronously() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();

    let response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HTTP_BASE_URL, &db.name).unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
    });

    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

#[test]
fn add_data_asynchronously() {
    let db = fresh_db();

    with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HTTP_BASE_URL, &db.name).unwrap();

        async_db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
    });

    let response: QueryResponse = db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#).unwrap();

    assert_eq!(response.results[0].error, None);
    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

#[test]
fn add_batched_data_asynchronously() {
    let db = fresh_db();

    with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HTTP_BASE_URL, &db.name).unwrap();

        async_db.add_data(r#"
cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000
cpu_load_short,host=server02,region=us-east value=0.23
cpu_load_short,host=server03,region=us-west value=0.01 1434055587000000000
rpm,host=server01,region=us-west value=1434"#)
    });

    let response: QueryResponse = db.query(r#"SELECT "value", "host" FROM "cpu_load_short""#).unwrap();

    assert_eq!(response.results[0].error, None);
    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values.len(), 3);
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

#[test]
fn add_data_asynchronously_udp() {
    let test_db = with_udp_db(|async_db| {
        async_db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
    });

    thread::sleep(Duration::from_millis(2 * UDP_BATCH_TIMEOUT_MS));

    let response: QueryResponse = test_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#).unwrap();

    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

#[test]
#[ignore] // TODO: handle errors returned in the response instead of status code
fn query_nonexistent_db() {
    let response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HTTP_BASE_URL, "does_not_exist").unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
    });

    assert_eq!(response.results[0].error, Some(String::from("database not found: does_not_exist")));
}

#[test]
fn multiple_queries() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();
    db.add_data("cpu_load_short,host=server02,region=us-west value=0.8")
        .unwrap();
    db.add_data("cpu_load_short,host=server01,region=us-west value=0.4")
        .unwrap();

    let mut response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HTTP_BASE_URL, &db.name).unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'; SELECT "value" FROM "cpu_load_short" WHERE "host"='server01'"#)
    });

    response.results.sort_by_key(|k| k.statement_id);

    assert_eq!(response.results[0].statement_id, 0);
    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));

    assert_eq!(response.results[1].statement_id, 1);
    assert_eq!(response.results[1].series[0].name, "cpu_load_short");
    assert_eq!(response.results[1].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[1].series[0].values[1][1].as_f64(), Some(0.4));
}

#[test]
fn multiple_queries_to_nonexistent_database() {
    let response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HTTP_BASE_URL, "does_not_exist").unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'; SELECT "value" FROM "cpu_load_short" WHERE "host"='server01'"#)
    });

    assert_eq!(response.results.len(), 1);
    assert_eq!(response.results[0].statement_id, 0);
    assert_eq!(response.results[0].series.len(), 0);
    assert_eq!(response.results[0].error, Some(String::from("not executed")));
}

#[test]
fn test_infrastructure() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();

    let response: QueryResponse =
        db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
        .unwrap();

    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

fn fresh_db() -> TestingDb {
    static DB_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;

    let id = DB_COUNTER.fetch_add(1, Ordering::SeqCst);
    let name = format!("influxdb_rs_{}", id);
    fresh_db_named(name)
}

fn fresh_db_named<S>(name: S) -> TestingDb
    where S: Into<String>,
{
    let db = TestingDb::new(HTTP_BASE_URL, name)
        .expect("Unable to create test database");
    db.create_db()
        .expect("Unable to create test database");

    // The InfluxDB created isn't ready immediately; this prevents
    // intermittent failures.
    thread::sleep(Duration::from_millis(5));
    db
}

// The InfluxDB UDP ingestion matches one UDP port to one
// database. Since we aren't starting a server for each test, and we
// want each test to be isolated, we can only have one UDP test at a
// time.
fn with_udp_db<F, T>(f: F) -> TestingDb
    where F: FnOnce(AsyncUdpDb) -> T,
          T: Future,
          T::Error: std::fmt::Debug,
{
    lazy_static! {
        static ref MUTEX: Mutex<()> = Mutex::new(());
    }

    let _lock = MUTEX.lock().expect("Unable to lock for UDP test");
    let test_db = fresh_db_named(UDP_DB_NAME);

    with_core(|core| {
        let db = AsyncUdpDb::new(core.handle(), UDP_IP_AND_PORT)
            .expect("Unable to create UDP database");
        f(db)
    });

    test_db
}

fn with_core<F, T>(f: F) -> T::Item
    where F: FnOnce(&mut tokio_core::reactor::Core) -> T,
          T: Future,
          T::Error: std::fmt::Debug,
{
    let mut core = tokio_core::reactor::Core::new()
        .expect("Unable to create reactor core for testing");

    let future = f(&mut core);

    core.run(future).expect("Unable to run future to completion")
}

struct TestingDb {
    name: String,
    client: reqwest::Client,
    query_endpoint: reqwest::Url,
    write_endpoint: reqwest::Url,
}

impl TestingDb {
    /// `base_url` should include the protocol, host, and port (`http://localhost:8086`)
    fn new<S>(base_url: &str, name: S) -> Result<Self, Box<Error>>
        where S: Into<String>,
    {
        let name = name.into();

        let base_url = reqwest::Url::parse(base_url)?;
        let query_endpoint = base_url.join("/query")?;
        let mut write_endpoint = base_url.join("/write")?;
        write_endpoint.query_pairs_mut()
            .append_pair("db", &name);

        let client = reqwest::Client::new()?;

        Ok(TestingDb {
            name: name,
            client: client,
            query_endpoint: query_endpoint,
            write_endpoint: write_endpoint,
        })
    }

    fn create_db(&self) -> Result<(), Box<Error>> {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("q", &format!("CREATE DATABASE {}", self.name));
        let mut res = self.client.post(u).send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn drop_db(&self) -> Result<(), Box<Error>> {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("q", &format!("DROP DATABASE {}", self.name));
        let mut res = self.client.post(u).send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn add_data(&self, data: &str) -> Result<(), Box<Error>> {
        let mut res = self.client.post(self.write_endpoint.clone())
            .body(data)
            .send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn query<T>(&self, query: &str) -> Result<T, Box<Error>>
        where T: serde::Deserialize,
    {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("db", &self.name)
            .append_pair("q", query);
        let mut res = self.client.get(u).send()?;

        check_result(&mut res)?;
        let val = res.json()?;
        Ok(val)
    }
}

impl Drop for TestingDb {
    fn drop(&mut self) {
        // Influx does not care if we drop a database that doesn't exist
        self.drop_db().unwrap_or_else(|e| panic!("Unable to drop database {}: {}", self.name, e));
    }
}

fn check_result(res: &mut reqwest::Response) -> Result<(), Box<Error>> {
    let status = *res.status();

    if status.is_success() {
        Ok(())
    } else if status.is_client_error() {
        Err(parse_influx_server_error(res, "Client error").into())
    } else if status.is_server_error() {
        Err(parse_influx_server_error(res, "Server error").into())
    } else {
        Err(parse_influx_server_error(res, "Unknown error").into())
    }
}

fn parse_influx_server_error(res: &mut reqwest::Response, kind: &str) -> String {
    match res.json::<InfluxServerError>() {
        Ok(e) => format!("{}: {}", kind, e.error),
        Err(_) => format!("{}: (unable to parse error message)", kind),
    }
}
<|endoftext|>


<commit_before>// rustfmt-indent_style: Block

// #1357
impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB>
    for SelectStatement<Select, From, Distinct, Where, Order, Limit, Offset, GroupBy>
where
    DB: Backend,
    Select: QueryFragment<DB> + SelectableExpression<From> + 'a,
    Distinct: QueryFragment<DB> + 'a,
    Where: Into<Option<Box<QueryFragment<DB> + 'a>>>,
    Order: QueryFragment<DB> + 'a,
    Limit: QueryFragment<DB> + 'a,
    Offset: QueryFragment<DB> + 'a,
{
    type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>;

    fn internal_into_boxed(self) -> Self::Output {
        BoxedSelectStatement::new(
            Box::new(self.select),
            self.from,
            Box::new(self.distinct),
            self.where_clause.into(),
            Box::new(self.order),
            Box::new(self.limit),
            Box::new(self.offset),
        )
    }
}

// #1369
impl<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName> Foo
    for Bar {
    fn foo() {}
}
impl Foo<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName>
    for Bar {
    fn foo() {}
}
impl<
    ExcessivelyLongGenericName,
    ExcessivelyLongGenericName,
    AnotherExcessivelyLongGenericName,
> Foo<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName>
    for Bar {
    fn foo() {}
}
impl<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName> Foo
    for Bar<
        ExcessivelyLongGenericName,
        ExcessivelyLongGenericName,
        AnotherExcessivelyLongGenericName,
    > {
    fn foo() {}
}
impl Foo<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName>
    for Bar<
        ExcessivelyLongGenericName,
        ExcessivelyLongGenericName,
        AnotherExcessivelyLongGenericName,
    > {
    fn foo() {}
}
impl<
    ExcessivelyLongGenericName,
    ExcessivelyLongGenericName,
    AnotherExcessivelyLongGenericName,
> Foo<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName>
    for Bar<
        ExcessivelyLongGenericName,
        ExcessivelyLongGenericName,
        AnotherExcessivelyLongGenericName,
    > {
    fn foo() {}
}

// #1689
impl<M, S, F, X> SubSelectDirect<M, S, F, X>
where
    M: select::Selector,
    S: event::Stream,
    F: for<'t> FnMut(transform::Api<'t, Stream<ContentStream<S>>>)
        -> transform::Api<'t, X>,
    X: event::Stream,
{
}
<commit_msg>Update a test<commit_after>// rustfmt-indent_style: Block

// #1357
impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB>
    for SelectStatement<Select, From, Distinct, Where, Order, Limit, Offset, GroupBy>
where
    DB: Backend,
    Select: QueryFragment<DB> + SelectableExpression<From> + 'a,
    Distinct: QueryFragment<DB> + 'a,
    Where: Into<Option<Box<QueryFragment<DB> + 'a>>>,
    Order: QueryFragment<DB> + 'a,
    Limit: QueryFragment<DB> + 'a,
    Offset: QueryFragment<DB> + 'a,
{
    type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>;

    fn internal_into_boxed(self) -> Self::Output {
        BoxedSelectStatement::new(
            Box::new(self.select),
            self.from,
            Box::new(self.distinct),
            self.where_clause.into(),
            Box::new(self.order),
            Box::new(self.limit),
            Box::new(self.offset),
        )
    }
}

// #1369
impl<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName> Foo
    for Bar {
    fn foo() {}
}
impl Foo<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName>
    for Bar {
    fn foo() {}
}
impl<
    ExcessivelyLongGenericName,
    ExcessivelyLongGenericName,
    AnotherExcessivelyLongGenericName,
> Foo<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName>
    for Bar {
    fn foo() {}
}
impl<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName> Foo
    for Bar<
        ExcessivelyLongGenericName,
        ExcessivelyLongGenericName,
        AnotherExcessivelyLongGenericName,
    > {
    fn foo() {}
}
impl Foo<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName>
    for Bar<
        ExcessivelyLongGenericName,
        ExcessivelyLongGenericName,
        AnotherExcessivelyLongGenericName,
    > {
    fn foo() {}
}
impl<
    ExcessivelyLongGenericName,
    ExcessivelyLongGenericName,
    AnotherExcessivelyLongGenericName,
> Foo<ExcessivelyLongGenericName, ExcessivelyLongGenericName, AnotherExcessivelyLongGenericName>
    for Bar<
        ExcessivelyLongGenericName,
        ExcessivelyLongGenericName,
        AnotherExcessivelyLongGenericName,
    > {
    fn foo() {}
}

// #1689
impl<M, S, F, X> SubSelectDirect<M, S, F, X>
where
    M: select::Selector,
    S: event::Stream,
    F: for<'t> FnMut(transform::Api<'t, Stream<ContentStream<S>>>) -> transform::Api<'t, X>,
    X: event::Stream,
{
}
<|endoftext|>


<commit_before>use crate::*;
use rustc_target::abi::{Align, Size};

/// Implementation of the SYS_futex syscall.
pub fn futex<'tcx>(
    this: &mut MiriEvalContext<'_, 'tcx>,
    args: &[OpTy<'tcx, Tag>],
    dest: PlaceTy<'tcx, Tag>,
) -> InterpResult<'tcx> {
    // The amount of arguments used depends on the type of futex operation.
    // Some users always pass all arguments, even the unused ones, due to how they wrap this syscall in their code base.
    // Some other users pass only the arguments the operation actually needs. So we don't use `check_arg_count` here.
    if !(4..=7).contains(&args.len()) {
        throw_ub_format!("incorrect number of arguments for futex syscall: got {}, expected between 4 and 7 (inclusive)", args.len());
    }

    // The first three arguments (after the syscall number itself) are the same to all futex operations:
    //     (int *addr, int op, int val).
    // Although note that the first one is often passed as a different pointer type, e.g. `*const AtomicU32` or `*mut u32`.
    let addr = this.deref_operand(args[1])?;
    let op = this.read_scalar(args[2])?.to_i32()?;
    let val = this.read_scalar(args[3])?.to_i32()?;

    // The raw pointer value is used to identify the mutex.
    // Not all mutex operations actually read from this address or even require this address to exist.
    let futex_ptr = addr.ptr.assert_ptr();

    let thread = this.get_active_thread();

    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
    let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
    let futex_wake = this.eval_libc_i32("FUTEX_WAKE")?;

    match op & !futex_private {
        op if op == futex_wait => {
            if args.len() < 5 {
                throw_ub_format!("incorrect number of arguments for FUTEX_WAIT syscall: got {}, expected at least 5", args.len());
            }
            let timeout = this.read_scalar(args[4])?.check_init()?;
            if !this.is_null(timeout)? {
                throw_ub_format!("miri does not support timeouts for futex operations");
            }
            // Check the pointer for alignment. Atomic operations are only available for fully aligned values.
            this.memory.check_ptr_access(addr.ptr.into(), Size::from_bytes(4), Align::from_bytes(4).unwrap())?;
            // Read an `i32` through the pointer, regardless of any wrapper types (e.g. `AtomicI32`).
            let futex_val = this.read_scalar(addr.offset(Size::ZERO, MemPlaceMeta::None, this.machine.layouts.i32, this)?.into())?.to_i32()?;
            if val == futex_val {
                this.block_thread(thread);
                this.futex_wait(futex_ptr, thread);
                this.write_scalar(Scalar::from_i32(0), dest)?;
            } else {
                let eagain = this.eval_libc("EAGAIN")?;
                this.set_last_error(eagain)?;
                this.write_scalar(Scalar::from_i32(-1), dest)?;
            }
        }
        op if op == futex_wake => {
            let mut n = 0;
            for _ in 0..val {
                if let Some(thread) = this.futex_wake(futex_ptr) {
                    this.unblock_thread(thread);
                    n += 1;
                } else {
                    break;
                }
            }
            this.write_scalar(Scalar::from_i32(n), dest)?;
        }
        op => throw_unsup_format!("miri does not support SYS_futex operation {}", op),
    }

    Ok(())
}
<commit_msg>Add comments that document SYS_futex better.<commit_after>use crate::*;
use rustc_target::abi::{Align, Size};

/// Implementation of the SYS_futex syscall.
pub fn futex<'tcx>(
    this: &mut MiriEvalContext<'_, 'tcx>,
    args: &[OpTy<'tcx, Tag>],
    dest: PlaceTy<'tcx, Tag>,
) -> InterpResult<'tcx> {
    // The amount of arguments used depends on the type of futex operation.
    // Some users always pass all arguments, even the unused ones, due to how they wrap this syscall in their code base.
    // Some other users pass only the arguments the operation actually needs. So we don't use `check_arg_count` here.
    if !(4..=7).contains(&args.len()) {
        throw_ub_format!("incorrect number of arguments for futex syscall: got {}, expected between 4 and 7 (inclusive)", args.len());
    }

    // The first three arguments (after the syscall number itself) are the same to all futex operations:
    //     (int *addr, int op, int val).
    // Although note that the first one is often passed as a different pointer type, e.g. `*const AtomicU32` or `*mut u32`.
    let addr = this.deref_operand(args[1])?;
    let op = this.read_scalar(args[2])?.to_i32()?;
    let val = this.read_scalar(args[3])?.to_i32()?;

    // The raw pointer value is used to identify the mutex.
    // Not all mutex operations actually read from this address or even require this address to exist.
    let futex_ptr = addr.ptr.assert_ptr();

    let thread = this.get_active_thread();

    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
    let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
    let futex_wake = this.eval_libc_i32("FUTEX_WAKE")?;

    // FUTEX_PRIVATE enables an optimization that stops it from working across processes.
    // Miri doesn't support that anyway, so we ignore that flag.
    match op & !futex_private {
        // FUTEX_WAIT: (int *addr, int op = FUTEX_WAIT, int val, const timespec *timeout)
        // Blocks the thread if *addr still equals val. Wakes up when FUTEX_WAKE is called on the same address,
        // or *timeout expires. `timeout == null` for an infinite timeout.
        op if op == futex_wait => {
            if args.len() < 5 {
                throw_ub_format!("incorrect number of arguments for FUTEX_WAIT syscall: got {}, expected at least 5", args.len());
            }
            let timeout = this.read_scalar(args[4])?.check_init()?;
            if !this.is_null(timeout)? {
                // FIXME: Implement timeouts. The condvar waiting code is probably a good example to start with.
                // Note that a triggered timeout should have this syscall return with -1 and errno set to ETIMEOUT.
                throw_ub_format!("miri does not support timeouts for futex operations");
            }
            // Check the pointer for alignment. Atomic operations are only available for fully aligned values.
            this.memory.check_ptr_access(addr.ptr.into(), Size::from_bytes(4), Align::from_bytes(4).unwrap())?;
            // Read an `i32` through the pointer, regardless of any wrapper types (e.g. `AtomicI32`).
            let futex_val = this.read_scalar(addr.offset(Size::ZERO, MemPlaceMeta::None, this.machine.layouts.i32, this)?.into())?.to_i32()?;
            if val == futex_val {
                // The value still matches, so we block the trait make it wait for FUTEX_WAKE.
                this.block_thread(thread);
                this.futex_wait(futex_ptr, thread);
                // Succesfully waking up from FUTEX_WAIT always returns zero.
                this.write_scalar(Scalar::from_i32(0), dest)?;
            } else {
                // The futex value doesn't match the expected value, so we return failure
                // right away without sleeping: -1 and errno set to EAGAIN.
                let eagain = this.eval_libc("EAGAIN")?;
                this.set_last_error(eagain)?;
                this.write_scalar(Scalar::from_i32(-1), dest)?;
            }
        }
        // FUTEX_WAKE: (int *addr, int op = FUTEX_WAKE, int val)
        // Wakes at most `val` threads waiting on the futex at `addr`.
        // Returns the amount of threads woken up.
        // Does not access the futex value at *addr.
        op if op == futex_wake => {
            let mut n = 0;
            for _ in 0..val {
                if let Some(thread) = this.futex_wake(futex_ptr) {
                    this.unblock_thread(thread);
                    n += 1;
                } else {
                    break;
                }
            }
            this.write_scalar(Scalar::from_i32(n), dest)?;
        }
        op => throw_unsup_format!("miri does not support SYS_futex operation {}", op),
    }

    Ok(())
}
<|endoftext|>


<commit_before>use graphics::*;

// Local crate.
use Vector2d = vector2d::Vector2d;

static EPSILON: f64 = 0.0000000001;

pub fn area(contour: &[Vector2d]) -> f64 {
    let n = contour.len();
    let mut A = 0.0_f64;

    for i in range(0, n) {
        let q = i;
        let p = (i + n - 1) % n;
        A += contour.get(p).unwrap().get_x() * contour.get(q).unwrap().get_y()
            - contour.get(q).unwrap().get_x() * contour.get(p).unwrap().get_y();
    }

    A * 0.5_f64
}

/// InsideTriangle decides if a point P is Inside of the triangle
/// defined by A, B, C.
pub fn inside_triangle(
    Ax: f64, Ay: f64,
    Bx: f64, By: f64,
    Cx: f64, Cy: f64,
    Px: f64, Py: f64
) -> bool {

    let ax = Cx - Bx;
    let ay = Cy - By;
    let bx = Ax - Cx;
    let by = Ay - Cy;
    let cx = Bx - Ax;
    let cy = By - Ay;
    let apx = Px - Ax;
    let apy = Py - Ay;
    let bpx = Px - Bx;
    let bpy = Py - By;
    let cpx = Px - Cx;
    let cpy = Py - Cy;

    let aCROSSbp = ax*bpy - ay*bpx;
    let cCROSSap = cx*apy - cy*apx;
    let bCROSScp = bx*cpy - by*cpx;

    (
        (aCROSSbp >= 0.0_f64)
        && (bCROSScp >= 0.0_f64)
        && (cCROSSap >= 0.0_f64)
    )
}

pub fn snip(
    contour: &[Vector2d],
    triangle: [uint, ..3],
    n: uint,
    vertex_indices: &Vec<uint>
) -> bool {
    let (u, v, w) = (triangle[0], triangle[1], triangle[2]);

    let A = contour.get(*vertex_indices.get(u)).unwrap();
    let B = contour.get(*vertex_indices.get(v)).unwrap();
    let C = contour.get(*vertex_indices.get(w)).unwrap();

    let (Ax, Ay) = (A.get_x(), A.get_y());
    let (Bx, By) = (B.get_x(), B.get_y());
    let (Cx, Cy) = (C.get_x(), C.get_y());

    if EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) {
        return false;
    }

    for p in range(0, n) {
        // Do not check for any of the vertices in the triangle.
        if (p == u) || (p == v) || (p == w) { continue; }

        let Px = contour.get(*vertex_indices.get(p)).unwrap().get_x();
        let Py = contour.get(*vertex_indices.get(p)).unwrap().get_y();

        if inside_triangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py) { return false; }
    }

    return true;
}

pub fn process(
    contour: &[Vector2d]
) -> Option<Vec<Vector2d>> {
    /* allocate and initialize list of Vertices in polygon */

    let n = contour.len();
    if n < 3 { return None; }

    let mut result: Vec<Vector2d> = Vec::new();
    let mut vertex_indices: Vec<uint> = Vec::with_capacity(n);

    /* we want a counter-clockwise polygon in V */

    // Computes the area which has opposite signs
    // whether the polygon is clock-wise or counter-clockwise.
    if 0.0_f64 < area(contour) {
        for v in range(0, n) { vertex_indices.push(v); }
    } else {
        // Add indices in reverse order.
        for v in range(0, n) { vertex_indices.push((n-1)-v); }
    }

    // Stores the number of vertices.
    // Used instead of `vertex_indices.len()` to emulate removing of vertices.
    let mut number_of_vertices = n;

    /*  remove nv-2 Vertices, creating 1 triangle every time */

    // Used for error detection.
    let mut count = 2 * number_of_vertices;

    let mut v = number_of_vertices - 1;
    while number_of_vertices > 2 {
        /* if we loop, it is probably a non-simple polygon */
        if count <= 0 {
            //** Triangulate: ERROR - probable bad polygon!
            return None;
        }

        count -= 1;

        /* three consecutive vertices in current polygon, <u,v,w> */
        let triangle = [
            v,
            vecmath::modular_offset_index(number_of_vertices, v, 1),
            vecmath::modular_offset_index(number_of_vertices, v, 2)
        ];
        v = triangle[1];

        if snip(contour, triangle, number_of_vertices, &mut vertex_indices) {
            for &i in triangle.iter() {
                result.push(*contour.get(*vertex_indices.get(i)).unwrap());
            }

            /* remove v from remaining polygon */
            for i in range(0, number_of_vertices - 3) {
                let s = v + i;
                let t = v + i + 1;

                *vertex_indices.get_mut(s) = *vertex_indices.get(t);
            }

            // "Removed" a vertex.
            number_of_vertices -= 1;

            /* resest error detection counter */
            count = 2 * number_of_vertices;
        }
    }

    Some(result)
}

<commit_msg>Simplified code<commit_after>use graphics::*;

// Local crate.
use Vector2d = vector2d::Vector2d;

static EPSILON: f64 = 0.0000000001;

pub fn area(contour: &[Vector2d]) -> f64 {
    let n = contour.len();
    let mut A = 0.0_f64;

    for i in range(0, n) {
        let q = i;
        let p = (i + n - 1) % n;
        A += contour.get(p).unwrap().get_x() * contour.get(q).unwrap().get_y()
            - contour.get(q).unwrap().get_x() * contour.get(p).unwrap().get_y();
    }

    A * 0.5_f64
}

/// InsideTriangle decides if a point P is Inside of the triangle
/// defined by A, B, C.
pub fn inside_triangle(
    Ax: f64, Ay: f64,
    Bx: f64, By: f64,
    Cx: f64, Cy: f64,
    Px: f64, Py: f64
) -> bool {

    let ax = Cx - Bx;
    let ay = Cy - By;
    let bx = Ax - Cx;
    let by = Ay - Cy;
    let cx = Bx - Ax;
    let cy = By - Ay;
    let apx = Px - Ax;
    let apy = Py - Ay;
    let bpx = Px - Bx;
    let bpy = Py - By;
    let cpx = Px - Cx;
    let cpy = Py - Cy;

    let aCROSSbp = ax*bpy - ay*bpx;
    let cCROSSap = cx*apy - cy*apx;
    let bCROSScp = bx*cpy - by*cpx;

    (
        (aCROSSbp >= 0.0_f64)
        && (bCROSScp >= 0.0_f64)
        && (cCROSSap >= 0.0_f64)
    )
}

pub fn snip(
    contour: &[Vector2d],
    triangle: [uint, ..3],
    n: uint,
    vertex_indices: &Vec<uint>
) -> bool {
    let (u, v, w) = (triangle[0], triangle[1], triangle[2]);

    let A = contour.get(*vertex_indices.get(u)).unwrap();
    let B = contour.get(*vertex_indices.get(v)).unwrap();
    let C = contour.get(*vertex_indices.get(w)).unwrap();

    let (Ax, Ay) = (A.get_x(), A.get_y());
    let (Bx, By) = (B.get_x(), B.get_y());
    let (Cx, Cy) = (C.get_x(), C.get_y());

    if EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) {
        return false;
    }

    for p in range(0, n) {
        // Do not check for any of the vertices in the triangle.
        if (p == u) || (p == v) || (p == w) { continue; }

        let P = contour.get(*vertex_indices.get(p)).unwrap();
        if inside_triangle(Ax,Ay,Bx,By,Cx,Cy,P.get_x(),P.get_y()) { return false; }
    }

    return true;
}

pub fn process(
    contour: &[Vector2d]
) -> Option<Vec<Vector2d>> {
    /* allocate and initialize list of Vertices in polygon */

    let n = contour.len();
    if n < 3 { return None; }

    let mut result: Vec<Vector2d> = Vec::new();
    let mut vertex_indices: Vec<uint> = Vec::with_capacity(n);

    /* we want a counter-clockwise polygon in V */

    // Computes the area which has opposite signs
    // whether the polygon is clock-wise or counter-clockwise.
    if 0.0_f64 < area(contour) {
        for v in range(0, n) { vertex_indices.push(v); }
    } else {
        // Add indices in reverse order.
        for v in range(0, n) { vertex_indices.push((n-1)-v); }
    }

    // Stores the number of vertices.
    // Used instead of `vertex_indices.len()` to emulate removing of vertices.
    let mut number_of_vertices = n;

    /*  remove nv-2 Vertices, creating 1 triangle every time */

    // Used for error detection.
    let mut count = 2 * number_of_vertices;

    let mut v = number_of_vertices - 1;
    while number_of_vertices > 2 {
        /* if we loop, it is probably a non-simple polygon */
        if count <= 0 {
            //** Triangulate: ERROR - probable bad polygon!
            return None;
        }

        count -= 1;

        /* three consecutive vertices in current polygon, <u,v,w> */
        let triangle = [
            v,
            vecmath::modular_offset_index(number_of_vertices, v, 1),
            vecmath::modular_offset_index(number_of_vertices, v, 2)
        ];
        v = triangle[1];

        if snip(contour, triangle, number_of_vertices, &mut vertex_indices) {
            for &i in triangle.iter() {
                result.push(*contour.get(*vertex_indices.get(i)).unwrap());
            }

            /* remove v from remaining polygon */
            for i in range(0, number_of_vertices - 3) {
                let s = v + i;
                let t = v + i + 1;

                *vertex_indices.get_mut(s) = *vertex_indices.get(t);
            }

            // "Removed" a vertex.
            number_of_vertices -= 1;

            /* resest error detection counter */
            count = 2 * number_of_vertices;
        }
    }

    Some(result)
}

<|endoftext|>


<commit_before>use crate::loom::{
    sync::atomic::{AtomicPtr, AtomicUsize},
    sync::CausalCell,
    thread,
};
use std::mem::{self, ManuallyDrop};
use std::ops;
use std::ptr::{self, NonNull};
use std::sync::atomic::Ordering::{self, AcqRel, Acquire, Release};

/// A block in a linked list.
///
/// Each block in the list can hold up to `BLOCK_CAP` messages.
pub(crate) struct Block<T> {
    /// The start index of this block.
    ///
    /// Slots in this block have indices in `start_index .. start_index + BLOCK_CAP`.
    start_index: usize,

    /// The next block in the linked list.
    next: AtomicPtr<Block<T>>,

    /// Bitfield tracking slots that are ready to have their values consumed.
    ready_slots: AtomicUsize,

    /// The observed `tail_position` value *after* the block has been passed by
    /// `block_tail`.
    observed_tail_position: CausalCell<usize>,

    /// Array containing values pushed into the block. Values are stored in a
    /// continuous array in order to improve cache line behavior when reading.
    /// The values must be manually dropped.
    values: Values<T>,
}

pub(crate) enum Read<T> {
    Value(T),
    Closed,
}

struct Values<T>([CausalCell<ManuallyDrop<T>>; BLOCK_CAP]);

use super::BLOCK_CAP;

/// Masks an index to get the block identifier
const BLOCK_MASK: usize = !(BLOCK_CAP - 1);

/// Masks an index to get the value offset in a block.
const SLOT_MASK: usize = BLOCK_CAP - 1;

/// Flag tracking that a block has gone through the sender's release routine.
///
/// When this is set, the receiver may consider freeing the block.
const RELEASED: usize = 1 << BLOCK_CAP;

/// Flag tracking all senders dropped.
///
/// When this flag is set, the send half of the channel has closed.
const TX_CLOSED: usize = RELEASED << 1;

/// Mask covering all bits used to track slot readiness.
const READY_MASK: usize = RELEASED - 1;

/// Returns the index of the first slot in the block referenced by `slot_index`.
#[inline(always)]
pub(crate) fn start_index(slot_index: usize) -> usize {
    BLOCK_MASK & slot_index
}

/// Returns the offset into the block referenced by `slot_index`.
#[inline(always)]
pub(crate) fn offset(slot_index: usize) -> usize {
    SLOT_MASK & slot_index
}

impl<T> Block<T> {
    pub(crate) fn new(start_index: usize) -> Block<T> {
        Block {
            // The absolute index in the channel of the first slot in the block.
            start_index,

            // Pointer to the next block in the linked list.
            next: AtomicPtr::new(ptr::null_mut()),

            ready_slots: AtomicUsize::new(0),

            observed_tail_position: CausalCell::new(0),

            // Value storage
            values: unsafe { Values::uninitialized() },
        }
    }

    /// Returns `true` if the block matches the given index
    pub(crate) fn is_at_index(&self, index: usize) -> bool {
        debug_assert!(offset(index) == 0);
        self.start_index == index
    }

    /// Returns the number of blocks between `self` and the block at the
    /// specified index.
    ///
    /// `start_index` must represent a block *after* `self`.
    pub(crate) fn distance(&self, other_index: usize) -> usize {
        debug_assert!(offset(other_index) == 0);
        other_index.wrapping_sub(self.start_index) / BLOCK_CAP
    }

    /// Read the value at the given offset.
    ///
    /// Returns `None` if the slot is empty.
    ///
    /// # Safety
    ///
    /// To maintain safety, the caller must ensure:
    ///
    /// * No concurrent access to the slot.
    pub(crate) unsafe fn read(&self, slot_index: usize) -> Option<Read<T>> {
        let offset = offset(slot_index);

        let ready_bits = self.ready_slots.load(Acquire);

        if !is_ready(ready_bits, offset) {
            if is_tx_closed(ready_bits) {
                return Some(Read::Closed);
            }

            return None;
        }

        // Get the value
        let value = self.values[offset].with(|ptr| ptr::read(ptr));

        Some(Read::Value(ManuallyDrop::into_inner(value)))
    }

    /// Write a value to the block at the given offset.
    ///
    /// # Safety
    ///
    /// To maintain safety, the caller must ensure:
    ///
    /// * The slot is empty.
    /// * No concurrent access to the slot.
    pub(crate) unsafe fn write(&self, slot_index: usize, value: T) {
        // Get the offset into the block
        let slot_offset = offset(slot_index);

        self.values[slot_offset].with_mut(|ptr| {
            ptr::write(ptr, ManuallyDrop::new(value));
        });

        // Release the value. After this point, the slot ref may no longer
        // be used. It is possible for the receiver to free the memory at
        // any point.
        self.set_ready(slot_offset);
    }

    /// Signal to the receiver that the sender half of the list is closed.
    pub(crate) unsafe fn tx_close(&self) {
        self.ready_slots.fetch_or(TX_CLOSED, Release);
    }

    /// Reset the block to a blank state. This enables reusing blocks in the
    /// channel.
    ///
    /// # Safety
    ///
    /// To maintain safety, the caller must ensure:
    ///
    /// * All slots are empty.
    /// * The caller holds a unique pointer to the block.
    pub(crate) unsafe fn reclaim(&mut self) {
        self.start_index = 0;
        self.next = AtomicPtr::new(ptr::null_mut());
        self.ready_slots = AtomicUsize::new(0);
    }

    /// Release the block to the rx half for freeing.
    ///
    /// This function is called by the tx half once it can be guaranteed that no
    /// more senders will attempt to access the block.
    ///
    /// # Safety
    ///
    /// To maintain safety, the caller must ensure:
    ///
    /// * The block will no longer be accessed by any sender.
    pub(crate) unsafe fn tx_release(&self, tail_position: usize) {
        // Track the observed tail_position. Any sender targetting a greater
        // tail_position is guaranteed to not access this block.
        self.observed_tail_position
            .with_mut(|ptr| *ptr = tail_position);

        // Set the released bit, signalling to the receiver that it is safe to
        // free the block's memory as soon as all slots **prior** to
        // `observed_tail_position` have been filled.
        self.ready_slots.fetch_or(RELEASED, Release);
    }

    /// Mark a slot as ready
    fn set_ready(&self, slot: usize) {
        let mask = 1 << slot;
        self.ready_slots.fetch_or(mask, Release);
    }

    /// Returns `true` when all slots have their `ready` bits set.
    ///
    /// This indicates that the block is in its final state and will no longer
    /// be mutated.
    ///
    /// # Implementation
    ///
    /// The implementation walks each slot checking the `ready` flag. It might
    /// be that it would make more sense to coalesce ready flags as bits in a
    /// single atomic cell. However, this could have negative impact on cache
    /// behavior as there would be many more mutations to a single slot.
    pub(crate) fn is_final(&self) -> bool {
        self.ready_slots.load(Acquire) & READY_MASK == READY_MASK
    }

    /// Returns the `observed_tail_position` value, if set
    pub(crate) fn observed_tail_position(&self) -> Option<usize> {
        if 0 == RELEASED & self.ready_slots.load(Acquire) {
            None
        } else {
            Some(self.observed_tail_position.with(|ptr| unsafe { *ptr }))
        }
    }

    /// Load the next block
    pub(crate) fn load_next(&self, ordering: Ordering) -> Option<NonNull<Block<T>>> {
        let ret = NonNull::new(self.next.load(ordering));

        debug_assert!(unsafe {
            ret.map(|block| block.as_ref().start_index == self.start_index.wrapping_add(BLOCK_CAP))
                .unwrap_or(true)
        });

        ret
    }

    /// Push `block` as the next block in the link.
    ///
    /// Returns Ok if successful, otherwise, a pointer to the next block in
    /// the list is returned.
    ///
    /// This requires that the next pointer is null.
    ///
    /// # Ordering
    ///
    /// This performs a compare-and-swap on `next` using AcqRel ordering.
    ///
    /// # Safety
    ///
    /// To maintain safety, the caller must ensure:
    ///
    /// * `block` is not freed until it has been removed from the list.
    pub(crate) unsafe fn try_push(
        &self,
        block: &mut NonNull<Block<T>>,
        ordering: Ordering,
    ) -> Result<(), NonNull<Block<T>>> {
        block.as_mut().start_index = self.start_index.wrapping_add(BLOCK_CAP);

        let next_ptr = self
            .next
            .compare_and_swap(ptr::null_mut(), block.as_ptr(), ordering);

        match NonNull::new(next_ptr) {
            Some(next_ptr) => Err(next_ptr),
            None => Ok(()),
        }
    }

    /// Grow the `Block` linked list by allocating and appending a new block.
    ///
    /// The next block in the linked list is returned. This may or may not be
    /// the one allocated by the function call.
    ///
    /// # Implementation
    ///
    /// It is assumed that `self.next` is null. A new block is allocated with
    /// `start_index` set to be the next block. A compare-and-swap is performed
    /// with AcqRel memory ordering. If the compare-and-swap is successful, the
    /// newly allocated block is released to other threads walking the block
    /// linked list. If the compare-and-swap fails, the current thread acquires
    /// the next block in the linked list, allowing the current thread to access
    /// the slots.
    pub(crate) fn grow(&self) -> NonNull<Block<T>> {
        // Create the new block. It is assumed that the block will become the
        // next one after `&self`. If this turns out to not be the case,
        // `start_index` is updated accordingly.
        let new_block = Box::new(Block::new(self.start_index + BLOCK_CAP));

        let mut new_block = unsafe { NonNull::new_unchecked(Box::into_raw(new_block)) };

        // Attempt to store the block. The first compare-and-swap attempt is
        // "unrolled" due to minor differences in logic
        //
        // `AcqRel` is used as the ordering **only** when attempting the
        // compare-and-swap on self.next.
        //
        // If the compare-and-swap fails, then the actual value of the cell is
        // returned from this function and accessed by the caller. Given this,
        // the memory must be acquired.
        //
        // `Release` ensures that the newly allocated block is available to
        // other threads acquiring the next pointer.
        let next = NonNull::new(self.next.compare_and_swap(
            ptr::null_mut(),
            new_block.as_ptr(),
            AcqRel,
        ));

        let next = match next {
            Some(next) => next,
            None => {
                // The compare-and-swap succeeded and the newly allocated block
                // is successfully pushed.
                return new_block;
            }
        };

        // There already is a next block in the linked list. The newly allocated
        // block could be dropped and the discovered next block returned;
        // however, that would be wasteful. Instead, the linked list is walked
        // by repeatedly attempting to compare-and-swap the pointer into the
        // `next` register until the compare-and-swap succeed.
        //
        // Care is taken to update new_block's start_index field as appropriate.

        let mut curr = next;

        // TODO: Should this iteration be capped?
        loop {
            let actual = unsafe { curr.as_ref().try_push(&mut new_block, AcqRel) };

            curr = match actual {
                Ok(_) => {
                    return next;
                }
                Err(curr) => curr,
            };

            // When running outside of loom, this calls `spin_loop_hint`.
            thread::yield_now();
        }
    }
}

/// Returns `true` if the specificed slot has a value ready to be consumed.
fn is_ready(bits: usize, slot: usize) -> bool {
    let mask = 1 << slot;
    mask == mask & bits
}

/// Returns `true` if the closed flag has been set.
fn is_tx_closed(bits: usize) -> bool {
    TX_CLOSED == bits & TX_CLOSED
}

impl<T> Values<T> {
    unsafe fn uninitialized() -> Values<T> {
        #[allow(deprecated)]
        let mut vals = mem::uninitialized();

        // When fuzzing, `CausalCell` needs to be initialized.
        if_fuzz! {
            use std::ptr;

            for v in &mut vals {
                ptr::write(
                    v as *mut _,
                    CausalCell::new(mem::zeroed()));
            }
        }

        Values(vals)
    }
}

impl<T> ops::Index<usize> for Values<T> {
    type Output = CausalCell<ManuallyDrop<T>>;

    fn index(&self, index: usize) -> &Self::Output {
        self.0.index(index)
    }
}
<commit_msg>sync: replace deprecated mem::uninitialized usage with MaybeUninit (#1540)<commit_after>use crate::loom::{
    sync::atomic::{AtomicPtr, AtomicUsize},
    sync::CausalCell,
    thread,
};
use std::mem::MaybeUninit;
use std::ops;
use std::ptr::{self, NonNull};
use std::sync::atomic::Ordering::{self, AcqRel, Acquire, Release};

/// A block in a linked list.
///
/// Each block in the list can hold up to `BLOCK_CAP` messages.
pub(crate) struct Block<T> {
    /// The start index of this block.
    ///
    /// Slots in this block have indices in `start_index .. start_index + BLOCK_CAP`.
    start_index: usize,

    /// The next block in the linked list.
    next: AtomicPtr<Block<T>>,

    /// Bitfield tracking slots that are ready to have their values consumed.
    ready_slots: AtomicUsize,

    /// The observed `tail_position` value *after* the block has been passed by
    /// `block_tail`.
    observed_tail_position: CausalCell<usize>,

    /// Array containing values pushed into the block. Values are stored in a
    /// continuous array in order to improve cache line behavior when reading.
    /// The values must be manually dropped.
    values: Values<T>,
}

pub(crate) enum Read<T> {
    Value(T),
    Closed,
}

struct Values<T>([CausalCell<MaybeUninit<T>>; BLOCK_CAP]);

use super::BLOCK_CAP;

/// Masks an index to get the block identifier
const BLOCK_MASK: usize = !(BLOCK_CAP - 1);

/// Masks an index to get the value offset in a block.
const SLOT_MASK: usize = BLOCK_CAP - 1;

/// Flag tracking that a block has gone through the sender's release routine.
///
/// When this is set, the receiver may consider freeing the block.
const RELEASED: usize = 1 << BLOCK_CAP;

/// Flag tracking all senders dropped.
///
/// When this flag is set, the send half of the channel has closed.
const TX_CLOSED: usize = RELEASED << 1;

/// Mask covering all bits used to track slot readiness.
const READY_MASK: usize = RELEASED - 1;

/// Returns the index of the first slot in the block referenced by `slot_index`.
#[inline(always)]
pub(crate) fn start_index(slot_index: usize) -> usize {
    BLOCK_MASK & slot_index
}

/// Returns the offset into the block referenced by `slot_index`.
#[inline(always)]
pub(crate) fn offset(slot_index: usize) -> usize {
    SLOT_MASK & slot_index
}

impl<T> Block<T> {
    pub(crate) fn new(start_index: usize) -> Block<T> {
        Block {
            // The absolute index in the channel of the first slot in the block.
            start_index,

            // Pointer to the next block in the linked list.
            next: AtomicPtr::new(ptr::null_mut()),

            ready_slots: AtomicUsize::new(0),

            observed_tail_position: CausalCell::new(0),

            // Value storage
            values: unsafe { Values::uninitialized() },
        }
    }

    /// Returns `true` if the block matches the given index
    pub(crate) fn is_at_index(&self, index: usize) -> bool {
        debug_assert!(offset(index) == 0);
        self.start_index == index
    }

    /// Returns the number of blocks between `self` and the block at the
    /// specified index.
    ///
    /// `start_index` must represent a block *after* `self`.
    pub(crate) fn distance(&self, other_index: usize) -> usize {
        debug_assert!(offset(other_index) == 0);
        other_index.wrapping_sub(self.start_index) / BLOCK_CAP
    }

    /// Read the value at the given offset.
    ///
    /// Returns `None` if the slot is empty.
    ///
    /// # Safety
    ///
    /// To maintain safety, the caller must ensure:
    ///
    /// * No concurrent access to the slot.
    pub(crate) unsafe fn read(&self, slot_index: usize) -> Option<Read<T>> {
        let offset = offset(slot_index);

        let ready_bits = self.ready_slots.load(Acquire);

        if !is_ready(ready_bits, offset) {
            if is_tx_closed(ready_bits) {
                return Some(Read::Closed);
            }

            return None;
        }

        // Get the value
        let value = self.values[offset].with(|ptr| ptr::read(ptr));

        Some(Read::Value(value.assume_init()))
    }

    /// Write a value to the block at the given offset.
    ///
    /// # Safety
    ///
    /// To maintain safety, the caller must ensure:
    ///
    /// * The slot is empty.
    /// * No concurrent access to the slot.
    pub(crate) unsafe fn write(&self, slot_index: usize, value: T) {
        // Get the offset into the block
        let slot_offset = offset(slot_index);

        self.values[slot_offset].with_mut(|ptr| {
            ptr::write(ptr, MaybeUninit::new(value));
        });

        // Release the value. After this point, the slot ref may no longer
        // be used. It is possible for the receiver to free the memory at
        // any point.
        self.set_ready(slot_offset);
    }

    /// Signal to the receiver that the sender half of the list is closed.
    pub(crate) unsafe fn tx_close(&self) {
        self.ready_slots.fetch_or(TX_CLOSED, Release);
    }

    /// Reset the block to a blank state. This enables reusing blocks in the
    /// channel.
    ///
    /// # Safety
    ///
    /// To maintain safety, the caller must ensure:
    ///
    /// * All slots are empty.
    /// * The caller holds a unique pointer to the block.
    pub(crate) unsafe fn reclaim(&mut self) {
        self.start_index = 0;
        self.next = AtomicPtr::new(ptr::null_mut());
        self.ready_slots = AtomicUsize::new(0);
    }

    /// Release the block to the rx half for freeing.
    ///
    /// This function is called by the tx half once it can be guaranteed that no
    /// more senders will attempt to access the block.
    ///
    /// # Safety
    ///
    /// To maintain safety, the caller must ensure:
    ///
    /// * The block will no longer be accessed by any sender.
    pub(crate) unsafe fn tx_release(&self, tail_position: usize) {
        // Track the observed tail_position. Any sender targetting a greater
        // tail_position is guaranteed to not access this block.
        self.observed_tail_position
            .with_mut(|ptr| *ptr = tail_position);

        // Set the released bit, signalling to the receiver that it is safe to
        // free the block's memory as soon as all slots **prior** to
        // `observed_tail_position` have been filled.
        self.ready_slots.fetch_or(RELEASED, Release);
    }

    /// Mark a slot as ready
    fn set_ready(&self, slot: usize) {
        let mask = 1 << slot;
        self.ready_slots.fetch_or(mask, Release);
    }

    /// Returns `true` when all slots have their `ready` bits set.
    ///
    /// This indicates that the block is in its final state and will no longer
    /// be mutated.
    ///
    /// # Implementation
    ///
    /// The implementation walks each slot checking the `ready` flag. It might
    /// be that it would make more sense to coalesce ready flags as bits in a
    /// single atomic cell. However, this could have negative impact on cache
    /// behavior as there would be many more mutations to a single slot.
    pub(crate) fn is_final(&self) -> bool {
        self.ready_slots.load(Acquire) & READY_MASK == READY_MASK
    }

    /// Returns the `observed_tail_position` value, if set
    pub(crate) fn observed_tail_position(&self) -> Option<usize> {
        if 0 == RELEASED & self.ready_slots.load(Acquire) {
            None
        } else {
            Some(self.observed_tail_position.with(|ptr| unsafe { *ptr }))
        }
    }

    /// Load the next block
    pub(crate) fn load_next(&self, ordering: Ordering) -> Option<NonNull<Block<T>>> {
        let ret = NonNull::new(self.next.load(ordering));

        debug_assert!(unsafe {
            ret.map(|block| block.as_ref().start_index == self.start_index.wrapping_add(BLOCK_CAP))
                .unwrap_or(true)
        });

        ret
    }

    /// Push `block` as the next block in the link.
    ///
    /// Returns Ok if successful, otherwise, a pointer to the next block in
    /// the list is returned.
    ///
    /// This requires that the next pointer is null.
    ///
    /// # Ordering
    ///
    /// This performs a compare-and-swap on `next` using AcqRel ordering.
    ///
    /// # Safety
    ///
    /// To maintain safety, the caller must ensure:
    ///
    /// * `block` is not freed until it has been removed from the list.
    pub(crate) unsafe fn try_push(
        &self,
        block: &mut NonNull<Block<T>>,
        ordering: Ordering,
    ) -> Result<(), NonNull<Block<T>>> {
        block.as_mut().start_index = self.start_index.wrapping_add(BLOCK_CAP);

        let next_ptr = self
            .next
            .compare_and_swap(ptr::null_mut(), block.as_ptr(), ordering);

        match NonNull::new(next_ptr) {
            Some(next_ptr) => Err(next_ptr),
            None => Ok(()),
        }
    }

    /// Grow the `Block` linked list by allocating and appending a new block.
    ///
    /// The next block in the linked list is returned. This may or may not be
    /// the one allocated by the function call.
    ///
    /// # Implementation
    ///
    /// It is assumed that `self.next` is null. A new block is allocated with
    /// `start_index` set to be the next block. A compare-and-swap is performed
    /// with AcqRel memory ordering. If the compare-and-swap is successful, the
    /// newly allocated block is released to other threads walking the block
    /// linked list. If the compare-and-swap fails, the current thread acquires
    /// the next block in the linked list, allowing the current thread to access
    /// the slots.
    pub(crate) fn grow(&self) -> NonNull<Block<T>> {
        // Create the new block. It is assumed that the block will become the
        // next one after `&self`. If this turns out to not be the case,
        // `start_index` is updated accordingly.
        let new_block = Box::new(Block::new(self.start_index + BLOCK_CAP));

        let mut new_block = unsafe { NonNull::new_unchecked(Box::into_raw(new_block)) };

        // Attempt to store the block. The first compare-and-swap attempt is
        // "unrolled" due to minor differences in logic
        //
        // `AcqRel` is used as the ordering **only** when attempting the
        // compare-and-swap on self.next.
        //
        // If the compare-and-swap fails, then the actual value of the cell is
        // returned from this function and accessed by the caller. Given this,
        // the memory must be acquired.
        //
        // `Release` ensures that the newly allocated block is available to
        // other threads acquiring the next pointer.
        let next = NonNull::new(self.next.compare_and_swap(
            ptr::null_mut(),
            new_block.as_ptr(),
            AcqRel,
        ));

        let next = match next {
            Some(next) => next,
            None => {
                // The compare-and-swap succeeded and the newly allocated block
                // is successfully pushed.
                return new_block;
            }
        };

        // There already is a next block in the linked list. The newly allocated
        // block could be dropped and the discovered next block returned;
        // however, that would be wasteful. Instead, the linked list is walked
        // by repeatedly attempting to compare-and-swap the pointer into the
        // `next` register until the compare-and-swap succeed.
        //
        // Care is taken to update new_block's start_index field as appropriate.

        let mut curr = next;

        // TODO: Should this iteration be capped?
        loop {
            let actual = unsafe { curr.as_ref().try_push(&mut new_block, AcqRel) };

            curr = match actual {
                Ok(_) => {
                    return next;
                }
                Err(curr) => curr,
            };

            // When running outside of loom, this calls `spin_loop_hint`.
            thread::yield_now();
        }
    }
}

/// Returns `true` if the specificed slot has a value ready to be consumed.
fn is_ready(bits: usize, slot: usize) -> bool {
    let mask = 1 << slot;
    mask == mask & bits
}

/// Returns `true` if the closed flag has been set.
fn is_tx_closed(bits: usize) -> bool {
    TX_CLOSED == bits & TX_CLOSED
}

impl<T> Values<T> {
    unsafe fn uninitialized() -> Values<T> {
        let mut vals = MaybeUninit::uninit();

        // When fuzzing, `CausalCell` needs to be initialized.
        if_fuzz! {
            let p = vals.as_mut_ptr() as *mut CausalCell<MaybeUninit<T>>;
            for i in 0..BLOCK_CAP {
                p.add(i)
                    .write(CausalCell::new(MaybeUninit::uninit()));
            }
        }

        Values(vals.assume_init())
    }
}

impl<T> ops::Index<usize> for Values<T> {
    type Output = CausalCell<MaybeUninit<T>>;

    fn index(&self, index: usize) -> &Self::Output {
        self.0.index(index)
    }
}
<|endoftext|>