<commit_before>extern crate encoding;

use std::{error}; //{env, error}
use std::io::prelude::*;
use std::net::TcpStream;
use encoding::{Encoding, EncoderTrap};
use encoding::all::ASCII;
use std::thread::sleep;
use std::io;
use std::time::Duration;
//use std::io::prelude::*;

//const HOST: &'static str = "127.0.0.1:5555";

fn check_file(command: &str, mut stream: &TcpStream) -> Result<String, Box<error::Error + Send + Sync>> {
    //prepare buffer
    let mut command_bytes = try!(ASCII.encode(command, EncoderTrap::Strict).map_err(|x| x.into_owned()));
    command_bytes.push('\r' as u8);            //ending escape sequence

    stream.write_all(&command_bytes).unwrap(); //write to stream (send path)

    sleep(Duration::from_millis(2));           //disgusting solution;
                                               //program should wait until stream is ready

    let mut response = String::new();
    let mut limited = stream.take(1024);       //read from stream (receive)
    limited.read_to_string(&mut response);     //unwrap() causes this to panic

    if response.is_empty()
    {
        println!("response is empty")
    }

    Ok(response)
}

fn main() {
    //setup connection:
    //let mut stream = TcpStream::connect("127.0.0.1:5555")
    let stream = TcpStream::connect("127.0.0.1:5555") // try!(TcpStream::connect(HOST));
                               .expect("Couldn't connect to the server...");

    //make stream nonblocking
    stream.set_nonblocking(true).expect("set_nonblocking call failed");

    loop {
        println!("Type command:");
        let stdin = io::stdin();
        for line in stdin.lock().lines() {
            let command = line.unwrap();
            println!("message: {}", command);

            match check_file(&command, &stream){
                Ok(response) => println!("response: {}", response),
                Err(err) => println!("An error occurred: {}", err),
            }
        }
    }

    // command line argument check
    /*let command = match env::args().nth(1) {
        Some(cmd) => cmd,
        None => {
            let my_name = env::args().nth(0).unwrap();
            panic!("Usage: {} [command]", my_name)
        }
    };*/
}
<commit_msg>buffered tcp receive on client side<commit_after>extern crate encoding;

use std::{error}; //{env, error}
use std::io::prelude::*;
use std::net::TcpStream;
use encoding::{Encoding, EncoderTrap};
use encoding::all::ASCII;
use std::thread::sleep;
use std::io;
use std::time::Duration;
use std::str;
//use std::io::prelude::*;

//const HOST: &'static str = "127.0.0.1:5555";

fn check_file(command: &str, mut stream: &TcpStream) -> Result<String, Box<error::Error + Send + Sync>> {
    //prepare buffer
    let mut command_bytes = try!(ASCII.encode(command, EncoderTrap::Strict).map_err(|x| x.into_owned()));
    command_bytes.push('\r' as u8);            //ending escape sequence

    let _ = stream.write_all(&command_bytes).unwrap(); //send

    stream.set_read_timeout(None).expect("set_read_timeout call failed");
    assert_eq!(stream.read_timeout().unwrap(), None);

    //let response = String::new();
    //let mut buf = [0; 8];
    let mut buf: Vec<u8> = Vec::new();
    loop {
        let mut result = stream.read(&mut buf);
        match result {
            Ok(n) => {
                println!("Received {} bytes", n);
                buf.push(n);
                if n < 8 { break };
            },
            _ => {},
        }
    }

    //convert vec to string and print it out
    let response = String::from_utf8(buf).unwrap();
    println!("response: {}", response);

    /*
    //sleep(Duration::from_millis(10));          //disgusting solution;
                                               //program should wait until stream is ready

    let mut response = String::new();
    let mut buffer = [0; 1024];                //1024 bytes buffer

    //set a timeout
    let mut limited = stream.read(&mut [0; 1024]);       //read from stream (receive) (this blocks)
    //limited.read_to_string(&mut response);     //unwrap() causes this to panic
    */

    Ok(response)
}

fn main() {
    //setup connection:
    //let mut stream = TcpStream::connect("127.0.0.1:5555")
    let stream = TcpStream::connect("127.0.0.1:5555") // try!(TcpStream::connect(HOST));
                            .expect("Couldn't connect to the server...");

    //make stream nonblocking
    //stream.set_nonblocking(true).expect("set_nonblocking call failed");

    loop {
        println!("Type command:");
        let stdin = io::stdin();
        for line in stdin.lock().lines() {
            let command = line.unwrap();
            println!("message: {}", command);

            match check_file(&command, &stream){
                Ok(response) => println!("response: {}", response),
                Err(err) => println!("An error occurred: {}", err),
            }
        }
    }

    // command line argument check
    /*let command = match env::args().nth(1) {
        Some(cmd) => cmd,
        None => {
            let my_name = env::args().nth(0).unwrap();
            panic!("Usage: {} [command]", my_name)
        }
    };*/
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate criterion;
extern crate pdatastructs;

use criterion::Criterion;
use pdatastructs::filters::bloomfilter::BloomFilter;
use pdatastructs::filters::cuckoofilter::CuckooFilter;
use pdatastructs::filters::Filter;
use pdatastructs::rand::{ChaChaRng, SeedableRng};

fn bloomfilter_insert_single(c: &mut Criterion) {
    c.bench_function("bloomfilter_insert_single", |b| {
        let false_positive_rate = 0.02; // = 2%
        let expected_elements = 1000;
        let mut filter = BloomFilter::with_properties(expected_elements, false_positive_rate);
        let obj = "foo bar";

        b.iter(|| {
            filter.insert(&obj).unwrap();
        })
    });
}

fn cuckoofilter_insert_many(c: &mut Criterion) {
    c.bench_function("cuckoofilter_insert_many", |b| {
        let false_positive_rate = 0.02; // = 2%
        let expected_elements = 1000 * 1000;
        let rng = ChaChaRng::from_seed([0; 32]);
        let mut filter =
            CuckooFilter::with_properties_8(false_positive_rate, expected_elements, rng);
        let mut obj: u64 = 0;

        b.iter(|| {
            filter.insert(&obj).unwrap();
            obj += 1;
        })
    });
}

criterion_group!(benches, bloomfilter_insert_single, cuckoofilter_insert_many);
criterion_main!(benches);
<commit_msg>filters: rework benches<commit_after>#[macro_use]
extern crate criterion;
extern crate pdatastructs;

use criterion::{Bencher, Criterion};
use pdatastructs::filters::bloomfilter::BloomFilter;
use pdatastructs::filters::cuckoofilter::CuckooFilter;
use pdatastructs::filters::quotientfilter::QuotientFilter;
use pdatastructs::filters::Filter;
use pdatastructs::rand::{ChaChaRng, SeedableRng};

fn run_insert_many<F>(mut filter: F, b: &mut Bencher)
where
    F: Filter,
{
    let mut obj: u64 = 0;

    b.iter(|| {
        filter.insert(&obj).unwrap();
        obj += 1;
    })
}

fn bloomfilter_insert_many(c: &mut Criterion) {
    c.bench_function("bloomfilter_insert_many", |b| {
        let false_positive_rate = 0.02; // = 2%
        let expected_elements = 1000 * 1000;
        let filter = BloomFilter::with_properties(expected_elements, false_positive_rate);

        run_insert_many(filter, b);
    });
}

fn cuckoofilter_insert_many(c: &mut Criterion) {
    c.bench_function("cuckoofilter_insert_many", |b| {
        let false_positive_rate = 0.02; // = 2%
        let expected_elements = 1000 * 1000;
        let rng = ChaChaRng::from_seed([0; 32]);
        let filter = CuckooFilter::with_properties_8(false_positive_rate, expected_elements, rng);

        run_insert_many(filter, b);
    });
}

fn quotientfilter_insert_many(c: &mut Criterion) {
    c.bench_function("quotientfilter_insert_many", |b| {
        let bits_quotient = 24;
        let bits_remainder = 4;
        let filter = QuotientFilter::with_params(bits_quotient, bits_remainder);

        run_insert_many(filter, b);
    });
}

criterion_group!(
    benches,
    bloomfilter_insert_many,
    cuckoofilter_insert_many,
    quotientfilter_insert_many
);
criterion_main!(benches);
<|endoftext|>


<commit_before>#![feature(test)]
extern crate minimax;
extern crate test;
use test::Bencher;
use minimax::*;

#[derive(Clone)]
pub struct Board;

#[derive(Copy, Clone)]
pub struct Place;

pub struct Eval;

pub struct Noop;

impl Move for Place {
    type G = Noop;
    fn apply(&self, _: &mut Board) { }
    fn undo(&self, _: &mut Board) { }
}

impl Game for Noop {
    type S = Board;
    type M = Place;

    fn generate_moves(_: &Board, _: Player, ms: &mut [Option<Place>]) -> usize {
        ms[0] = Some(Place);
        ms[1] = Some(Place);
        ms[2] = Some(Place);
        ms[3] = Some(Place);
        ms[4] = None;
        4
    }

    fn get_winner(_: &Board) -> Option<Winner> { None }
}

impl Evaluator for Eval {
    type G = Noop;

    fn evaluate(_: &Board, _: Option<Winner>) -> Evaluation {
        Evaluation::Score(0)
    }
}

#[bench]
fn bench_negamax(b: &mut Bencher) {
    let board = Board;
    let mut s = Negamax::<Eval>::new(Options { max_depth: 10 });
    b.iter(|| s.choose_move(&board, Player::Computer));
}
<commit_msg>Make idiomatic the negemax benchmark's move generation function.<commit_after>#![feature(test)]
extern crate minimax;
extern crate test;
use test::Bencher;
use minimax::*;

#[derive(Clone)]
pub struct Board;

#[derive(Copy, Clone)]
pub struct Place;

pub struct Eval;

pub struct Noop;

impl Move for Place {
    type G = Noop;
    fn apply(&self, _: &mut Board) { }
    fn undo(&self, _: &mut Board) { }
}

impl Game for Noop {
    type S = Board;
    type M = Place;

    fn generate_moves(_: &Board, _: Player, ms: &mut [Option<Place>]) -> usize {
        const NUM_MOVES: usize = 4;
        for m in ms.iter_mut().take(NUM_MOVES) {
            *m = Some(Place);
        }
        ms[NUM_MOVES] = None;
        NUM_MOVES
    }

    fn get_winner(_: &Board) -> Option<Winner> { None }
}

impl Evaluator for Eval {
    type G = Noop;

    fn evaluate(_: &Board, _: Option<Winner>) -> Evaluation {
        Evaluation::Score(0)
    }
}

#[bench]
fn bench_negamax(b: &mut Bencher) {
    let board = Board;
    let mut s = Negamax::<Eval>::new(Options { max_depth: 10 });
    b.iter(|| s.choose_move(&board, Player::Computer));
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate criterion;
extern crate rustdct;

// can't coerce Arc<Type2And3<f32>> to Arc<DCT2<f32>>
use rustdct::{DCTplanner, Type2And3 as DCT2};

use criterion::{Criterion, Fun};

use std::cmp;

struct StepIter {
    curr: usize,
    step: usize,
    max: usize,
}

impl Iterator for StepIter {
    type Item = usize;

    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        let ret = self.curr;

        if ret >= self.max {
            None
        } else {
            self.curr += self.step;
            Some(ret)
        }
    }
}

fn transpose_safe(width: usize, height: usize, input: &[f32], output: &mut [f32]) {
    assert_eq!(input.len(), output.len());
    assert_eq!(width * height, input.len());
    assert_eq!(width * height, output.len());

    let output_len = output.len();

    let mut col_iter = (0 .. height).flat_map(|y| StepIter { curr: y, step: height, max: output_len});

    let mut chunks_exact = input.chunks_exact(16);
    for chunk in chunks_exact.by_ref() {
        for (val, out_idx) in chunk.iter().zip(&mut col_iter) {
            output[out_idx] = *val;
        }
    }

    for (val, out_idx) in chunks_exact.remainder().iter().zip(&mut col_iter) {
        output[out_idx] = *val;
    }
}

const BLOCK_SIZE: usize = 16;

#[inline(always)]
unsafe fn transpose_block<T: Copy>(input: &[T], output: &mut [T], width: usize, height: usize, block_x: usize, block_y: usize) {
    for inner_x in 0..BLOCK_SIZE {
        for inner_y in 0..BLOCK_SIZE {
            let x = block_x * BLOCK_SIZE + inner_x;
            let y = block_y * BLOCK_SIZE + inner_y;

            let input_index = x + y * width;
            let output_index = y + x * height;

            *output.get_unchecked_mut(output_index) = *input.get_unchecked(input_index);
        }
    }
}

#[inline(always)]
unsafe fn transpose_endcap_block<T: Copy>(input: &[T], output: &mut [T], width: usize, height: usize, block_x: usize, block_y: usize, block_width: usize, block_height: usize) {
    for inner_x in 0..block_width {
        for inner_y in 0..block_height {
            let x = block_x * BLOCK_SIZE + inner_x;
            let y = block_y * BLOCK_SIZE + inner_y;

            let input_index = x + y * width;
            let output_index = y + x * height;

            *output.get_unchecked_mut(output_index) = *input.get_unchecked(input_index);
        }
    }
}

/// Given an array of size width * height, representing a flattened 2D array,
/// transpose the rows and columns of that 2D array into the output
// Use "Loop tiling" to improve cache-friendliness
pub fn transpose_unsafe<T: Copy>(width: usize, height: usize, input: &[T], output: &mut [T]) {
    assert_eq!(width*height, input.len());
    assert_eq!(width*height, output.len());

    let x_block_count = width / BLOCK_SIZE;
    let y_block_count = height / BLOCK_SIZE;

    let remainder_x = width - x_block_count * BLOCK_SIZE;
    let remainder_y = height - y_block_count * BLOCK_SIZE;

    for y_block in 0..y_block_count {
        for x_block in 0..x_block_count {
            unsafe {
                transpose_block(
                    input, output,
                    width, height,
                    x_block, y_block);
            }
        }

        //if the width is not cleanly divisible by block_size, there are still a few columns that haven't been transposed
        if remainder_x > 0 {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block_count, y_block,
                    remainder_x, BLOCK_SIZE);
            }
        }
    }

    //if the height is not cleanly divisible by BLOCK_SIZE, there are still a few columns that haven't been transposed
    if remainder_y > 0 {
        for x_block in 0..x_block_count {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block, y_block_count,
                    BLOCK_SIZE, remainder_y,
                );
            }
        }

        //if the width is not cleanly divisible by block_size, there are still a few columns that haven't been transposed
        if remainder_x > 0 {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block_count, y_block_count,
                    remainder_x, remainder_y);
            }
        }
    }
}

fn dct_2d<Ft>(row_dct: &DCT2<f32>, col_dct: &DCT2<f32>, signal: &mut [f32], width: usize, height: usize, transpose: Ft)
where Ft: Fn(usize, usize, &[f32], &mut [f32]) {
    assert_eq!(width * height, signal.len());
    let mut scratch = vec![0f32; signal.len()];

    for (row_in, row_out) in signal.chunks_mut(width).zip(scratch.chunks_mut(width)) {
        row_dct.process_dct2(row_in, row_out);
    }

    transpose(width, height, &scratch, signal);

    for (row_in, row_out) in signal.chunks_mut(height).zip(scratch.chunks_mut(height)) {
        col_dct.process_dct2(row_in, row_out);
    }

    transpose(width, height, &scratch, signal);
}

fn bench_transposes(criterion: &mut Criterion) {
    fn gen_data(width: usize, height: usize) -> Vec<f32> {
        (0 .. width * height).map(|x| x as f32).collect()
    }

    let dimensions = [
        [8, 8], [8, 16], [16, 8],
        [16, 16], [16, 32], [32, 16],
        [64, 64], [64, 128], [128, 64],
        [256, 256], [256, 512], [512, 256],
        [512, 512], [512, 1024], [1024, 512],
        [1024, 1024]
    ];

    for &[width, height] in &dimensions {
        let mut planner = DCTplanner::new();
        let mut planner2 = DCTplanner::new();

        let fns = vec![
            Fun::new("Safe Transpose", move |b, _| {
                let row_dct = planner.plan_dct2(width);
                let col_dct = planner.plan_dct2(height);

                b.iter_with_setup(
                    || gen_data(width, height),
                    |mut data| dct_2d(&*row_dct, &*col_dct, &mut data, width, height, transpose_safe)
                )
            }),
            Fun::new("Unsafe Transpose", move |b, _| {
                let row_dct = planner2.plan_dct2(width);
                let col_dct = planner2.plan_dct2(height);

                b.iter_with_setup(
                    || gen_data(width, height),
                    |mut data| dct_2d(&*row_dct, &*col_dct, &mut data, width, height, transpose_unsafe)
                )
            })
        ];

        criterion.bench_functions(&format!("RustDCT {}x{}", width, height), fns, ());
    }
}

criterion_group!(benches, bench_transposes);
criterion_main!(benches);
<commit_msg>adjust transpose benchmark to only measure transpose performance; test both aligned and unaligned inputs and outputs<commit_after>#[macro_use]
extern crate criterion;
extern crate rustdct;

// can't coerce Arc<Type2And3<f32>> to Arc<DCT2<f32>>
use rustdct::{DCTplanner, Type2And3 as DCT2};

use criterion::{Criterion, Fun};

use std::cmp;
use std::ops::{Deref, DerefMut};

struct StepIter {
    curr: usize,
    step: usize,
    max: usize,
}

impl Iterator for StepIter {
    type Item = usize;

    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        let ret = self.curr;

        if ret >= self.max {
            None
        } else {
            self.curr += self.step;
            Some(ret)
        }
    }
}

fn transpose_safe(width: usize, height: usize, input: &[f32], output: &mut [f32]) {
    assert_eq!(input.len(), output.len());
    assert_eq!(width * height, input.len());
    assert_eq!(width * height, output.len());

    let output_len = output.len();

    let mut col_iter = (0 .. height).flat_map(|y| StepIter { curr: y, step: height, max: output_len});

    let mut chunks_exact = input.chunks_exact(16);
    for chunk in chunks_exact.by_ref() {
        for (val, out_idx) in chunk.iter().zip(&mut col_iter) {
            output[out_idx] = *val;
        }
    }

    for (val, out_idx) in chunks_exact.remainder().iter().zip(&mut col_iter) {
        output[out_idx] = *val;
    }
}

const BLOCK_SIZE: usize = 8;

#[inline(always)]
unsafe fn transpose_block<T: Copy>(input: &[T], output: &mut [T], width: usize, height: usize, block_x: usize, block_y: usize) {
    for inner_x in 0..BLOCK_SIZE {
        for inner_y in 0..BLOCK_SIZE {
            let x = block_x * BLOCK_SIZE + inner_x;
            let y = block_y * BLOCK_SIZE + inner_y;

            let input_index = x + y * width;
            let output_index = y + x * height;

            *output.get_unchecked_mut(output_index) = *input.get_unchecked(input_index);
        }
    }
}

#[inline(always)]
unsafe fn transpose_endcap_block<T: Copy>(input: &[T], output: &mut [T], width: usize, height: usize, block_x: usize, block_y: usize, block_width: usize, block_height: usize) {
    for inner_x in 0..block_width {
        for inner_y in 0..block_height {
            let x = block_x * BLOCK_SIZE + inner_x;
            let y = block_y * BLOCK_SIZE + inner_y;

            let input_index = x + y * width;
            let output_index = y + x * height;

            *output.get_unchecked_mut(output_index) = *input.get_unchecked(input_index);
        }
    }
}

/// Given an array of size width * height, representing a flattened 2D array,
/// transpose the rows and columns of that 2D array into the output
// Use "Loop tiling" to improve cache-friendliness
pub fn transpose_unsafe<T: Copy>(width: usize, height: usize, input: &[T], output: &mut [T]) {
    assert_eq!(width*height, input.len());
    assert_eq!(width*height, output.len());

    let x_block_count = width / BLOCK_SIZE;
    let y_block_count = height / BLOCK_SIZE;

    let remainder_x = width - x_block_count * BLOCK_SIZE;
    let remainder_y = height - y_block_count * BLOCK_SIZE;

    for y_block in 0..y_block_count {
        for x_block in 0..x_block_count {
            unsafe {
                transpose_block(
                    input, output,
                    width, height,
                    x_block, y_block);
            }
        }

        //if the width is not cleanly divisible by block_size, there are still a few columns that haven't been transposed
        if remainder_x > 0 {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block_count, y_block,
                    remainder_x, BLOCK_SIZE);
            }
        }
    }

    //if the height is not cleanly divisible by BLOCK_SIZE, there are still a few columns that haven't been transposed
    if remainder_y > 0 {
        for x_block in 0..x_block_count {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block, y_block_count,
                    BLOCK_SIZE, remainder_y,
                );
            }
        }

        //if the width is not cleanly divisible by block_size, there are still a few columns that haven't been transposed
        if remainder_x > 0 {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block_count, y_block_count,
                    remainder_x, remainder_y);
            }
        }
    }
}

fn dct_2d<Ft>(row_dct: &DCT2<f32>, col_dct: &DCT2<f32>, signal: &mut [f32], width: usize, height: usize, transpose: Ft)
where Ft: Fn(usize, usize, &[f32], &mut [f32]) {
    assert_eq!(width * height, signal.len());
    let mut scratch = vec![0f32; signal.len()];

    for (row_in, row_out) in signal.chunks_mut(width).zip(scratch.chunks_mut(width)) {
        row_dct.process_dct2(row_in, row_out);
    }

    transpose(width, height, &scratch, signal);

    for (row_in, row_out) in signal.chunks_mut(height).zip(scratch.chunks_mut(height)) {
        col_dct.process_dct2(row_in, row_out);
    }

    transpose(width, height, &scratch, signal);
}

#[derive(Debug)]
struct AlignedVec {
    vec: Vec<f32>,
    start: usize,
    end: usize,
}

impl AlignedVec {
    pub fn new(len: usize) -> Self {
        let vec = vec![0.; len + 16];
        let start = (64 - vec.as_ptr() as usize % 64) / 4;
        AlignedVec {
            vec, start, end: start + len,
        }
    }

    pub fn unaligned(len: usize) -> Self {
        AlignedVec {
            vec: vec![0.; len], start: 0, end: len
        }
    }
}

impl Deref for AlignedVec {
    type Target = [f32];

    fn deref(&self) -> &[f32] {
        &self.vec[self.start .. self.end]
    }
}

impl DerefMut for AlignedVec {
    fn deref_mut(&mut self) -> &mut [f32] {
        &mut self.vec[self.start .. self.end]
    }
}

fn bench_transposes(criterion: &mut Criterion) {
    fn fill_data(width: usize, height: usize, out: &mut [f32]) {
        (0 .. height).flat_map(|y| (0 .. width).map(move |x| x as f32 * y as f32))
            .zip(out).for_each(|(val, out)| *out = val);
    }

    let dimensions = [
        [8, 8], [8, 16], [16, 8],
        [16, 16], [16, 32], [32, 16],
        [64, 64], [64, 128], [128, 64],
        [256, 256], [256, 512], [512, 256],
        [512, 512], [512, 1024], [1024, 512],
        [1024, 1024]
    ];

    for &[width, height] in &dimensions {
        let mut aligned = AlignedVec::new(width * height);
        fill_data(width, height, &mut aligned);

        let mut unaligned = AlignedVec::unaligned(width * height);
        fill_data(width, height, &mut unaligned);

        let fns = vec![
            Fun::new("Safe Transpose", move |b, data: &AlignedVec| {
                b.iter_with_setup(
                    || AlignedVec::new(width * height),
                    |mut out| {
                        transpose_safe(width, height, &data, &mut out);
                        out
                    }
                )
            }),
            Fun::new("Unsafe Transpose", move |b, data: &AlignedVec| {
                b.iter_with_setup(
                    || AlignedVec::new(width * height),
                    |mut out| {
                        transpose_unsafe(width, height, &data, &mut out);
                        out
                    }
                )
            })
        ];

        criterion.bench_functions(&format!("RustDCT {}x{} (aligned)", width, height), fns, aligned);

        let fns = vec![
            Fun::new("Safe Transpose", move |b, data: &AlignedVec| {
                b.iter_with_setup(
                    || AlignedVec::unaligned(width * height),
                    |mut out| {
                        transpose_safe(width, height, &data, &mut out);
                        out
                    }
                )
            }),
            Fun::new("Unsafe Transpose", move |b, data: &AlignedVec| {
                b.iter_with_setup(
                    || AlignedVec::unaligned(width * height),
                    |mut out| {
                        transpose_unsafe(width, height, &data, &mut out);
                        out
                    }
                )
            })
        ];

        criterion.bench_functions(&format!("RustDCT {}x{} (unaligned)", width, height), fns, unaligned);
    }
}

criterion_group!(benches, bench_transposes);
criterion_main!(benches);
<|endoftext|>


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

use std::collections::HashSet;

use criterion::{
    black_box, AxisScale, Bencher, Criterion, ParameterizedBenchmark, PlotConfiguration, Throughput,
};
use rand::{Rng, RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

use exonum_crypto::Hash;
use exonum_merkledb::{
    proof_map_index::PROOF_MAP_KEY_SIZE as KEY_SIZE, Database, MapIndex, ProofListIndex,
    ProofMapIndex, TemporaryDB,
};

const NAME: &str = "name";
const FAMILY: &str = "index_family";
const SAMPLE_SIZE: usize = 10;
const CHUNK_SIZE: usize = 64;
const SEED: [u8; 16] = [100; 16];
const ITEM_COUNTS: [usize; 4] = [1_000, 10_000, 100_000, 1_000_000];

fn generate_random_kv(len: usize) -> Vec<(Hash, Vec<u8>)> {
    let mut rng = XorShiftRng::from_seed(SEED);
    let mut exists_keys = HashSet::new();
    let mut base = [0; KEY_SIZE];
    rng.fill_bytes(&mut base);
    let base = base;

    let kv_generator = |_| {
        let mut v = vec![0; CHUNK_SIZE];
        // Generate only unique keys.
        let mut k = base;
        let byte: usize = rng.gen_range(0, 31);
        k[byte] = rng.gen::<u8>();

        rng.fill_bytes(&mut v);
        while exists_keys.contains(&k) {
            rng.fill_bytes(&mut k);
        }
        exists_keys.insert(k);
        (Hash::new(k), v)
    };

    (0..len).map(kv_generator).collect::<Vec<_>>()
}

fn plain_map_index_insert(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    b.iter_with_setup(
        || (TemporaryDB::default(), data.clone()),
        |(db, data)| {
            let mut fork = db.fork();
            {
                let mut table = MapIndex::new(NAME, &mut fork);
                for item in data {
                    table.put(&item.0, item.1);
                }
            }
            db.merge_sync(fork.into_patch()).unwrap();
        },
    );
}

fn plain_map_index_with_family_insert(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    b.iter_with_setup(
        || (TemporaryDB::default(), data.clone()),
        |(db, data)| {
            let mut fork = db.fork();
            {
                let mut table = MapIndex::new_in_family(NAME, FAMILY, &mut fork);
                for item in data {
                    table.put(&item.0, item.1);
                }
            }
            db.merge_sync(fork.into_patch()).unwrap();
        },
    );
}

fn plain_map_index_iter(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    let db = TemporaryDB::default();
    let mut fork = db.fork();

    let mut table = MapIndex::new(NAME, &mut fork);
    assert!(table.keys().next().is_none());
    for item in data {
        table.put(&item.0, item.1);
    }
    db.merge_sync(fork.into_patch()).unwrap();

    b.iter_with_setup(
        || db.snapshot(),
        |snapshot| {
            let index: MapIndex<_, Vec<u8>, Vec<u8>> = MapIndex::new(NAME, &snapshot);
            for (key, value) in &index {
                black_box(key);
                black_box(value);
            }
        },
    );
}

fn plain_map_index_with_family_iter(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    let db = TemporaryDB::default();
    let mut fork = db.fork();

    let mut table = MapIndex::new_in_family(NAME, FAMILY, &mut fork);
    assert!(table.keys().next().is_none());
    for item in data {
        table.put(&item.0, item.1);
    }
    db.merge(fork.into_patch()).unwrap();

    b.iter_with_setup(
        || db.snapshot(),
        |snapshot| {
            let index: MapIndex<_, Vec<u8>, Vec<u8>> =
                MapIndex::new_in_family(NAME, FAMILY, &snapshot);
            for (key, value) in &index {
                black_box(key);
                black_box(value);
            }
        },
    );
}

fn proof_list_append(b: &mut Bencher, len: usize) {
    let mut rng = XorShiftRng::from_seed(SEED);
    let data = (0..len)
        .map(|_| {
            let mut chunk = vec![0; CHUNK_SIZE];
            rng.fill_bytes(&mut chunk);
            chunk
        })
        .collect::<Vec<_>>();

    let db = TemporaryDB::default();
    b.iter_with_setup(
        || (db.fork(), data.clone()),
        |(mut storage, data)| {
            let mut table = ProofListIndex::new(NAME, &mut storage);
            assert!(table.is_empty());
            for item in data {
                table.push(item);
            }
        },
    );
}

fn proof_map_insert_without_merge(b: &mut Bencher, len: usize) {
    let db = TemporaryDB::default();
    let data = generate_random_kv(len);
    b.iter_with_setup(
        || (db.fork(), data.clone()),
        |(mut storage, data)| {
            let mut table = ProofMapIndex::new(NAME, &mut storage);
            for item in data {
                table.put(&item.0, item.1);
            }
        },
    );
}

fn proof_map_insert_with_merge(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    b.iter_with_setup(
        || (TemporaryDB::default(), data.clone()),
        |(db, data)| {
            let mut fork = db.fork();
            {
                let mut table = ProofMapIndex::new(NAME, &mut fork);
                for item in data {
                    table.put(&item.0, item.1);
                }
            }
            db.merge_sync(fork.into_patch()).unwrap();
        },
    );
}

fn proof_map_index_build_proofs(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    let db = TemporaryDB::default();
    let storage = db.fork();
    let mut table = ProofMapIndex::new(NAME, &storage);

    for item in &data {
        table.put(&item.0, item.1.clone());
    }
    let table_merkle_root = table.merkle_root();
    let mut proofs = Vec::with_capacity(data.len());

    b.iter(|| {
        proofs.clear();
        proofs.extend(data.iter().map(|item| table.get_proof(item.0)));
    });

    for (i, proof) in proofs.into_iter().enumerate() {
        let checked_proof = proof.check().unwrap();
        assert_eq!(*checked_proof.entries().next().unwrap().1, data[i].1);
        assert_eq!(checked_proof.merkle_root(), table_merkle_root);
    }
}

fn proof_map_index_verify_proofs(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    let db = TemporaryDB::default();
    let storage = db.fork();
    let mut table = ProofMapIndex::new(NAME, &storage);

    for item in &data {
        table.put(&item.0, item.1.clone());
    }
    let table_merkle_root = table.merkle_root();
    let proofs: Vec<_> = data.iter().map(|item| table.get_proof(item.0)).collect();

    b.iter(|| {
        for (i, proof) in proofs.iter().enumerate() {
            let checked_proof = proof.clone().check().unwrap();
            assert_eq!(*checked_proof.entries().next().unwrap().1, data[i].1);
            assert_eq!(checked_proof.merkle_root(), table_merkle_root);
        }
    });
}

fn bench_fn<F>(c: &mut Criterion, name: &str, benchmark: F)
where
    F: Fn(&mut Bencher, usize) + 'static,
{
    let item_counts = ITEM_COUNTS.iter().cloned();
    c.bench(
        name,
        ParameterizedBenchmark::new(
            "items",
            move |b: &mut Bencher, &len: &usize| benchmark(b, len),
            item_counts,
        )
        .throughput(|s| Throughput::Elements(*s as u32))
        .plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic))
        .sample_size(SAMPLE_SIZE),
    );
}

pub fn bench_storage(c: &mut Criterion) {
    exonum_crypto::init();

    bench_fn(c, "plain_map/insert", plain_map_index_insert);
    bench_fn(c, "plain_map/iter", plain_map_index_iter);
    bench_fn(
        c,
        "plain_map_with_family/insert",
        plain_map_index_with_family_insert,
    );
    bench_fn(
        c,
        "plain_map_with_family/iter",
        plain_map_index_with_family_iter,
    );
    bench_fn(c, "proof_list/append", proof_list_append);
    bench_fn(
        c,
        "proof_map/insert/no_merge",
        proof_map_insert_without_merge,
    );
    bench_fn(c, "proof_map/insert/merge", proof_map_insert_with_merge);
    bench_fn(c, "proof_map/proofs/build", proof_map_index_build_proofs);
    bench_fn(
        c,
        "proof_map/proofs/validate",
        proof_map_index_verify_proofs,
    );
}
<commit_msg>Add benchmarks for read<commit_after>// Copyright 2019 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;

use criterion::{
    black_box, AxisScale, Bencher, Criterion, ParameterizedBenchmark, PlotConfiguration, Throughput,
};
use rand::{Rng, RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

use exonum_crypto::Hash;
use exonum_merkledb::{
    proof_map_index::PROOF_MAP_KEY_SIZE as KEY_SIZE, Database, MapIndex, ProofListIndex,
    ProofMapIndex, TemporaryDB,
};

const NAME: &str = "name";
const FAMILY: &str = "index_family";
const SAMPLE_SIZE: usize = 10;
const CHUNK_SIZE: usize = 64;
const SEED: [u8; 16] = [100; 16];
const ITEM_COUNTS: [usize; 4] = [1_000, 10_000, 100_000, 1_000_000];

fn generate_random_kv(len: usize) -> Vec<(Hash, Vec<u8>)> {
    let mut rng = XorShiftRng::from_seed(SEED);
    let mut exists_keys = HashSet::new();
    let mut base = [0; KEY_SIZE];
    rng.fill_bytes(&mut base);
    let base = base;

    let kv_generator = |_| {
        let mut v = vec![0; CHUNK_SIZE];
        // Generate only unique keys.
        let mut k = base;
        let byte: usize = rng.gen_range(0, 31);
        k[byte] = rng.gen::<u8>();

        rng.fill_bytes(&mut v);
        while exists_keys.contains(&k) {
            rng.fill_bytes(&mut k);
        }
        exists_keys.insert(k);
        (Hash::new(k), v)
    };

    (0..len).map(kv_generator).collect::<Vec<_>>()
}

fn plain_map_index_insert(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    b.iter_with_setup(
        || (TemporaryDB::default(), data.clone()),
        |(db, data)| {
            let mut fork = db.fork();
            {
                let mut table = MapIndex::new(NAME, &mut fork);
                for item in data {
                    table.put(&item.0, item.1);
                }
            }
            db.merge_sync(fork.into_patch()).unwrap();
        },
    );
}

fn plain_map_index_with_family_insert(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    b.iter_with_setup(
        || (TemporaryDB::default(), data.clone()),
        |(db, data)| {
            let mut fork = db.fork();
            {
                let mut table = MapIndex::new_in_family(NAME, FAMILY, &mut fork);
                for item in data {
                    table.put(&item.0, item.1);
                }
            }
            db.merge_sync(fork.into_patch()).unwrap();
        },
    );
}

fn plain_map_index_iter(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    let db = TemporaryDB::default();
    let mut fork = db.fork();

    let mut table = MapIndex::new(NAME, &mut fork);
    assert!(table.keys().next().is_none());
    for item in data {
        table.put(&item.0, item.1);
    }
    db.merge_sync(fork.into_patch()).unwrap();

    b.iter_with_setup(
        || db.snapshot(),
        |snapshot| {
            let index: MapIndex<_, Hash, Vec<u8>> = MapIndex::new(NAME, &snapshot);
            for (key, value) in &index {
                black_box(key);
                black_box(value);
            }
        },
    );
}

fn plain_map_index_with_family_iter(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    let db = TemporaryDB::default();
    let mut fork = db.fork();

    let mut table = MapIndex::new_in_family(NAME, FAMILY, &mut fork);
    assert!(table.keys().next().is_none());
    for item in data {
        table.put(&item.0, item.1);
    }
    db.merge(fork.into_patch()).unwrap();

    b.iter_with_setup(
        || db.snapshot(),
        |snapshot| {
            let index: MapIndex<_, Hash, Vec<u8>> =
                MapIndex::new_in_family(NAME, FAMILY, &snapshot);
            for (key, value) in &index {
                black_box(key);
                black_box(value);
            }
        },
    );
}

fn plain_map_index_read(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    let db = TemporaryDB::default();
    let mut fork = db.fork();

    let mut table = MapIndex::new(NAME, &mut fork);
    assert!(table.keys().next().is_none());
    for item in data.clone() {
        table.put(&item.0, item.1);
    }
    db.merge_sync(fork.into_patch()).unwrap();

    b.iter_with_setup(
        || db.snapshot(),
        |snapshot| {
            let index: MapIndex<_, Hash, Vec<u8>> = MapIndex::new(NAME, &snapshot);
            for item in &data {
                let value = index.get(&item.0);
                black_box(value);
            }
        },
    );
}

fn plain_map_index_with_family_read(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    let db = TemporaryDB::default();
    let mut fork = db.fork();

    let mut table = MapIndex::new_in_family(NAME, FAMILY, &mut fork);
    assert!(table.keys().next().is_none());
    for item in data.clone() {
        table.put(&item.0, item.1);
    }
    db.merge_sync(fork.into_patch()).unwrap();

    b.iter_with_setup(
        || db.snapshot(),
        |snapshot| {
            let index: MapIndex<_, Hash, Vec<u8>> =
                MapIndex::new_in_family(NAME, FAMILY, &snapshot);
            for item in &data {
                let value = index.get(&item.0);
                black_box(value);
            }
        },
    );
}

fn proof_list_append(b: &mut Bencher, len: usize) {
    let mut rng = XorShiftRng::from_seed(SEED);
    let data = (0..len)
        .map(|_| {
            let mut chunk = vec![0; CHUNK_SIZE];
            rng.fill_bytes(&mut chunk);
            chunk
        })
        .collect::<Vec<_>>();

    let db = TemporaryDB::default();
    b.iter_with_setup(
        || (db.fork(), data.clone()),
        |(mut storage, data)| {
            let mut table = ProofListIndex::new(NAME, &mut storage);
            assert!(table.is_empty());
            for item in data {
                table.push(item);
            }
        },
    );
}

fn proof_map_insert_without_merge(b: &mut Bencher, len: usize) {
    let db = TemporaryDB::default();
    let data = generate_random_kv(len);
    b.iter_with_setup(
        || (db.fork(), data.clone()),
        |(mut storage, data)| {
            let mut table = ProofMapIndex::new(NAME, &mut storage);
            for item in data {
                table.put(&item.0, item.1);
            }
        },
    );
}

fn proof_map_insert_with_merge(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    b.iter_with_setup(
        || (TemporaryDB::default(), data.clone()),
        |(db, data)| {
            let mut fork = db.fork();
            {
                let mut table = ProofMapIndex::new(NAME, &mut fork);
                for item in data {
                    table.put(&item.0, item.1);
                }
            }
            db.merge_sync(fork.into_patch()).unwrap();
        },
    );
}

fn proof_map_index_build_proofs(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    let db = TemporaryDB::default();
    let storage = db.fork();
    let mut table = ProofMapIndex::new(NAME, &storage);

    for item in &data {
        table.put(&item.0, item.1.clone());
    }
    let table_merkle_root = table.merkle_root();
    let mut proofs = Vec::with_capacity(data.len());

    b.iter(|| {
        proofs.clear();
        proofs.extend(data.iter().map(|item| table.get_proof(item.0)));
    });

    for (i, proof) in proofs.into_iter().enumerate() {
        let checked_proof = proof.check().unwrap();
        assert_eq!(*checked_proof.entries().next().unwrap().1, data[i].1);
        assert_eq!(checked_proof.merkle_root(), table_merkle_root);
    }
}

fn proof_map_index_verify_proofs(b: &mut Bencher, len: usize) {
    let data = generate_random_kv(len);
    let db = TemporaryDB::default();
    let storage = db.fork();
    let mut table = ProofMapIndex::new(NAME, &storage);

    for item in &data {
        table.put(&item.0, item.1.clone());
    }
    let table_merkle_root = table.merkle_root();
    let proofs: Vec<_> = data.iter().map(|item| table.get_proof(item.0)).collect();

    b.iter(|| {
        for (i, proof) in proofs.iter().enumerate() {
            let checked_proof = proof.clone().check().unwrap();
            assert_eq!(*checked_proof.entries().next().unwrap().1, data[i].1);
            assert_eq!(checked_proof.merkle_root(), table_merkle_root);
        }
    });
}

fn bench_fn<F>(c: &mut Criterion, name: &str, benchmark: F)
where
    F: Fn(&mut Bencher, usize) + 'static,
{
    let item_counts = ITEM_COUNTS.iter().cloned();
    c.bench(
        name,
        ParameterizedBenchmark::new(
            "items",
            move |b: &mut Bencher, &len: &usize| benchmark(b, len),
            item_counts,
        )
        .throughput(|s| Throughput::Elements(*s as u32))
        .plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic))
        .sample_size(SAMPLE_SIZE),
    );
}

pub fn bench_storage(c: &mut Criterion) {
    exonum_crypto::init();
    // MapIndex
    bench_fn(c, "plain_map/insert", plain_map_index_insert);
    bench_fn(c, "plain_map/iter", plain_map_index_iter);
    bench_fn(
        c,
        "plain_map_with_family/insert",
        plain_map_index_with_family_insert,
    );
    bench_fn(
        c,
        "plain_map_with_family/iter",
        plain_map_index_with_family_iter,
    );
    bench_fn(c, "plain_map/read", plain_map_index_read);
    bench_fn(
        c,
        "plain_map_with_family/read",
        plain_map_index_with_family_read,
    );
    // ProofListIndex
    bench_fn(c, "proof_list/append", proof_list_append);
    // ProofMapIndex
    bench_fn(
        c,
        "proof_map/insert/no_merge",
        proof_map_insert_without_merge,
    );
    bench_fn(c, "proof_map/insert/merge", proof_map_insert_with_merge);
    bench_fn(c, "proof_map/proofs/build", proof_map_index_build_proofs);
    bench_fn(
        c,
        "proof_map/proofs/validate",
        proof_map_index_verify_proofs,
    );
}
<|endoftext|>


<commit_before>use std::io::{BufReader, Result};
use std::net::TcpStream;
use std::time::Duration;

use birch::network::NetworkConnection;
use birch::socket::IrcReader;

struct IrcSocket<'a> {
    stream_factory: &'a dyn Fn(usize) -> Result<TcpStream>,
}

impl<'a> IrcSocket<'a> {
    fn new(stream_factory: &'a dyn Fn(usize) -> Result<TcpStream>) -> Self {
        Self { stream_factory }
    }

    fn start(&mut self) -> Result<()> {
        let factory = self.stream_factory;

        loop {
            let mut stream = factory(0)?;
            let mut reader = BufReader::new(stream.try_clone()?);
            let mut network = NetworkConnection::new("ep`", &mut stream);

            network.initialize()?;
            loop {
                let msg = reader.read_message();
                if let Ok(msg) = msg {
                    println!("[birch <- \u{1b}[37;1mnet\u{1b}[0m] {}", msg);
                    network.handle(&msg)?;
                } else {
                    println!("read failed");
                    break;
                }
            }
        }

        Ok(())
    }
}

fn main() -> Result<()> {
    let stream_factory = |_attempt| {
        // Hardcoding things for now just to test everything out.
        let stream = TcpStream::connect("irc.freenode.net:6667")?;
        stream.set_read_timeout(Some(Duration::from_secs(180)))?;

        Ok(stream)
    };

    let mut sock = IrcSocket::new(&stream_factory);
    sock.start()
}
<commit_msg>Add config to IrcSocket<commit_after>use std::io::{BufReader, Result};
use std::net::TcpStream;
use std::time::Duration;

use birch::network::NetworkConnection;
use birch::socket::IrcReader;

struct IrcSocketConfig<'a> {
    nick: &'a str,
    addr: &'a str,
    max_retries: Option<usize>,
}

struct IrcSocket<'a> {
    config: IrcSocketConfig<'a>,
}

impl<'a> IrcSocket<'a> {
    fn new(config: IrcSocketConfig<'a>) -> Self {
        Self { config }
    }

    // TODO: this is kind of gross, clean this up
    fn create_stream(&self) -> Result<TcpStream> {
        let _create_stream = || {
            let stream = TcpStream::connect(self.config.addr)?;
            stream.set_read_timeout(Some(Duration::from_secs(180)))?;
            Ok(stream)
        };

        let max_retries = self.config.max_retries;

        let mut i = 0;
        loop {
            let stream = _create_stream();
            let over_max_tries = max_retries.map(|max| i > max).unwrap_or(false);

            if stream.is_ok() || over_max_tries {
                return stream;
            }

            i += 1
        }
    }

    /// On connection close, return `true` when the connection should
    /// be restarted, and false otherwise. If there is a
    /// non-recoverable exception, return the error.
    ///
    /// TODO: Need to come up with the clean exit concept.
    fn connect(&self) -> Result<bool> {
        let mut stream = self.create_stream()?;
        let mut reader = BufReader::new(stream.try_clone()?);
        let mut network = NetworkConnection::new(self.config.nick, &mut stream);

        if network.initialize().is_err() {
            return Ok(true);
        }

        loop {
            let result = reader.read_message().and_then(|msg| {
                println!("[birch <- \u{1b}[37;1mnet\u{1b}[0m] {}", msg);
                network.handle(&msg)
            });

            if result.is_err() {
                println!("read failed");
                break;
            }
        }

        Ok(true)
    }

    fn start_loop(&mut self) -> Result<()> {
        loop {
            match self.connect() {
                Ok(true) => println!("connection terminated, restarting"),
                Ok(false) => break,
                Err(err) => {
                    println!("connection failed: {:?}", err);
                    return Err(err);
                }
            }
        }

        Ok(())
    }
}

fn main() -> Result<()> {
    let config = IrcSocketConfig {
        nick: "ep`",
        addr: "irc.freenode.net:6667",
        max_retries: Some(3),
    };

    let mut sock = IrcSocket::new(config);
    sock.start_loop()
}
<|endoftext|>


<commit_before>//! Defines the `IntoIter` owned iterator for arrays.

use crate::{
    fmt,
    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
    mem::{self, MaybeUninit},
    ops::Range,
    ptr,
};
use super::LengthAtMost32;

/// A by-value [array] iterator.
///
/// [array]: ../../std/primitive.array.html
#[unstable(feature = "array_value_iter", issue = "65798")]
pub struct IntoIter<T, const N: usize>
where
    [T; N]: LengthAtMost32,
{
    /// This is the array we are iterating over.
    ///
    /// Elements with index `i` where `alive.start <= i < alive.end` have not
    /// been yielded yet and are valid array entries. Elements with indices `i
    /// < alive.start` or `i >= alive.end` have been yielded already and must
    /// not be accessed anymore! Those dead elements might even be in a
    /// completely uninitialized state!
    ///
    /// So the invariants are:
    /// - `data[alive]` is alive (i.e. contains valid elements)
    /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
    ///   elements were already read and must not be touched anymore!)
    data: [MaybeUninit<T>; N],

    /// The elements in `data` that have not been yielded yet.
    ///
    /// Invariants:
    /// - `alive.start <= alive.end`
    /// - `alive.end <= N`
    alive: Range<usize>,
}

impl<T, const N: usize> IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    /// Creates a new iterator over the given `array`.
    ///
    /// *Note*: this method might never get stabilized and/or removed in the
    /// future as there will likely be another, preferred way of obtaining this
    /// iterator (either via `IntoIterator` for arrays or via another way).
    #[unstable(feature = "array_value_iter", issue = "65798")]
    pub fn new(array: [T; N]) -> Self {
        // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
        // promise:
        //
        // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
        // > as `T`.
        //
        // The docs even show a transmute from an array of `MaybeUninit<T>` to
        // an array of `T`.
        //
        // With that, this initialization satisfies the invariants.

        // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
        // works with const generics:
        //     `mem::transmute::<[T; {N}], [MaybeUninit<T>; {N}]>(array)`
        //
        // Until then, we do it manually here. We first create a bitwise copy
        // but cast the pointer so that it is treated as a different type. Then
        // we forget `array` so that it is not dropped.
        let data = unsafe {
            let data = ptr::read(&array as *const [T; N] as *const [MaybeUninit<T>; N]);
            mem::forget(array);
            data
        };

        Self {
            data,
            alive: 0..N,
        }
    }

    /// Returns an immutable slice of all elements that have not been yielded
    /// yet.
    fn as_slice(&self) -> &[T] {
        let slice = &self.data[self.alive.clone()];
        // SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
        // the size and alignment of `T`. Furthermore, we know that all
        // elements within `alive` are properly initialized.
        unsafe {
            mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Iterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        if self.alive.start == self.alive.end {
            return None;
        }

        // Bump start index.
        //
        // From the check above we know that `alive.start != alive.end`.
        // Combine this with the invariant `alive.start <= alive.end`, we know
        // that `alive.start < alive.end`. Increasing `alive.start` by 1
        // maintains the invariant regarding `alive`. However, due to this
        // change, for a short time, the alive zone is not `data[alive]`
        // anymore, but `data[idx..alive.end]`.
        let idx = self.alive.start;
        self.alive.start += 1;

        // Read the element from the array.
        // SAFETY: This is safe: `idx` is an index
        // into the "alive" region of the array. Reading this element means
        // that `data[idx]` is regarded as dead now (i.e. do not touch). As
        // `idx` was the start of the alive-zone, the alive zone is now
        // `data[alive]` again, restoring all invariants.
        let out = unsafe { self.data.get_unchecked(idx).read() };

        Some(out)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len();
        (len, Some(len))
    }

    fn count(self) -> usize {
        self.len()
    }

    fn last(mut self) -> Option<Self::Item> {
        self.next_back()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.alive.start == self.alive.end {
            return None;
        }

        // Decrease end index.
        //
        // From the check above we know that `alive.start != alive.end`.
        // Combine this with the invariant `alive.start <= alive.end`, we know
        // that `alive.start < alive.end`. As `alive.start` cannot be negative,
        // `alive.end` is at least 1, meaning that we can safely decrement it
        // by one. This also maintains the invariant `alive.start <=
        // alive.end`. However, due to this change, for a short time, the alive
        // zone is not `data[alive]` anymore, but `data[alive.start..alive.end
        // + 1]`.
        self.alive.end -= 1;

        // Read the element from the array.
        // SAFETY: This is safe: `alive.end` is an
        // index into the "alive" region of the array. Compare the previous
        // comment that states that the alive region is
        // `data[alive.start..alive.end + 1]`. Reading this element means that
        // `data[alive.end]` is regarded as dead now (i.e. do not touch). As
        // `alive.end` was the end of the alive-zone, the alive zone is now
        // `data[alive]` again, restoring all invariants.
        let out = unsafe { self.data.get_unchecked(self.alive.end).read() };

        Some(out)
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Drop for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn drop(&mut self) {
        // We simply drop each element via `for_each`. This should not incur
        // any significant runtime overhead and avoids adding another `unsafe`
        // block.
        self.by_ref().for_each(drop);
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn len(&self) -> usize {
        // Will never underflow due to the invariant `alive.start <=
        // alive.end`.
        self.alive.end - self.alive.start
    }
    fn is_empty(&self) -> bool {
        self.alive.is_empty()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> FusedIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{}

// The iterator indeed reports the correct length. The number of "alive"
// elements (that will still be yielded) is the length of the range `alive`.
// This range is decremented in length in either `next` or `next_back`. It is
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn clone(&self) -> Self {
        // SAFETY: each point of unsafety is documented inside the unsafe block
        unsafe {
            // This creates a new uninitialized array. Note that the `assume_init`
            // refers to the array, not the individual elements. And it is Ok if
            // the array is in an uninitialized state as all elements may be
            // uninitialized (all bit patterns are valid). Compare the
            // `MaybeUninit` docs for more information.
            let mut new_data: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init();

            // Clone all alive elements.
            for idx in self.alive.clone() {
                // The element at `idx` in the old array is alive, so we can
                // safely call `get_ref()`. We then clone it, and write the
                // clone into the new array.
                let clone = self.data.get_unchecked(idx).get_ref().clone();
                new_data.get_unchecked_mut(idx).write(clone);
            }

            Self {
                data: new_data,
                alive: self.alive.clone(),
            }
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Only print the elements that were not yielded yet: we cannot
        // access the yielded elements anymore.
        f.debug_tuple("IntoIter")
            .field(&self.as_slice())
            .finish()
    }
}
<commit_msg>Auto merge of #65821 - SimonSapin:in-place, r=Amanieu<commit_after>//! Defines the `IntoIter` owned iterator for arrays.

use crate::{
    fmt,
    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
    mem::{self, MaybeUninit},
    ops::Range,
    ptr,
};
use super::LengthAtMost32;

/// A by-value [array] iterator.
///
/// [array]: ../../std/primitive.array.html
#[unstable(feature = "array_value_iter", issue = "65798")]
pub struct IntoIter<T, const N: usize>
where
    [T; N]: LengthAtMost32,
{
    /// This is the array we are iterating over.
    ///
    /// Elements with index `i` where `alive.start <= i < alive.end` have not
    /// been yielded yet and are valid array entries. Elements with indices `i
    /// < alive.start` or `i >= alive.end` have been yielded already and must
    /// not be accessed anymore! Those dead elements might even be in a
    /// completely uninitialized state!
    ///
    /// So the invariants are:
    /// - `data[alive]` is alive (i.e. contains valid elements)
    /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
    ///   elements were already read and must not be touched anymore!)
    data: [MaybeUninit<T>; N],

    /// The elements in `data` that have not been yielded yet.
    ///
    /// Invariants:
    /// - `alive.start <= alive.end`
    /// - `alive.end <= N`
    alive: Range<usize>,
}

impl<T, const N: usize> IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    /// Creates a new iterator over the given `array`.
    ///
    /// *Note*: this method might never get stabilized and/or removed in the
    /// future as there will likely be another, preferred way of obtaining this
    /// iterator (either via `IntoIterator` for arrays or via another way).
    #[unstable(feature = "array_value_iter", issue = "65798")]
    pub fn new(array: [T; N]) -> Self {
        // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
        // promise:
        //
        // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
        // > as `T`.
        //
        // The docs even show a transmute from an array of `MaybeUninit<T>` to
        // an array of `T`.
        //
        // With that, this initialization satisfies the invariants.

        // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
        // works with const generics:
        //     `mem::transmute::<[T; {N}], [MaybeUninit<T>; {N}]>(array)`
        //
        // Until then, we do it manually here. We first create a bitwise copy
        // but cast the pointer so that it is treated as a different type. Then
        // we forget `array` so that it is not dropped.
        let data = unsafe {
            let data = ptr::read(&array as *const [T; N] as *const [MaybeUninit<T>; N]);
            mem::forget(array);
            data
        };

        Self {
            data,
            alive: 0..N,
        }
    }

    /// Returns an immutable slice of all elements that have not been yielded
    /// yet.
    fn as_slice(&self) -> &[T] {
        let slice = &self.data[self.alive.clone()];
        // SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
        // the size and alignment of `T`. Furthermore, we know that all
        // elements within `alive` are properly initialized.
        unsafe {
            mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
        }
    }

    /// Returns a mutable slice of all elements that have not been yielded yet.
    fn as_mut_slice(&mut self) -> &mut [T] {
        // This transmute is safe, same as in `as_slice` above.
        let slice = &mut self.data[self.alive.clone()];
        // SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
        // the size and alignment of `T`. Furthermore, we know that all
        // elements within `alive` are properly initialized.
        unsafe {
            mem::transmute::<&mut [MaybeUninit<T>], &mut [T]>(slice)
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Iterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        if self.alive.start == self.alive.end {
            return None;
        }

        // Bump start index.
        //
        // From the check above we know that `alive.start != alive.end`.
        // Combine this with the invariant `alive.start <= alive.end`, we know
        // that `alive.start < alive.end`. Increasing `alive.start` by 1
        // maintains the invariant regarding `alive`. However, due to this
        // change, for a short time, the alive zone is not `data[alive]`
        // anymore, but `data[idx..alive.end]`.
        let idx = self.alive.start;
        self.alive.start += 1;

        // Read the element from the array.
        // SAFETY: This is safe: `idx` is an index
        // into the "alive" region of the array. Reading this element means
        // that `data[idx]` is regarded as dead now (i.e. do not touch). As
        // `idx` was the start of the alive-zone, the alive zone is now
        // `data[alive]` again, restoring all invariants.
        let out = unsafe { self.data.get_unchecked(idx).read() };

        Some(out)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len();
        (len, Some(len))
    }

    fn count(self) -> usize {
        self.len()
    }

    fn last(mut self) -> Option<Self::Item> {
        self.next_back()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.alive.start == self.alive.end {
            return None;
        }

        // Decrease end index.
        //
        // From the check above we know that `alive.start != alive.end`.
        // Combine this with the invariant `alive.start <= alive.end`, we know
        // that `alive.start < alive.end`. As `alive.start` cannot be negative,
        // `alive.end` is at least 1, meaning that we can safely decrement it
        // by one. This also maintains the invariant `alive.start <=
        // alive.end`. However, due to this change, for a short time, the alive
        // zone is not `data[alive]` anymore, but `data[alive.start..alive.end
        // + 1]`.
        self.alive.end -= 1;

        // Read the element from the array.
        // SAFETY: This is safe: `alive.end` is an
        // index into the "alive" region of the array. Compare the previous
        // comment that states that the alive region is
        // `data[alive.start..alive.end + 1]`. Reading this element means that
        // `data[alive.end]` is regarded as dead now (i.e. do not touch). As
        // `alive.end` was the end of the alive-zone, the alive zone is now
        // `data[alive]` again, restoring all invariants.
        let out = unsafe { self.data.get_unchecked(self.alive.end).read() };

        Some(out)
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Drop for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn drop(&mut self) {
        // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
        // of elements that have not been moved out yet and that remain
        // to be dropped.
        unsafe {
            ptr::drop_in_place(self.as_mut_slice())
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn len(&self) -> usize {
        // Will never underflow due to the invariant `alive.start <=
        // alive.end`.
        self.alive.end - self.alive.start
    }
    fn is_empty(&self) -> bool {
        self.alive.is_empty()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> FusedIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{}

// The iterator indeed reports the correct length. The number of "alive"
// elements (that will still be yielded) is the length of the range `alive`.
// This range is decremented in length in either `next` or `next_back`. It is
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn clone(&self) -> Self {
        // SAFETY: each point of unsafety is documented inside the unsafe block
        unsafe {
            // This creates a new uninitialized array. Note that the `assume_init`
            // refers to the array, not the individual elements. And it is Ok if
            // the array is in an uninitialized state as all elements may be
            // uninitialized (all bit patterns are valid). Compare the
            // `MaybeUninit` docs for more information.
            let mut new_data: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init();

            // Clone all alive elements.
            for idx in self.alive.clone() {
                // The element at `idx` in the old array is alive, so we can
                // safely call `get_ref()`. We then clone it, and write the
                // clone into the new array.
                let clone = self.data.get_unchecked(idx).get_ref().clone();
                new_data.get_unchecked_mut(idx).write(clone);
            }

            Self {
                data: new_data,
                alive: self.alive.clone(),
            }
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Only print the elements that were not yielded yet: we cannot
        // access the yielded elements anymore.
        f.debug_tuple("IntoIter")
            .field(&self.as_slice())
            .finish()
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of Rust panics via process aborts
//!
//! When compared to the implementation via unwinding, this crate is *much*
//! simpler! That being said, it's not quite as versatile, but here goes!

#![no_std]
#![unstable(feature = "panic_abort", issue = "32837")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
#![panic_runtime]
#![allow(unused_features)]

#![feature(core_intrinsics)]
#![feature(libc)]
#![feature(nll)]
#![feature(panic_runtime)]
#![feature(staged_api)]
#![feature(rustc_attrs)]

// Rust's "try" function, but if we're aborting on panics we just call the
// function as there's nothing else we need to do here.
#[rustc_std_internal_symbol]
pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8),
                                              data: *mut u8,
                                              _data_ptr: *mut usize,
                                              _vtable_ptr: *mut usize) -> u32 {
    f(data);
    0
}

// "Leak" the payload and shim to the relevant abort on the platform in
// question.
//
// For Unix we just use `abort` from libc as it'll trigger debuggers, core
// dumps, etc, as one might expect. On Windows, however, the best option we have
// is the `__fastfail` intrinsics, but that's unfortunately not defined in LLVM,
// and the `RaiseFailFastException` function isn't available until Windows 7
// which would break compat with XP. For now just use `intrinsics::abort` which
// will kill us with an illegal instruction, which will do a good enough job for
// now hopefully.
#[rustc_std_internal_symbol]
pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 {
    abort();

    #[cfg(any(unix, target_os = "cloudabi"))]
    unsafe fn abort() -> ! {
        extern crate libc;
        libc::abort();
    }

    #[cfg(any(target_os = "redox",
              windows,
              all(target_arch = "wasm32", not(target_os = "emscripten"))))]
    unsafe fn abort() -> ! {
        core::intrinsics::abort();
    }
}

// This... is a bit of an oddity. The tl;dr; is that this is required to link
// correctly, the longer explanation is below.
//
// Right now the binaries of libcore/libstd that we ship are all compiled with
// `-C panic=unwind`. This is done to ensure that the binaries are maximally
// compatible with as many situations as possible. The compiler, however,
// requires a "personality function" for all functions compiled with `-C
// panic=unwind`. This personality function is hardcoded to the symbol
// `rust_eh_personality` and is defined by the `eh_personality` lang item.
//
// So... why not just define that lang item here? Good question! The way that
// panic runtimes are linked in is actually a little subtle in that they're
// "sort of" in the compiler's crate store, but only actually linked if another
// isn't actually linked. This ends up meaning that both this crate and the
// panic_unwind crate can appear in the compiler's crate store, and if both
// define the `eh_personality` lang item then that'll hit an error.
//
// To handle this the compiler only requires the `eh_personality` is defined if
// the panic runtime being linked in is the unwinding runtime, and otherwise
// it's not required to be defined (rightfully so). In this case, however, this
// library just defines this symbol so there's at least some personality
// somewhere.
//
// Essentially this symbol is just defined to get wired up to libcore/libstd
// binaries, but it should never be called as we don't link in an unwinding
// runtime at all.
pub mod personalities {
    #[no_mangle]
    #[cfg(not(any(
        target_arch = "wasm32",
        all(
            target_os = "windows",
            target_env = "gnu",
            target_arch = "x86_64",
        ),
    )))]
    pub extern fn rust_eh_personality() {}

    // On x86_64-pc-windows-gnu we use our own personality function that needs
    // to return `ExceptionContinueSearch` as we're passing on all our frames.
    #[no_mangle]
    #[cfg(all(target_os = "windows",
              target_env = "gnu",
              target_arch = "x86_64"))]
    pub extern fn rust_eh_personality(_record: usize,
                                      _frame: usize,
                                      _context: usize,
                                      _dispatcher: usize) -> u32 {
        1 // `ExceptionContinueSearch`
    }

    // Similar to above, this corresponds to the `eh_unwind_resume` lang item
    // that's only used on Windows currently.
    //
    // Note that we don't execute landing pads, so this is never called, so it's
    // body is empty.
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu"))]
    pub extern fn rust_eh_unwind_resume() {}

    // These two are called by our startup objects on i686-pc-windows-gnu, but
    // they don't need to do anything so the bodies are nops.
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern fn rust_eh_register_frames() {}
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern fn rust_eh_unregister_frames() {}
}
<commit_msg>wasm32-unknown-emscripten expects the rust_eh_personality symbol<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of Rust panics via process aborts
//!
//! When compared to the implementation via unwinding, this crate is *much*
//! simpler! That being said, it's not quite as versatile, but here goes!

#![no_std]
#![unstable(feature = "panic_abort", issue = "32837")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
#![panic_runtime]
#![allow(unused_features)]

#![feature(core_intrinsics)]
#![feature(libc)]
#![feature(nll)]
#![feature(panic_runtime)]
#![feature(staged_api)]
#![feature(rustc_attrs)]

// Rust's "try" function, but if we're aborting on panics we just call the
// function as there's nothing else we need to do here.
#[rustc_std_internal_symbol]
pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8),
                                              data: *mut u8,
                                              _data_ptr: *mut usize,
                                              _vtable_ptr: *mut usize) -> u32 {
    f(data);
    0
}

// "Leak" the payload and shim to the relevant abort on the platform in
// question.
//
// For Unix we just use `abort` from libc as it'll trigger debuggers, core
// dumps, etc, as one might expect. On Windows, however, the best option we have
// is the `__fastfail` intrinsics, but that's unfortunately not defined in LLVM,
// and the `RaiseFailFastException` function isn't available until Windows 7
// which would break compat with XP. For now just use `intrinsics::abort` which
// will kill us with an illegal instruction, which will do a good enough job for
// now hopefully.
#[rustc_std_internal_symbol]
pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 {
    abort();

    #[cfg(any(unix, target_os = "cloudabi"))]
    unsafe fn abort() -> ! {
        extern crate libc;
        libc::abort();
    }

    #[cfg(any(target_os = "redox",
              windows,
              all(target_arch = "wasm32", not(target_os = "emscripten"))))]
    unsafe fn abort() -> ! {
        core::intrinsics::abort();
    }
}

// This... is a bit of an oddity. The tl;dr; is that this is required to link
// correctly, the longer explanation is below.
//
// Right now the binaries of libcore/libstd that we ship are all compiled with
// `-C panic=unwind`. This is done to ensure that the binaries are maximally
// compatible with as many situations as possible. The compiler, however,
// requires a "personality function" for all functions compiled with `-C
// panic=unwind`. This personality function is hardcoded to the symbol
// `rust_eh_personality` and is defined by the `eh_personality` lang item.
//
// So... why not just define that lang item here? Good question! The way that
// panic runtimes are linked in is actually a little subtle in that they're
// "sort of" in the compiler's crate store, but only actually linked if another
// isn't actually linked. This ends up meaning that both this crate and the
// panic_unwind crate can appear in the compiler's crate store, and if both
// define the `eh_personality` lang item then that'll hit an error.
//
// To handle this the compiler only requires the `eh_personality` is defined if
// the panic runtime being linked in is the unwinding runtime, and otherwise
// it's not required to be defined (rightfully so). In this case, however, this
// library just defines this symbol so there's at least some personality
// somewhere.
//
// Essentially this symbol is just defined to get wired up to libcore/libstd
// binaries, but it should never be called as we don't link in an unwinding
// runtime at all.
pub mod personalities {
    #[no_mangle]
    #[cfg(not(any(
        all(
            target_arch = "wasm32",
            not(target_os = "emscripten"),
        ),
        all(
            target_os = "windows",
            target_env = "gnu",
            target_arch = "x86_64",
        ),
    )))]
    pub extern fn rust_eh_personality() {}

    // On x86_64-pc-windows-gnu we use our own personality function that needs
    // to return `ExceptionContinueSearch` as we're passing on all our frames.
    #[no_mangle]
    #[cfg(all(target_os = "windows",
              target_env = "gnu",
              target_arch = "x86_64"))]
    pub extern fn rust_eh_personality(_record: usize,
                                      _frame: usize,
                                      _context: usize,
                                      _dispatcher: usize) -> u32 {
        1 // `ExceptionContinueSearch`
    }

    // Similar to above, this corresponds to the `eh_unwind_resume` lang item
    // that's only used on Windows currently.
    //
    // Note that we don't execute landing pads, so this is never called, so it's
    // body is empty.
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu"))]
    pub extern fn rust_eh_unwind_resume() {}

    // These two are called by our startup objects on i686-pc-windows-gnu, but
    // they don't need to do anything so the bodies are nops.
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern fn rust_eh_register_frames() {}
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern fn rust_eh_unregister_frames() {}
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use io;
use libc::{self, c_int, size_t, c_void};
use mem;
use sys::cvt;
use sys_common::AsInner;

pub struct FileDesc {
    fd: c_int,
}

impl FileDesc {
    pub fn new(fd: c_int) -> FileDesc {
        FileDesc { fd: fd }
    }

    pub fn raw(&self) -> c_int { self.fd }

    /// Extracts the actual filedescriptor without closing it.
    pub fn into_raw(self) -> c_int {
        let fd = self.fd;
        mem::forget(self);
        fd
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = try!(cvt(unsafe {
            libc::read(self.fd,
                       buf.as_mut_ptr() as *mut c_void,
                       buf.len() as size_t)
        }));
        Ok(ret as usize)
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        let ret = try!(cvt(unsafe {
            libc::write(self.fd,
                        buf.as_ptr() as *const c_void,
                        buf.len() as size_t)
        }));
        Ok(ret as usize)
    }

    #[cfg(not(target_env = "newlib"))]
    pub fn set_cloexec(&self) {
        unsafe {
            let ret = libc::ioctl(self.fd, libc::FIOCLEX);
            debug_assert_eq!(ret, 0);
        }
    }
    #[cfg(target_env = "newlib")]
    pub fn set_cloexec(&self) {
        unsafe {
            let previous = libc::fnctl(self.fd, libc::F_GETFD);
            let ret = libc::fnctl(self.fd, libc::F_SETFD, previous | libc::FD_CLOEXEC);
            debug_assert_eq!(ret, 0);
        }
    }
}

impl AsInner<c_int> for FileDesc {
    fn as_inner(&self) -> &c_int { &self.fd }
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        // Note that errors are ignored when closing a file descriptor. The
        // reason for this is that if an error occurs we don't actually know if
        // the file descriptor was closed or not, and if we retried (for
        // something like EINTR), we might close another valid file descriptor
        // (opened after we closed ours.
        let _ = unsafe { libc::close(self.fd) };
    }
}
<commit_msg>Auto merge of #30270 - DiamondLovesYou:fix-30231, r=alexcrichton<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use io;
use libc::{self, c_int, size_t, c_void};
use mem;
use sys::cvt;
use sys_common::AsInner;

pub struct FileDesc {
    fd: c_int,
}

impl FileDesc {
    pub fn new(fd: c_int) -> FileDesc {
        FileDesc { fd: fd }
    }

    pub fn raw(&self) -> c_int { self.fd }

    /// Extracts the actual filedescriptor without closing it.
    pub fn into_raw(self) -> c_int {
        let fd = self.fd;
        mem::forget(self);
        fd
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = try!(cvt(unsafe {
            libc::read(self.fd,
                       buf.as_mut_ptr() as *mut c_void,
                       buf.len() as size_t)
        }));
        Ok(ret as usize)
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        let ret = try!(cvt(unsafe {
            libc::write(self.fd,
                        buf.as_ptr() as *const c_void,
                        buf.len() as size_t)
        }));
        Ok(ret as usize)
    }

    #[cfg(not(target_env = "newlib"))]
    pub fn set_cloexec(&self) {
        unsafe {
            let ret = libc::ioctl(self.fd, libc::FIOCLEX);
            debug_assert_eq!(ret, 0);
        }
    }
    #[cfg(target_env = "newlib")]
    pub fn set_cloexec(&self) {
        unsafe {
            let previous = libc::fcntl(self.fd, libc::F_GETFD);
            let ret = libc::fcntl(self.fd, libc::F_SETFD, previous | libc::FD_CLOEXEC);
            debug_assert_eq!(ret, 0);
        }
    }
}

impl AsInner<c_int> for FileDesc {
    fn as_inner(&self) -> &c_int { &self.fd }
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        // Note that errors are ignored when closing a file descriptor. The
        // reason for this is that if an error occurs we don't actually know if
        // the file descriptor was closed or not, and if we retried (for
        // something like EINTR), we might close another valid file descriptor
        // (opened after we closed ours.
        let _ = unsafe { libc::close(self.fd) };
    }
}
<|endoftext|>


<commit_before>//! LR(1) state construction algorithm.

use kernel_set;
use grammar::repr::*;
use lr1::core::*;
use lr1::first;
use lr1::lookahead::Lookahead;
use std::rc::Rc;
use tls::Tls;
use util::{map, Multimap, Set};

#[cfg(test)] mod test;

pub fn build_lr1_states<'grammar>(grammar: &'grammar Grammar,
                                  start: NonterminalString)
                                  -> Result<Vec<State<'grammar>>,
                                            TableConstructionError<'grammar>>
{
    let lr1 = LR1::new(grammar);
    lr1.build_states(start)
}

struct LR1<'grammar> {
    grammar: &'grammar Grammar,
    first_sets: first::FirstSets,
}

impl<'grammar> LR1<'grammar> {
    fn new(grammar: &'grammar Grammar) -> Self {
        LR1 {
            grammar: grammar,
            first_sets: first::FirstSets::new(grammar),
        }
    }

    fn build_states(&self, start_nt: NonterminalString)
                    -> Result<Vec<State<'grammar>>, TableConstructionError<'grammar>>
    {
        let session = Tls::session();
        let mut kernel_set = kernel_set::KernelSet::new();
        let mut states = vec![];
        let mut errors = 0;

        // create the starting state
        kernel_set.add_state(
            self.transitive_closure(
                self.items(start_nt, 0, Lookahead::EOF)));

        while let Some(items) = kernel_set.next() {
            let index = StateIndex(states.len());

            if index.0 % 10000 == 0 && index.0 > 0 {
                log!(session, Verbose, "{} states created so far.", index.0);
            }

            let mut this_state = State { index: index, items: items.clone(),
                                         tokens: map(), gotos: map(),
                                         conflicts: map() };

            // group the items that we can transition into by shifting
            // over a term or nonterm
            let transitions: Multimap<Symbol, Item<'grammar>> =
                items.vec
                     .iter()
                     .filter_map(|item| item.shifted_item())
                     .collect();

            for (symbol, items) in transitions.into_iter() {
                let items = self.transitive_closure(items);
                let next_state = kernel_set.add_state(items);

                match symbol {
                    Symbol::Terminal(s) => {
                        let action = Action::Shift(next_state);
                        let prev = this_state.tokens.insert(Lookahead::Terminal(s), action);
                        assert!(prev.is_none()); // cannot have a shift/shift conflict
                    }

                    Symbol::Nonterminal(s) => {
                        let prev = this_state.gotos.insert(s, next_state);
                        assert!(prev.is_none());
                    }
                }
            }

            // finally, consider the reductions
            for item in items.vec.iter().filter(|i| i.can_reduce()) {
                let action = Action::Reduce(item.production);
                let prev = this_state.tokens.insert(item.lookahead, action);
                if let Some(conflict) = prev {
                    log!(session, Verbose, "Encountered conflict in state {}",
                         index.0);
                    this_state.conflicts.entry(item.lookahead)
                                        .or_insert(vec![])
                                        .push(Conflict {
                                            state: index,
                                            production: item.production,
                                            action: conflict,
                                        });
                    errors += 1;
                }
            }

            // extract a new state
            states.push(this_state);

            if session.stop_after(errors) {
                log!(session, Verbose,
                     "{} conflicts encountered, stopping.", errors);
                break;
            }
        }

        if states.iter().any(|s| !s.conflicts.is_empty()) {
            Err(TableConstructionError { states: states })
        } else {
            Ok(states)
        }
    }

    fn items(&self,
             id: NonterminalString,
             index: usize,
             lookahead: Lookahead)
             -> Vec<Item<'grammar>>
    {
        self.grammar.productions_for(id)
                    .iter()
                    .map(|production| {
                        debug_assert!(index <= production.symbols.len());
                        Item { production: production,
                                        index: index,
                                        lookahead: lookahead }
                    })
                    .collect()
    }

    // expands `state` with epsilon moves
    fn transitive_closure(&self, mut items: Vec<Item<'grammar>>)
                          -> Items<'grammar>
    {
        let mut counter = 0;

        let mut set: Set<Item<'grammar>> =
            items.iter().cloned().collect();

        while counter < items.len() {
            let new_items: Vec<_> =
                items[counter..]
                .iter()
                .filter_map(|item| {
                    let shift_symbol = item.shift_symbol();
                    match shift_symbol {
                        None => None, // requires a reduce
                        Some((Symbol::Terminal(_), _)) => None, // requires a shift
                        Some((Symbol::Nonterminal(nt), remainder)) => {
                            Some((nt, remainder, item.lookahead))
                        }
                    }
                })
                .flat_map(|(nt, remainder, lookahead)| {
                    let (first_set, _) =
                        self.first_sets.first(self.grammar, remainder, lookahead);
                    first_set.iter(self.grammar)
                             .flat_map(|l| self.items(nt, 0, l))
                             .collect::<Vec<_>>()
                })
                .filter(|&item| set.insert(item))
                .collect();

            counter = items.len();
            items.extend(new_items);
        }

        items.sort();
        items.dedup();

        Items { vec: Rc::new(items) }
    }
}

<commit_msg>Make status updates appear more often<commit_after>//! LR(1) state construction algorithm.

use kernel_set;
use grammar::repr::*;
use lr1::core::*;
use lr1::first;
use lr1::lookahead::Lookahead;
use std::rc::Rc;
use tls::Tls;
use util::{map, Multimap, Set};

#[cfg(test)] mod test;

pub fn build_lr1_states<'grammar>(grammar: &'grammar Grammar,
                                  start: NonterminalString)
                                  -> Result<Vec<State<'grammar>>,
                                            TableConstructionError<'grammar>>
{
    let lr1 = LR1::new(grammar);
    lr1.build_states(start)
}

struct LR1<'grammar> {
    grammar: &'grammar Grammar,
    first_sets: first::FirstSets,
}

impl<'grammar> LR1<'grammar> {
    fn new(grammar: &'grammar Grammar) -> Self {
        LR1 {
            grammar: grammar,
            first_sets: first::FirstSets::new(grammar),
        }
    }

    fn build_states(&self, start_nt: NonterminalString)
                    -> Result<Vec<State<'grammar>>, TableConstructionError<'grammar>>
    {
        let session = Tls::session();
        let mut kernel_set = kernel_set::KernelSet::new();
        let mut states = vec![];
        let mut errors = 0;

        // create the starting state
        kernel_set.add_state(
            self.transitive_closure(
                self.items(start_nt, 0, Lookahead::EOF)));

        while let Some(items) = kernel_set.next() {
            let index = StateIndex(states.len());

            if index.0 % 5000 == 0 && index.0 > 0 {
                log!(session, Verbose, "{} states created so far.", index.0);
            }

            let mut this_state = State { index: index, items: items.clone(),
                                         tokens: map(), gotos: map(),
                                         conflicts: map() };

            // group the items that we can transition into by shifting
            // over a term or nonterm
            let transitions: Multimap<Symbol, Item<'grammar>> =
                items.vec
                     .iter()
                     .filter_map(|item| item.shifted_item())
                     .collect();

            for (symbol, items) in transitions.into_iter() {
                let items = self.transitive_closure(items);
                let next_state = kernel_set.add_state(items);

                match symbol {
                    Symbol::Terminal(s) => {
                        let action = Action::Shift(next_state);
                        let prev = this_state.tokens.insert(Lookahead::Terminal(s), action);
                        assert!(prev.is_none()); // cannot have a shift/shift conflict
                    }

                    Symbol::Nonterminal(s) => {
                        let prev = this_state.gotos.insert(s, next_state);
                        assert!(prev.is_none());
                    }
                }
            }

            // finally, consider the reductions
            for item in items.vec.iter().filter(|i| i.can_reduce()) {
                let action = Action::Reduce(item.production);
                let prev = this_state.tokens.insert(item.lookahead, action);
                if let Some(conflict) = prev {
                    log!(session, Verbose, "Encountered conflict in state {}",
                         index.0);
                    this_state.conflicts.entry(item.lookahead)
                                        .or_insert(vec![])
                                        .push(Conflict {
                                            state: index,
                                            production: item.production,
                                            action: conflict,
                                        });
                    errors += 1;
                }
            }

            // extract a new state
            states.push(this_state);

            if session.stop_after(errors) {
                log!(session, Verbose,
                     "{} conflicts encountered, stopping.", errors);
                break;
            }
        }

        if states.iter().any(|s| !s.conflicts.is_empty()) {
            Err(TableConstructionError { states: states })
        } else {
            Ok(states)
        }
    }

    fn items(&self,
             id: NonterminalString,
             index: usize,
             lookahead: Lookahead)
             -> Vec<Item<'grammar>>
    {
        self.grammar.productions_for(id)
                    .iter()
                    .map(|production| {
                        debug_assert!(index <= production.symbols.len());
                        Item { production: production,
                                        index: index,
                                        lookahead: lookahead }
                    })
                    .collect()
    }

    // expands `state` with epsilon moves
    fn transitive_closure(&self, mut items: Vec<Item<'grammar>>)
                          -> Items<'grammar>
    {
        let mut counter = 0;

        let mut set: Set<Item<'grammar>> =
            items.iter().cloned().collect();

        while counter < items.len() {
            let new_items: Vec<_> =
                items[counter..]
                .iter()
                .filter_map(|item| {
                    let shift_symbol = item.shift_symbol();
                    match shift_symbol {
                        None => None, // requires a reduce
                        Some((Symbol::Terminal(_), _)) => None, // requires a shift
                        Some((Symbol::Nonterminal(nt), remainder)) => {
                            Some((nt, remainder, item.lookahead))
                        }
                    }
                })
                .flat_map(|(nt, remainder, lookahead)| {
                    let (first_set, _) =
                        self.first_sets.first(self.grammar, remainder, lookahead);
                    first_set.iter(self.grammar)
                             .flat_map(|l| self.items(nt, 0, l))
                             .collect::<Vec<_>>()
                })
                .filter(|&item| set.insert(item))
                .collect();

            counter = items.len();
            items.extend(new_items);
        }

        items.sort();
        items.dedup();

        Items { vec: Rc::new(items) }
    }
}

<|endoftext|>