<commit_before>#![feature(test)]

extern crate test;
extern crate itertools;

use test::{black_box};
use itertools::Stride;
use itertools::Itertools;

#[cfg(feature = "unstable")]
use itertools::{ZipTrusted};

use itertools::ZipSlices;

use std::iter::repeat;
use std::cmp;
use std::cmp::Ordering;

#[bench]
fn slice_iter(b: &mut test::Bencher)
{
    let xs: Vec<_> = repeat(1i32).take(20).collect();
    b.iter(|| for elt in xs.iter() {
        test::black_box(elt);
    })
}

#[bench]
fn slice_iter_rev(b: &mut test::Bencher)
{
    let xs: Vec<_> = repeat(1i32).take(20).collect();
    b.iter(|| for elt in xs.iter().rev() {
        test::black_box(elt);
    })
}

#[bench]
fn stride_iter(b: &mut test::Bencher)
{
    let xs: Vec<_> = repeat(1i32).take(20).collect();
    b.iter(|| for elt in Stride::from_slice(&xs, 1) {
        test::black_box(elt);
    })
}

#[bench]
fn stride_iter_rev(b: &mut test::Bencher)
{
    let xs: Vec<_> = repeat(1i32).take(20).collect();
    b.iter(|| for elt in Stride::from_slice(&xs, 1).rev() {
        test::black_box(elt);
    })
}

#[bench]
fn zip_default_zip(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        for (&x, &y) in xs.iter().zip(&ys) {
            test::black_box(x);
            test::black_box(y);
        }
    })
}

#[bench]
fn zip_default_zip3(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let zs = vec![0; 766];
    let xs = black_box(xs);
    let ys = black_box(ys);
    let zs = black_box(zs);

    b.iter(|| {
        for ((&x, &y), &z) in xs.iter().zip(&ys).zip(&zs) {
            test::black_box(x);
            test::black_box(y);
            test::black_box(z);
        }
    })
}

/*
#[bench]
fn zip_slices_ziptuple(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];

    b.iter(|| {
        let xs = black_box(&xs);
        let ys = black_box(&ys);
        for (&x, &y) in Zip::new((xs, ys)) {
            test::black_box(x);
            test::black_box(y);
        }
    })
}
*/

#[bench]
fn zip_slices(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        for (&x, &y) in ZipSlices::new(&xs, &ys) {
            test::black_box(x);
            test::black_box(y);
        }
    })
}

#[bench]
fn zip_slices_mut(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let mut ys = black_box(ys);

    b.iter(|| {
        for (&x, &mut y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) {
            test::black_box(x);
            test::black_box(y);
        }
    })
}

#[cfg(feature = "unstable")]
#[bench]
fn ziptrusted(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        for (&x, &y) in ZipTrusted::new((xs.iter(), ys.iter())) {
            test::black_box(x);
            test::black_box(y);
        }
    })
}

#[cfg(feature = "unstable")]
#[bench]
fn ziptrusted3(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let zs = vec![0; 766];
    let xs = black_box(xs);
    let ys = black_box(ys);
    let zs = black_box(zs);

    b.iter(|| {
        for (&x, &y, &z) in ZipTrusted::new((xs.iter(), ys.iter(), zs.iter())) {
            test::black_box(x);
            test::black_box(y);
            test::black_box(z);
        }
    })
}

#[bench]
fn zip_checked_counted_loop(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        // Must slice to equal lengths, and then bounds checks are eliminated!
        let len = cmp::min(xs.len(), ys.len());
        let xs = &xs[..len];
        let ys = &ys[..len];

        for i in 0..len {
            let x = xs[i];
            let y = ys[i];
            test::black_box(x);
            test::black_box(y);
        }
    })
}

#[bench]
fn zip_unchecked_counted_loop(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        let len = cmp::min(xs.len(), ys.len());
        for i in 0..len {
            unsafe {
            let x = *xs.get_unchecked(i);
            let y = *ys.get_unchecked(i);
            test::black_box(x);
            test::black_box(y);
            }
        }
    })
}

#[bench]
fn zip_unchecked_counted_loop3(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let zs = vec![0; 766];
    let xs = black_box(xs);
    let ys = black_box(ys);
    let zs = black_box(zs);

    b.iter(|| {
        let len = cmp::min(xs.len(), cmp::min(ys.len(), zs.len()));
        for i in 0..len {
            unsafe {
            let x = *xs.get_unchecked(i);
            let y = *ys.get_unchecked(i);
            let z = *zs.get_unchecked(i);
            test::black_box(x);
            test::black_box(y);
            test::black_box(z);
            }
        }
    })
}

#[bench]
fn group_by_lazy_1(b: &mut test::Bencher) {
    let mut data = vec![0; 1024];
    for (index, elt) in data.iter_mut().enumerate() {
        *elt = index / 10;
    }

    let data = test::black_box(data);

    b.iter(|| {
        for (_key, group) in &data.iter().group_by_lazy(|elt| **elt) {
            for elt in group {
                test::black_box(elt);
            }
        }
    })
}

#[bench]
fn group_by_lazy_2(b: &mut test::Bencher) {
    let mut data = vec![0; 1024];
    for (index, elt) in data.iter_mut().enumerate() {
        *elt = index / 2;
    }

    let data = test::black_box(data);

    b.iter(|| {
        for (_key, group) in &data.iter().group_by_lazy(|elt| **elt) {
            for elt in group {
                test::black_box(elt);
            }
        }
    })
}

#[bench]
fn slice_chunks(b: &mut test::Bencher) {
    let data = vec![0; 1024];

    let data = test::black_box(data);
    let sz = test::black_box(10);

    b.iter(|| {
        for group in data.chunks(sz) {
            for elt in group {
                test::black_box(elt);
            }
        }
    })
}

#[bench]
fn chunks_lazy_1(b: &mut test::Bencher) {
    let data = vec![0; 1024];

    let data = test::black_box(data);
    let sz = test::black_box(10);

    b.iter(|| {
        for group in &data.iter().chunks_lazy(sz) {
            for elt in group {
                test::black_box(elt);
            }
        }
    })
}

#[bench]
fn equal(b: &mut test::Bencher) {
    let data = vec![7; 1024];
    let l = data.len();
    let alpha = test::black_box(&data[1..]);
    let beta = test::black_box(&data[..l - 1]);
    b.iter(|| {
        itertools::equal(alpha, beta)
    })
}

#[bench]
fn merge_default(b: &mut test::Bencher) {
    let mut data1 = vec![0; 1024];
    let mut data2 = vec![0; 800];
    let mut x = 0;
    for (_, elt) in data1.iter_mut().enumerate() {
        *elt = x;
        x += 1;
    }

    let mut y = 0;
    for (i, elt) in data2.iter_mut().enumerate() {
        *elt += y;
        if i % 3 == 0 {
            y += 3;
        } else {
            y += 0;
        }
    }
    let data1 = test::black_box(data1);
    let data2 = test::black_box(data2);
    b.iter(|| {
        data1.iter().merge(&data2).count()
    })
}

#[bench]
fn merge_by_cmp(b: &mut test::Bencher) {
    let mut data1 = vec![0; 1024];
    let mut data2 = vec![0; 800];
    let mut x = 0;
    for (_, elt) in data1.iter_mut().enumerate() {
        *elt = x;
        x += 1;
    }

    let mut y = 0;
    for (i, elt) in data2.iter_mut().enumerate() {
        *elt += y;
        if i % 3 == 0 {
            y += 3;
        } else {
            y += 0;
        }
    }
    let data1 = test::black_box(data1);
    let data2 = test::black_box(data2);
    b.iter(|| {
        data1.iter().merge_by(&data2, Ord::cmp).count()
    })
}

#[bench]
fn merge_by_lt(b: &mut test::Bencher) {
    let mut data1 = vec![0; 1024];
    let mut data2 = vec![0; 800];
    let mut x = 0;
    for (_, elt) in data1.iter_mut().enumerate() {
        *elt = x;
        x += 1;
    }

    let mut y = 0;
    for (i, elt) in data2.iter_mut().enumerate() {
        *elt += y;
        if i % 3 == 0 {
            y += 3;
        } else {
            y += 0;
        }
    }
    let data1 = test::black_box(data1);
    let data2 = test::black_box(data2);
    b.iter(|| {
        data1.iter().merge_by(&data2, |a, b| if a <= b { Ordering::Less } else { Ordering::Greater }).count()
    })
}
<commit_msg>benches: Add dot product benchmarks for zip meethods<commit_after>#![feature(test)]

extern crate test;
extern crate itertools;

use test::{black_box};
use itertools::Stride;
use itertools::Itertools;

#[cfg(feature = "unstable")]
use itertools::{ZipTrusted};

use itertools::ZipSlices;

use std::iter::repeat;
use std::cmp;
use std::cmp::Ordering;

#[bench]
fn slice_iter(b: &mut test::Bencher)
{
    let xs: Vec<_> = repeat(1i32).take(20).collect();
    b.iter(|| for elt in xs.iter() {
        test::black_box(elt);
    })
}

#[bench]
fn slice_iter_rev(b: &mut test::Bencher)
{
    let xs: Vec<_> = repeat(1i32).take(20).collect();
    b.iter(|| for elt in xs.iter().rev() {
        test::black_box(elt);
    })
}

#[bench]
fn stride_iter(b: &mut test::Bencher)
{
    let xs: Vec<_> = repeat(1i32).take(20).collect();
    b.iter(|| for elt in Stride::from_slice(&xs, 1) {
        test::black_box(elt);
    })
}

#[bench]
fn stride_iter_rev(b: &mut test::Bencher)
{
    let xs: Vec<_> = repeat(1i32).take(20).collect();
    b.iter(|| for elt in Stride::from_slice(&xs, 1).rev() {
        test::black_box(elt);
    })
}

#[bench]
fn zip_default_zip(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        for (&x, &y) in xs.iter().zip(&ys) {
            test::black_box(x);
            test::black_box(y);
        }
    })
}

#[bench]
fn zipdot_i32_default_zip(b: &mut test::Bencher)
{
    let xs = vec![2; 1024];
    let ys = vec![2; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        let mut s = 0;
        for (&x, &y) in xs.iter().zip(&ys) {
            s += x * y;
        }
        s
    })
}

#[bench]
fn zipdot_f32_default_zip(b: &mut test::Bencher)
{
    let xs = vec![2f32; 1024];
    let ys = vec![2f32; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        let mut s = 0.;
        for (&x, &y) in xs.iter().zip(&ys) {
            s += x * y;
        }
        s
    })
}

#[bench]
fn zip_default_zip3(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let zs = vec![0; 766];
    let xs = black_box(xs);
    let ys = black_box(ys);
    let zs = black_box(zs);

    b.iter(|| {
        for ((&x, &y), &z) in xs.iter().zip(&ys).zip(&zs) {
            test::black_box(x);
            test::black_box(y);
            test::black_box(z);
        }
    })
}

/*
#[bench]
fn zip_slices_ziptuple(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];

    b.iter(|| {
        let xs = black_box(&xs);
        let ys = black_box(&ys);
        for (&x, &y) in Zip::new((xs, ys)) {
            test::black_box(x);
            test::black_box(y);
        }
    })
}
*/

#[bench]
fn zipslices(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        for (&x, &y) in ZipSlices::new(&xs, &ys) {
            test::black_box(x);
            test::black_box(y);
        }
    })
}

#[bench]
fn zipslices_mut(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let mut ys = black_box(ys);

    b.iter(|| {
        for (&x, &mut y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) {
            test::black_box(x);
            test::black_box(y);
        }
    })
}

#[bench]
fn zipdot_i32_zipslices(b: &mut test::Bencher)
{
    let xs = vec![2; 1024];
    let ys = vec![2; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        let mut s = 0i32;
        for (&x, &y) in ZipSlices::new(&xs, &ys) {
            s += x * y;
        }
        s
    })
}

#[bench]
fn zipdot_f32_zipslices(b: &mut test::Bencher)
{
    let xs = vec![2f32; 1024];
    let ys = vec![2f32; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        let mut s = 0.;
        for (&x, &y) in ZipSlices::new(&xs, &ys) {
            s += x * y;
        }
        s
    })
}

#[cfg(feature = "unstable")]
#[bench]
fn ziptrusted(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        for (&x, &y) in ZipTrusted::new((xs.iter(), ys.iter())) {
            test::black_box(x);
            test::black_box(y);
        }
    })
}

#[cfg(feature = "unstable")]
#[bench]
fn zipdot_i32_ziptrusted(b: &mut test::Bencher)
{
    let xs = vec![2; 1024];
    let ys = vec![2; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        let mut s = 0i32;
        for (&x, &y) in ZipTrusted::new((xs.iter(), ys.iter())) {
            s += x * y;
        }
        s
    })
}

#[cfg(feature = "unstable")]
#[bench]
fn zipdot_f32_ziptrusted(b: &mut test::Bencher)
{
    let xs = vec![2.; 1024];
    let ys = vec![2.; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        let mut s = 0f32;
        for (&x, &y) in ZipTrusted::new((xs.iter(), ys.iter())) {
            s += x * y;
        }
        s
    })
}

#[cfg(feature = "unstable")]
#[bench]
fn ziptrusted3(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let zs = vec![0; 766];
    let xs = black_box(xs);
    let ys = black_box(ys);
    let zs = black_box(zs);

    b.iter(|| {
        for (&x, &y, &z) in ZipTrusted::new((xs.iter(), ys.iter(), zs.iter())) {
            test::black_box(x);
            test::black_box(y);
            test::black_box(z);
        }
    })
}

#[bench]
fn zip_checked_counted_loop(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        // Must slice to equal lengths, and then bounds checks are eliminated!
        let len = cmp::min(xs.len(), ys.len());
        let xs = &xs[..len];
        let ys = &ys[..len];

        for i in 0..len {
            let x = xs[i];
            let y = ys[i];
            test::black_box(x);
            test::black_box(y);
        }
    })
}

#[bench]
fn zipdot_i32_checked_counted_loop(b: &mut test::Bencher)
{
    let xs = vec![2; 1024];
    let ys = vec![2; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        // Must slice to equal lengths, and then bounds checks are eliminated!
        let len = cmp::min(xs.len(), ys.len());
        let xs = &xs[..len];
        let ys = &ys[..len];

        let mut s = 0i32;

        for i in 0..len {
            s += xs[i] * ys[i];
        }
        s
    })
}

#[bench]
fn zipdot_f32_checked_counted_loop(b: &mut test::Bencher)
{
    let xs = vec![2f32; 1024];
    let ys = vec![2f32; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        // Must slice to equal lengths, and then bounds checks are eliminated!
        let len = cmp::min(xs.len(), ys.len());
        let xs = &xs[..len];
        let ys = &ys[..len];

        let mut s = 0.;

        for i in 0..len {
            s += xs[i] * ys[i];
        }
        s
    })
}

#[bench]
fn zip_unchecked_counted_loop(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        let len = cmp::min(xs.len(), ys.len());
        for i in 0..len {
            unsafe {
            let x = *xs.get_unchecked(i);
            let y = *ys.get_unchecked(i);
            test::black_box(x);
            test::black_box(y);
            }
        }
    })
}

#[bench]
fn zipdot_i32_unchecked_counted_loop(b: &mut test::Bencher)
{
    let xs = vec![2; 1024];
    let ys = vec![2; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        let len = cmp::min(xs.len(), ys.len());
        let mut s = 0i32;
        for i in 0..len {
            unsafe {
            let x = *xs.get_unchecked(i);
            let y = *ys.get_unchecked(i);
            s += x * y;
            }
        }
        s
    })
}

#[bench]
fn zipdot_f32_unchecked_counted_loop(b: &mut test::Bencher)
{
    let xs = vec![2.; 1024];
    let ys = vec![2.; 768];
    let xs = black_box(xs);
    let ys = black_box(ys);

    b.iter(|| {
        let len = cmp::min(xs.len(), ys.len());
        let mut s = 0f32;
        for i in 0..len {
            unsafe {
            let x = *xs.get_unchecked(i);
            let y = *ys.get_unchecked(i);
            s += x * y;
            }
        }
        s
    })
}

#[bench]
fn zip_unchecked_counted_loop3(b: &mut test::Bencher)
{
    let xs = vec![0; 1024];
    let ys = vec![0; 768];
    let zs = vec![0; 766];
    let xs = black_box(xs);
    let ys = black_box(ys);
    let zs = black_box(zs);

    b.iter(|| {
        let len = cmp::min(xs.len(), cmp::min(ys.len(), zs.len()));
        for i in 0..len {
            unsafe {
            let x = *xs.get_unchecked(i);
            let y = *ys.get_unchecked(i);
            let z = *zs.get_unchecked(i);
            test::black_box(x);
            test::black_box(y);
            test::black_box(z);
            }
        }
    })
}

#[bench]
fn group_by_lazy_1(b: &mut test::Bencher) {
    let mut data = vec![0; 1024];
    for (index, elt) in data.iter_mut().enumerate() {
        *elt = index / 10;
    }

    let data = test::black_box(data);

    b.iter(|| {
        for (_key, group) in &data.iter().group_by_lazy(|elt| **elt) {
            for elt in group {
                test::black_box(elt);
            }
        }
    })
}

#[bench]
fn group_by_lazy_2(b: &mut test::Bencher) {
    let mut data = vec![0; 1024];
    for (index, elt) in data.iter_mut().enumerate() {
        *elt = index / 2;
    }

    let data = test::black_box(data);

    b.iter(|| {
        for (_key, group) in &data.iter().group_by_lazy(|elt| **elt) {
            for elt in group {
                test::black_box(elt);
            }
        }
    })
}

#[bench]
fn slice_chunks(b: &mut test::Bencher) {
    let data = vec![0; 1024];

    let data = test::black_box(data);
    let sz = test::black_box(10);

    b.iter(|| {
        for group in data.chunks(sz) {
            for elt in group {
                test::black_box(elt);
            }
        }
    })
}

#[bench]
fn chunks_lazy_1(b: &mut test::Bencher) {
    let data = vec![0; 1024];

    let data = test::black_box(data);
    let sz = test::black_box(10);

    b.iter(|| {
        for group in &data.iter().chunks_lazy(sz) {
            for elt in group {
                test::black_box(elt);
            }
        }
    })
}

#[bench]
fn equal(b: &mut test::Bencher) {
    let data = vec![7; 1024];
    let l = data.len();
    let alpha = test::black_box(&data[1..]);
    let beta = test::black_box(&data[..l - 1]);
    b.iter(|| {
        itertools::equal(alpha, beta)
    })
}

#[bench]
fn merge_default(b: &mut test::Bencher) {
    let mut data1 = vec![0; 1024];
    let mut data2 = vec![0; 800];
    let mut x = 0;
    for (_, elt) in data1.iter_mut().enumerate() {
        *elt = x;
        x += 1;
    }

    let mut y = 0;
    for (i, elt) in data2.iter_mut().enumerate() {
        *elt += y;
        if i % 3 == 0 {
            y += 3;
        } else {
            y += 0;
        }
    }
    let data1 = test::black_box(data1);
    let data2 = test::black_box(data2);
    b.iter(|| {
        data1.iter().merge(&data2).count()
    })
}

#[bench]
fn merge_by_cmp(b: &mut test::Bencher) {
    let mut data1 = vec![0; 1024];
    let mut data2 = vec![0; 800];
    let mut x = 0;
    for (_, elt) in data1.iter_mut().enumerate() {
        *elt = x;
        x += 1;
    }

    let mut y = 0;
    for (i, elt) in data2.iter_mut().enumerate() {
        *elt += y;
        if i % 3 == 0 {
            y += 3;
        } else {
            y += 0;
        }
    }
    let data1 = test::black_box(data1);
    let data2 = test::black_box(data2);
    b.iter(|| {
        data1.iter().merge_by(&data2, Ord::cmp).count()
    })
}

#[bench]
fn merge_by_lt(b: &mut test::Bencher) {
    let mut data1 = vec![0; 1024];
    let mut data2 = vec![0; 800];
    let mut x = 0;
    for (_, elt) in data1.iter_mut().enumerate() {
        *elt = x;
        x += 1;
    }

    let mut y = 0;
    for (i, elt) in data2.iter_mut().enumerate() {
        *elt += y;
        if i % 3 == 0 {
            y += 3;
        } else {
            y += 0;
        }
    }
    let data1 = test::black_box(data1);
    let data2 = test::black_box(data2);
    b.iter(|| {
        data1.iter().merge_by(&data2, |a, b| if a <= b { Ordering::Less } else { Ordering::Greater }).count()
    })
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate itertools;

use test::{black_box, Bencher};
use itertools::Itertools;

fn s1(a: u32) -> u32 {
    black_box(a)
}

fn s2(a: u32, b: u32) -> u32 {
    black_box(a + b)
}

fn s3(a: u32, b: u32, c: u32) -> u32 {
    black_box(a + b + c)
}

fn s4(a: u32, b: u32, c: u32, d: u32) -> u32 {
    black_box(a + b + c + d)
}

fn sum_s1(s: &[u32]) -> u32 {
    s1(s[0])
}

fn sum_s2(s: &[u32]) -> u32 {
    s2(s[0], s[1])
}

fn sum_s3(s: &[u32]) -> u32 {
    s3(s[0], s[1], s[2])
}

fn sum_s4(s: &[u32]) -> u32 {
    s4(s[0], s[1], s[2], s[3])
}

fn sum_t1(s: &(&u32, )) -> u32 {
    s1(*s.0)
}

fn sum_t2(s: &(&u32, &u32)) -> u32 {
    s2(*s.0, *s.1)
}

fn sum_t3(s: &(&u32, &u32, &u32)) -> u32 {
    s3(*s.0, *s.1, *s.2)
}

fn sum_t4(s: &(&u32, &u32, &u32, &u32)) -> u32 {
    s4(*s.0, *s.1, *s.2, *s.3)
}

macro_rules! def_benchs {
    ($N:expr;
     $TUPLE_FUN:ident,
     $TUPLES:ident,
     $TUPLE_WINDOWS:ident;
     $SLICE_FUN:ident,
     $CHUNKS:ident,
     $WINDOWS:ident;
     $FOR_CHUNKS:ident,
     $FOR_WINDOWS:ident
     ) => (
        #[bench]
        fn $FOR_CHUNKS(b: &mut Bencher) {
            let v: Vec<u32> = (0.. $N * 1_000).collect();
            b.iter(|| {
                let mut j = 0;
                for _ in 0..1_000 {
                    black_box($SLICE_FUN(&v[j..(j + $N)]));
                    j += $N;
                }
            });
        }

        #[bench]
        fn $FOR_WINDOWS(b: &mut Bencher) {
            let v: Vec<u32> = (0..1_000).collect();
            b.iter(|| {
                for i in 0..(1_000 - $N) {
                    black_box($SLICE_FUN(&v[i..(i + $N)]));
                }
            });
        }

        #[bench]
        fn $TUPLES(b: &mut Bencher) {
            let v: Vec<u32> = (0.. $N * 1_000).collect();
            b.iter(|| {
                for x in v.iter().tuples() {
                    black_box($TUPLE_FUN(&x));
                }
            });
        }

        #[bench]
        fn $CHUNKS(b: &mut Bencher) {
            let v: Vec<u32> = (0.. $N * 1_000).collect();
            b.iter(|| {
                for x in v.chunks($N) {
                    black_box($SLICE_FUN(x));
                }
            });
        }

        #[bench]
        fn $TUPLE_WINDOWS(b: &mut Bencher) {
            let v: Vec<u32> = (0..1_000).collect();
            b.iter(|| {
                for x in v.iter().tuple_windows() {
                    black_box($TUPLE_FUN(&x));
                }
            });
        }

        #[bench]
        fn $WINDOWS(b: &mut Bencher) {
            let v: Vec<u32> = (0..1_000).collect();
            b.iter(|| {
                for x in v.windows($N) {
                    black_box($SLICE_FUN(x));
                }
            });
        }
    )
}

def_benchs!{
    1;
    sum_t1,
    tuple_chunks_1,
    tuple_windows_1;
    sum_s1,
    slice_chunks_1,
    slice_windows_1;
    for_chunks_1,
    for_windows_1
}

def_benchs!{
    2;
    sum_t2,
    tuple_chunks_2,
    tuple_windows_2;
    sum_s2,
    slice_chunks_2,
    slice_windows_2;
    for_chunks_2,
    for_windows_2
}

def_benchs!{
    3;
    sum_t3,
    tuple_chunks_3,
    tuple_windows_3;
    sum_s3,
    slice_chunks_3,
    slice_windows_3;
    for_chunks_3,
    for_windows_3
}

def_benchs!{
    4;
    sum_t4,
    tuple_chunks_4,
    tuple_windows_4;
    sum_s4,
    slice_chunks_4,
    slice_windows_4;
    for_chunks_4,
    for_windows_4
}
<commit_msg>Remove use of black_box<commit_after>#![feature(test)]

extern crate test;
extern crate itertools;

use test::Bencher;
use itertools::Itertools;

fn s1(a: u32) -> u32 {
    a
}

fn s2(a: u32, b: u32) -> u32 {
    a + b
}

fn s3(a: u32, b: u32, c: u32) -> u32 {
    a + b + c
}

fn s4(a: u32, b: u32, c: u32, d: u32) -> u32 {
    a + b + c + d
}

fn sum_s1(s: &[u32]) -> u32 {
    s1(s[0])
}

fn sum_s2(s: &[u32]) -> u32 {
    s2(s[0], s[1])
}

fn sum_s3(s: &[u32]) -> u32 {
    s3(s[0], s[1], s[2])
}

fn sum_s4(s: &[u32]) -> u32 {
    s4(s[0], s[1], s[2], s[3])
}

fn sum_t1(s: &(&u32, )) -> u32 {
    s1(*s.0)
}

fn sum_t2(s: &(&u32, &u32)) -> u32 {
    s2(*s.0, *s.1)
}

fn sum_t3(s: &(&u32, &u32, &u32)) -> u32 {
    s3(*s.0, *s.1, *s.2)
}

fn sum_t4(s: &(&u32, &u32, &u32, &u32)) -> u32 {
    s4(*s.0, *s.1, *s.2, *s.3)
}

macro_rules! def_benchs {
    ($N:expr;
     $TUPLE_FUN:ident,
     $TUPLES:ident,
     $TUPLE_WINDOWS:ident;
     $SLICE_FUN:ident,
     $CHUNKS:ident,
     $WINDOWS:ident;
     $FOR_CHUNKS:ident,
     $FOR_WINDOWS:ident
     ) => (
        #[bench]
        fn $FOR_CHUNKS(b: &mut Bencher) {
            let v: Vec<u32> = (0.. $N * 1_000).collect();
            let mut s = 0;
            b.iter(|| {
                let mut j = 0;
                for _ in 0..1_000 {
                    s += $SLICE_FUN(&v[j..(j + $N)]);
                    j += $N;
                }
                s
            });
        }

        #[bench]
        fn $FOR_WINDOWS(b: &mut Bencher) {
            let v: Vec<u32> = (0..1_000).collect();
            let mut s = 0;
            b.iter(|| {
                for i in 0..(1_000 - $N) {
                    s += $SLICE_FUN(&v[i..(i + $N)]);
                }
                s
            });
        }

        #[bench]
        fn $TUPLES(b: &mut Bencher) {
            let v: Vec<u32> = (0.. $N * 1_000).collect();
            let mut s = 0;
            b.iter(|| {
                for x in v.iter().tuples() {
                    s += $TUPLE_FUN(&x);
                }
                s
            });
        }

        #[bench]
        fn $CHUNKS(b: &mut Bencher) {
            let v: Vec<u32> = (0.. $N * 1_000).collect();
            let mut s = 0;
            b.iter(|| {
                for x in v.chunks($N) {
                    s += $SLICE_FUN(x);
                }
                s
            });
        }

        #[bench]
        fn $TUPLE_WINDOWS(b: &mut Bencher) {
            let v: Vec<u32> = (0..1_000).collect();
            let mut s = 0;
            b.iter(|| {
                for x in v.iter().tuple_windows() {
                    s += $TUPLE_FUN(&x);
                }
                s
            });
        }

        #[bench]
        fn $WINDOWS(b: &mut Bencher) {
            let v: Vec<u32> = (0..1_000).collect();
            let mut s = 0;
            b.iter(|| {
                for x in v.windows($N) {
                    s += $SLICE_FUN(x);
                }
                s
            });
        }
    )
}

def_benchs!{
    1;
    sum_t1,
    tuple_chunks_1,
    tuple_windows_1;
    sum_s1,
    slice_chunks_1,
    slice_windows_1;
    for_chunks_1,
    for_windows_1
}

def_benchs!{
    2;
    sum_t2,
    tuple_chunks_2,
    tuple_windows_2;
    sum_s2,
    slice_chunks_2,
    slice_windows_2;
    for_chunks_2,
    for_windows_2
}

def_benchs!{
    3;
    sum_t3,
    tuple_chunks_3,
    tuple_windows_3;
    sum_s3,
    slice_chunks_3,
    slice_windows_3;
    for_chunks_3,
    for_windows_3
}

def_benchs!{
    4;
    sum_t4,
    tuple_chunks_4,
    tuple_windows_4;
    sum_s4,
    slice_chunks_4,
    slice_windows_4;
    for_chunks_4,
    for_windows_4
}
<|endoftext|>


<commit_before>// Copyright 2013 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.

/*!

Signal handling

This modules provides bindings to receive signals safely, built on top of the
local I/O factory. There are a number of defined signals which can be caught,
but not all signals will work across all platforms (windows doesn't have
definitions for a number of signals.

*/

use comm::{Port, SharedChan, stream};
use hashmap;
use option::{Some, None};
use result::{Err, Ok};
use rt::io::io_error;
use rt::rtio::{IoFactory, RtioSignal, with_local_io};

#[deriving(Eq, IterBytes)]
pub enum Signum {
    /// Equivalent to SIGBREAK, delivered when the user presses Ctrl-Break.
    Break = 21i,
    /// Equivalent to SIGHUP, delivered when the user closes the terminal
    /// window. On delivery of HangUp, the program is given approximately
    /// 10 seconds to perfom any cleanup. After that, Windows will
    /// unconditionally terminate it.
    HangUp = 1i,
    /// Equivalent to SIGINT, delivered when the user presses Ctrl-c.
    Interrupt = 2i,
    /// Equivalent to SIGQUIT, delivered when the user presses Ctrl-\.
    Quit = 3i,
    /// Equivalent to SIGTSTP, delivered when the user presses Ctrl-z.
    StopTemporarily = 20i,
    /// Equivalent to SIGUSR1.
    User1 = 10i,
    /// Equivalent to SIGUSR2.
    User2 = 12i,
    /// Equivalent to SIGWINCH, delivered when the console has been resized.
    /// WindowSizeChange may not be delivered in a timely manner; size change
    /// will only be detected when the cursor is being moved.
    WindowSizeChange = 28i,
}

/// Listener provides a port to listen for registered signals.
///
/// Listener automatically unregisters its handles once it is out of scope.
/// However, clients can still unregister signums manually.
///
/// # Example
///
/// ```rust
/// use std::rt::io::signal::{Listener, Interrupt};
///
/// let mut listener = Listener::new();
/// listener.register(signal::Interrupt);
///
/// do spawn {
///     loop {
///         match listener.port.recv() {
///             Interrupt => println("Got Interrupt'ed"),
///             _ => (),
///         }
///     }
/// }
///
/// ```
pub struct Listener {
    /// A map from signums to handles to keep the handles in memory
    priv handles: hashmap::HashMap<Signum, ~RtioSignal>,
    /// chan is where all the handles send signums, which are received by
    /// the clients from port.
    priv chan: SharedChan<Signum>,

    /// Clients of Listener can `recv()` from this port. This is exposed to
    /// allow selection over this port as well as manipulation of the port
    /// directly.
    port: Port<Signum>,
}

impl Listener {
    /// Creates a new listener for signals. Once created, signals are bound via
    /// the `register` method (otherwise nothing will ever be received)
    pub fn new() -> Listener {
        let (port, chan) = stream();
        Listener {
            chan: SharedChan::new(chan),
            port: port,
            handles: hashmap::HashMap::new(),
        }
    }

    /// Listen for a signal, returning true when successfully registered for
    /// signum. Signals can be received using `recv()`.
    ///
    /// Once a signal is registered, this listener will continue to receive
    /// notifications of signals until it is unregistered. This occurs
    /// regardless of the number of other listeners registered in other tasks
    /// (or on this task).
    ///
    /// Signals are still received if there is no task actively waiting for
    /// a signal, and a later call to `recv` will return the signal that was
    /// received while no task was waiting on it.
    ///
    /// # Failure
    ///
    /// If this function fails to register a signal handler, then an error will
    /// be raised on the `io_error` condition and the function will return
    /// false.
    pub fn register(&mut self, signum: Signum) -> bool {
        if self.handles.contains_key(&signum) {
            return true; // self is already listening to signum, so succeed
        }
        do with_local_io |io| {
            match io.signal(signum, self.chan.clone()) {
                Ok(w) => {
                    self.handles.insert(signum, w);
                    Some(())
                },
                Err(ioerr) => {
                    io_error::cond.raise(ioerr);
                    None
                }
            }
        }.is_some()
    }

    /// Unregisters a signal. If this listener currently had a handler
    /// registered for the signal, then it will stop receiving any more
    /// notification about the signal. If the signal has already been received,
    /// it may still be returned by `recv`.
    pub fn unregister(&mut self, signum: Signum) {
        self.handles.pop(&signum);
    }
}

#[cfg(test)]
mod test {
    use libc;
    use rt::io::timer;
    use rt::io;
    use super::*;

    // kill is only available on Unixes
    #[cfg(unix)]
    #[fixed_stack_segment]
    fn sigint() {
        unsafe {
            libc::funcs::posix88::signal::kill(libc::getpid(), libc::SIGINT);
        }
    }

    #[test] #[cfg(unix)]
    fn test_io_signal_smoketest() {
        let mut signal = Listener::new();
        signal.register(Interrupt);
        sigint();
        timer::sleep(10);
        match signal.port.recv() {
            Interrupt => (),
            s => fail!("Expected Interrupt, got {:?}", s),
        }
    }

    #[test] #[cfg(unix)]
    fn test_io_signal_two_signal_one_signum() {
        let mut s1 = Listener::new();
        let mut s2 = Listener::new();
        s1.register(Interrupt);
        s2.register(Interrupt);
        sigint();
        timer::sleep(10);
        match s1.port.recv() {
            Interrupt => (),
            s => fail!("Expected Interrupt, got {:?}", s),
        }
        match s1.port.recv() {
            Interrupt => (),
            s => fail!("Expected Interrupt, got {:?}", s),
        }
    }

    #[test] #[cfg(unix)]
    fn test_io_signal_unregister() {
        let mut s1 = Listener::new();
        let mut s2 = Listener::new();
        s1.register(Interrupt);
        s2.register(Interrupt);
        s2.unregister(Interrupt);
        sigint();
        timer::sleep(10);
        if s2.port.peek() {
            fail!("Unexpected {:?}", s2.port.recv());
        }
    }

    #[cfg(windows)]
    #[test]
    fn test_io_signal_invalid_signum() {
        let mut s = Listener::new();
        let mut called = false;
        do io::io_error::cond.trap(|_| {
            called = true;
        }).inside {
            if s.register(User1) {
                fail!("Unexpected successful registry of signum {:?}", User1);
            }
        }
        assert!(called);
    }
}
<commit_msg>Fix a typo in a rt::io::signal test<commit_after>// Copyright 2013 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.

/*!

Signal handling

This modules provides bindings to receive signals safely, built on top of the
local I/O factory. There are a number of defined signals which can be caught,
but not all signals will work across all platforms (windows doesn't have
definitions for a number of signals.

*/

use comm::{Port, SharedChan, stream};
use hashmap;
use option::{Some, None};
use result::{Err, Ok};
use rt::io::io_error;
use rt::rtio::{IoFactory, RtioSignal, with_local_io};

#[deriving(Eq, IterBytes)]
pub enum Signum {
    /// Equivalent to SIGBREAK, delivered when the user presses Ctrl-Break.
    Break = 21i,
    /// Equivalent to SIGHUP, delivered when the user closes the terminal
    /// window. On delivery of HangUp, the program is given approximately
    /// 10 seconds to perfom any cleanup. After that, Windows will
    /// unconditionally terminate it.
    HangUp = 1i,
    /// Equivalent to SIGINT, delivered when the user presses Ctrl-c.
    Interrupt = 2i,
    /// Equivalent to SIGQUIT, delivered when the user presses Ctrl-\.
    Quit = 3i,
    /// Equivalent to SIGTSTP, delivered when the user presses Ctrl-z.
    StopTemporarily = 20i,
    /// Equivalent to SIGUSR1.
    User1 = 10i,
    /// Equivalent to SIGUSR2.
    User2 = 12i,
    /// Equivalent to SIGWINCH, delivered when the console has been resized.
    /// WindowSizeChange may not be delivered in a timely manner; size change
    /// will only be detected when the cursor is being moved.
    WindowSizeChange = 28i,
}

/// Listener provides a port to listen for registered signals.
///
/// Listener automatically unregisters its handles once it is out of scope.
/// However, clients can still unregister signums manually.
///
/// # Example
///
/// ```rust
/// use std::rt::io::signal::{Listener, Interrupt};
///
/// let mut listener = Listener::new();
/// listener.register(signal::Interrupt);
///
/// do spawn {
///     loop {
///         match listener.port.recv() {
///             Interrupt => println("Got Interrupt'ed"),
///             _ => (),
///         }
///     }
/// }
///
/// ```
pub struct Listener {
    /// A map from signums to handles to keep the handles in memory
    priv handles: hashmap::HashMap<Signum, ~RtioSignal>,
    /// chan is where all the handles send signums, which are received by
    /// the clients from port.
    priv chan: SharedChan<Signum>,

    /// Clients of Listener can `recv()` from this port. This is exposed to
    /// allow selection over this port as well as manipulation of the port
    /// directly.
    port: Port<Signum>,
}

impl Listener {
    /// Creates a new listener for signals. Once created, signals are bound via
    /// the `register` method (otherwise nothing will ever be received)
    pub fn new() -> Listener {
        let (port, chan) = stream();
        Listener {
            chan: SharedChan::new(chan),
            port: port,
            handles: hashmap::HashMap::new(),
        }
    }

    /// Listen for a signal, returning true when successfully registered for
    /// signum. Signals can be received using `recv()`.
    ///
    /// Once a signal is registered, this listener will continue to receive
    /// notifications of signals until it is unregistered. This occurs
    /// regardless of the number of other listeners registered in other tasks
    /// (or on this task).
    ///
    /// Signals are still received if there is no task actively waiting for
    /// a signal, and a later call to `recv` will return the signal that was
    /// received while no task was waiting on it.
    ///
    /// # Failure
    ///
    /// If this function fails to register a signal handler, then an error will
    /// be raised on the `io_error` condition and the function will return
    /// false.
    pub fn register(&mut self, signum: Signum) -> bool {
        if self.handles.contains_key(&signum) {
            return true; // self is already listening to signum, so succeed
        }
        do with_local_io |io| {
            match io.signal(signum, self.chan.clone()) {
                Ok(w) => {
                    self.handles.insert(signum, w);
                    Some(())
                },
                Err(ioerr) => {
                    io_error::cond.raise(ioerr);
                    None
                }
            }
        }.is_some()
    }

    /// Unregisters a signal. If this listener currently had a handler
    /// registered for the signal, then it will stop receiving any more
    /// notification about the signal. If the signal has already been received,
    /// it may still be returned by `recv`.
    pub fn unregister(&mut self, signum: Signum) {
        self.handles.pop(&signum);
    }
}

#[cfg(test)]
mod test {
    use libc;
    use rt::io::timer;
    use rt::io;
    use super::*;

    // kill is only available on Unixes
    #[cfg(unix)]
    #[fixed_stack_segment]
    fn sigint() {
        unsafe {
            libc::funcs::posix88::signal::kill(libc::getpid(), libc::SIGINT);
        }
    }

    #[test] #[cfg(unix)]
    fn test_io_signal_smoketest() {
        let mut signal = Listener::new();
        signal.register(Interrupt);
        sigint();
        timer::sleep(10);
        match signal.port.recv() {
            Interrupt => (),
            s => fail!("Expected Interrupt, got {:?}", s),
        }
    }

    #[test] #[cfg(unix)]
    fn test_io_signal_two_signal_one_signum() {
        let mut s1 = Listener::new();
        let mut s2 = Listener::new();
        s1.register(Interrupt);
        s2.register(Interrupt);
        sigint();
        timer::sleep(10);
        match s1.port.recv() {
            Interrupt => (),
            s => fail!("Expected Interrupt, got {:?}", s),
        }
        match s2.port.recv() {
            Interrupt => (),
            s => fail!("Expected Interrupt, got {:?}", s),
        }
    }

    #[test] #[cfg(unix)]
    fn test_io_signal_unregister() {
        let mut s1 = Listener::new();
        let mut s2 = Listener::new();
        s1.register(Interrupt);
        s2.register(Interrupt);
        s2.unregister(Interrupt);
        sigint();
        timer::sleep(10);
        if s2.port.peek() {
            fail!("Unexpected {:?}", s2.port.recv());
        }
    }

    #[cfg(windows)]
    #[test]
    fn test_io_signal_invalid_signum() {
        let mut s = Listener::new();
        let mut called = false;
        do io::io_error::cond.trap(|_| {
            called = true;
        }).inside {
            if s.register(User1) {
                fail!("Unexpected successful registry of signum {:?}", User1);
            }
        }
        assert!(called);
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 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.

pub trait MyIterator {
}

pub struct MyStruct<T>(T);

macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            impl<'a, T> MyIterator for &'a MyStruct<[T; $N]> {
            }
        )+
    }
}

// @has issue_53812/trait.MyIterator.html '//*[@id="implementors-list"]//h3[1]' 'MyStruct<[T; 0]>'
array_impls! { 10 3 2 1 0 }
<commit_msg>Check the remaining nodes<commit_after>// Copyright 2018 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.

pub trait MyIterator {
}

pub struct MyStruct<T>(T);

macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            impl<'a, T> MyIterator for &'a MyStruct<[T; $N]> {
            }
        )+
    }
}

// @has issue_53812/trait.MyIterator.html '//*[@id="implementors-list"]//h3[1]' 'MyStruct<[T; 0]>'
// @has - '//*[@id="implementors-list"]//h3[2]' 'MyStruct<[T; 1]>'
// @has - '//*[@id="implementors-list"]//h3[3]' 'MyStruct<[T; 2]>'
// @has - '//*[@id="implementors-list"]//h3[4]' 'MyStruct<[T; 3]>'
// @has - '//*[@id="implementors-list"]//h3[5]' 'MyStruct<[T; 10]>'
array_impls! { 10 3 2 1 0 }
<|endoftext|>


<commit_before>mod attestation_producer;
mod block_producer;
mod config;
mod duties;
pub mod error;
mod service;
mod signer;

use crate::config::Config as ValidatorClientConfig;
use crate::service::Service as ValidatorService;
use clap::{App, Arg};
use eth2_config::{get_data_dir, read_from_file, write_to_file, Eth2Config};
use protos::services_grpc::ValidatorServiceClient;
use slog::{crit, error, info, o, Drain};
use std::path::PathBuf;
use types::{Keypair, MainnetEthSpec, MinimalEthSpec};

pub const DEFAULT_SPEC: &str = "minimal";
pub const DEFAULT_DATA_DIR: &str = ".lighthouse-validator";
pub const CLIENT_CONFIG_FILENAME: &str = "validator-client.toml";
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";

fn main() {
    // Logging
    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::CompactFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build().fuse();
    let log = slog::Logger::root(drain, o!());

    // CLI
    let matches = App::new("Lighthouse Validator Client")
        .version("0.0.1")
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about("Eth 2.0 Validator Client")
        .arg(
            Arg::with_name("datadir")
                .long("datadir")
                .value_name("DIR")
                .help("Data directory for keys and databases.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("eth-config")
                .long("eth-config")
                .short("e")
                .value_name("DIR")
                .help(&format!("Directory containing {}.", ETH2_CONFIG_FILENAME))
                .takes_value(true)
                .default_value(ETH2_CONFIG_FILENAME),
        )
        .arg(
            Arg::with_name("server")
                .long("server")
                .value_name("server")
                .help("Address to connect to BeaconNode.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("spec-constants")
                .long("spec-constants")
                .value_name("TITLE")
                .short("s")
                .help("The title of the spec constants for chain config.")
                .takes_value(true)
                .possible_values(&["mainnet", "minimal"])
                .default_value("minimal"),
        )
        .get_matches();

    let data_dir = match get_data_dir(&matches, PathBuf::from(DEFAULT_DATA_DIR)) {
        Ok(dir) => dir,
        Err(e) => {
            crit!(log, "Failed to initialize data dir"; "error" => format!("{:?}", e));
            return;
        }
    };

    let client_config_path = data_dir.join(CLIENT_CONFIG_FILENAME);

    // Attempt to lead the `ClientConfig` from disk.
    //
    // If file doesn't exist, create a new, default one.
    let mut client_config = match read_from_file::<ValidatorClientConfig>(
        client_config_path.clone(),
    ) {
        Ok(Some(c)) => c,
        Ok(None) => {
            let default = ValidatorClientConfig::default();
            if let Err(e) = write_to_file(client_config_path.clone(), &default) {
                crit!(log, "Failed to write default ClientConfig to file"; "error" => format!("{:?}", e));
                return;
            }
            default
        }
        Err(e) => {
            crit!(log, "Failed to load a ChainConfig file"; "error" => format!("{:?}", e));
            return;
        }
    };

    // Ensure the `data_dir` in the config matches that supplied to the CLI.
    client_config.data_dir = data_dir.clone();

    // Update the client config with any CLI args.
    match client_config.apply_cli_args(&matches) {
        Ok(()) => (),
        Err(s) => {
            crit!(log, "Failed to parse ClientConfig CLI arguments"; "error" => s);
            return;
        }
    };

    let eth2_config_path: PathBuf = matches
        .value_of("eth-config")
        .and_then(|s| Some(PathBuf::from(s)))
        .unwrap_or_else(|| data_dir.join(ETH2_CONFIG_FILENAME));

    // Attempt to load the `Eth2Config` from file.
    //
    // If the file doesn't exist, create a default one depending on the CLI flags.
    let mut eth2_config = match read_from_file::<Eth2Config>(eth2_config_path.clone()) {
        Ok(Some(c)) => c,
        Ok(None) => {
            let default = match matches.value_of("spec-constants") {
                Some("mainnet") => Eth2Config::mainnet(),
                Some("minimal") => Eth2Config::minimal(),
                _ => unreachable!(), // Guarded by slog.
            };
            if let Err(e) = write_to_file(eth2_config_path, &default) {
                crit!(log, "Failed to write default Eth2Config to file"; "error" => format!("{:?}", e));
                return;
            }
            default
        }
        Err(e) => {
            crit!(log, "Failed to instantiate an Eth2Config"; "error" => format!("{:?}", e));
            return;
        }
    };

    // Update the eth2 config with any CLI flags.
    match eth2_config.apply_cli_args(&matches) {
        Ok(()) => (),
        Err(s) => {
            crit!(log, "Failed to parse Eth2Config CLI arguments"; "error" => s);
            return;
        }
    };

    info!(
        log,
        "Starting validator client";
        "datadir" => client_config.data_dir.to_str(),
        "spec_constants" => &eth2_config.spec_constants,
    );

    let result = match eth2_config.spec_constants.as_str() {
        "mainnet" => ValidatorService::<ValidatorServiceClient, Keypair>::start::<MainnetEthSpec>(
            client_config,
            eth2_config,
            log.clone(),
        ),
        "minimal" => ValidatorService::<ValidatorServiceClient, Keypair>::start::<MinimalEthSpec>(
            client_config,
            eth2_config,
            log.clone(),
        ),
        other => {
            crit!(log, "Unknown spec constants"; "title" => other);
            return;
        }
    };

    // start the validator service.
    // this specifies the GRPC and signer type to use as the duty manager beacon node.
    match result {
        Ok(_) => info!(log, "Validator client shutdown successfully."),
        Err(e) => crit!(log, "Validator client exited with error"; "error" => e.to_string()),
    }
}
<commit_msg>Change name of VC CLI param<commit_after>mod attestation_producer;
mod block_producer;
mod config;
mod duties;
pub mod error;
mod service;
mod signer;

use crate::config::Config as ValidatorClientConfig;
use crate::service::Service as ValidatorService;
use clap::{App, Arg};
use eth2_config::{get_data_dir, read_from_file, write_to_file, Eth2Config};
use protos::services_grpc::ValidatorServiceClient;
use slog::{crit, error, info, o, Drain};
use std::path::PathBuf;
use types::{Keypair, MainnetEthSpec, MinimalEthSpec};

pub const DEFAULT_SPEC: &str = "minimal";
pub const DEFAULT_DATA_DIR: &str = ".lighthouse-validator";
pub const CLIENT_CONFIG_FILENAME: &str = "validator-client.toml";
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";

fn main() {
    // Logging
    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::CompactFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build().fuse();
    let log = slog::Logger::root(drain, o!());

    // CLI
    let matches = App::new("Lighthouse Validator Client")
        .version("0.0.1")
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about("Eth 2.0 Validator Client")
        .arg(
            Arg::with_name("datadir")
                .long("datadir")
                .value_name("DIR")
                .help("Data directory for keys and databases.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("eth2-spec")
                .long("eth2-spec")
                .short("e")
                .value_name("TOML_FILE")
                .help("Path to Ethereum 2.0 specifications file.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("server")
                .long("server")
                .value_name("server")
                .help("Address to connect to BeaconNode.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("spec-constants")
                .long("spec-constants")
                .value_name("TITLE")
                .short("s")
                .help("The title of the spec constants for chain config.")
                .takes_value(true)
                .possible_values(&["mainnet", "minimal"])
                .default_value("minimal"),
        )
        .get_matches();

    let data_dir = match get_data_dir(&matches, PathBuf::from(DEFAULT_DATA_DIR)) {
        Ok(dir) => dir,
        Err(e) => {
            crit!(log, "Failed to initialize data dir"; "error" => format!("{:?}", e));
            return;
        }
    };

    let client_config_path = data_dir.join(CLIENT_CONFIG_FILENAME);

    // Attempt to lead the `ClientConfig` from disk.
    //
    // If file doesn't exist, create a new, default one.
    let mut client_config = match read_from_file::<ValidatorClientConfig>(
        client_config_path.clone(),
    ) {
        Ok(Some(c)) => c,
        Ok(None) => {
            let default = ValidatorClientConfig::default();
            if let Err(e) = write_to_file(client_config_path.clone(), &default) {
                crit!(log, "Failed to write default ClientConfig to file"; "error" => format!("{:?}", e));
                return;
            }
            default
        }
        Err(e) => {
            crit!(log, "Failed to load a ChainConfig file"; "error" => format!("{:?}", e));
            return;
        }
    };

    // Ensure the `data_dir` in the config matches that supplied to the CLI.
    client_config.data_dir = data_dir.clone();

    // Update the client config with any CLI args.
    match client_config.apply_cli_args(&matches) {
        Ok(()) => (),
        Err(s) => {
            crit!(log, "Failed to parse ClientConfig CLI arguments"; "error" => s);
            return;
        }
    };

    let eth2_config_path: PathBuf = matches
        .value_of("eth2-spec")
        .and_then(|s| Some(PathBuf::from(s)))
        .unwrap_or_else(|| data_dir.join(ETH2_CONFIG_FILENAME));

    // Attempt to load the `Eth2Config` from file.
    //
    // If the file doesn't exist, create a default one depending on the CLI flags.
    let mut eth2_config = match read_from_file::<Eth2Config>(eth2_config_path.clone()) {
        Ok(Some(c)) => c,
        Ok(None) => {
            let default = match matches.value_of("spec-constants") {
                Some("mainnet") => Eth2Config::mainnet(),
                Some("minimal") => Eth2Config::minimal(),
                _ => unreachable!(), // Guarded by slog.
            };
            if let Err(e) = write_to_file(eth2_config_path, &default) {
                crit!(log, "Failed to write default Eth2Config to file"; "error" => format!("{:?}", e));
                return;
            }
            default
        }
        Err(e) => {
            crit!(log, "Failed to instantiate an Eth2Config"; "error" => format!("{:?}", e));
            return;
        }
    };

    // Update the eth2 config with any CLI flags.
    match eth2_config.apply_cli_args(&matches) {
        Ok(()) => (),
        Err(s) => {
            crit!(log, "Failed to parse Eth2Config CLI arguments"; "error" => s);
            return;
        }
    };

    info!(
        log,
        "Starting validator client";
        "datadir" => client_config.data_dir.to_str(),
        "spec_constants" => &eth2_config.spec_constants,
    );

    let result = match eth2_config.spec_constants.as_str() {
        "mainnet" => ValidatorService::<ValidatorServiceClient, Keypair>::start::<MainnetEthSpec>(
            client_config,
            eth2_config,
            log.clone(),
        ),
        "minimal" => ValidatorService::<ValidatorServiceClient, Keypair>::start::<MinimalEthSpec>(
            client_config,
            eth2_config,
            log.clone(),
        ),
        other => {
            crit!(log, "Unknown spec constants"; "title" => other);
            return;
        }
    };

    // start the validator service.
    // this specifies the GRPC and signer type to use as the duty manager beacon node.
    match result {
        Ok(_) => info!(log, "Validator client shutdown successfully."),
        Err(e) => crit!(log, "Validator client exited with error"; "error" => e.to_string()),
    }
}
<|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 std::borrow::Cow;

use syntax::codemap::{BytePos, Pos, Span};

use codemap::LineRangeUtils;
use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices};
use config::{EmitMode, FileName};
use shape::{Indent, Shape};
use utils::{count_newlines, last_line_width, mk_sp};
use visitor::FmtVisitor;

struct SnippetStatus {
    /// An offset to the current line from the beginnig of the original snippet.
    line_start: usize,
    /// A length of trailing whitespaces on the current line.
    last_wspace: Option<usize>,
    /// The current line number.
    cur_line: usize,
}

impl SnippetStatus {
    fn new(cur_line: usize) -> Self {
        SnippetStatus {
            line_start: 0,
            last_wspace: None,
            cur_line,
        }
    }
}

impl<'a> FmtVisitor<'a> {
    fn output_at_start(&self) -> bool {
        self.buffer.is_empty()
    }

    // TODO these format_missing methods are ugly. Refactor and add unit tests
    // for the central whitespace stripping loop.
    pub fn format_missing(&mut self, end: BytePos) {
        self.format_missing_inner(end, |this, last_snippet, _| this.push_str(last_snippet))
    }

    pub fn format_missing_with_indent(&mut self, end: BytePos) {
        let config = self.config;
        self.format_missing_inner(end, |this, last_snippet, snippet| {
            this.push_str(last_snippet.trim_right());
            if last_snippet == snippet && !this.output_at_start() {
                // No new lines in the snippet.
                this.push_str("\n");
            }
            let indent = this.block_indent.to_string(config);
            this.push_str(&indent);
        })
    }

    pub fn format_missing_no_indent(&mut self, end: BytePos) {
        self.format_missing_inner(end, |this, last_snippet, _| {
            this.push_str(last_snippet.trim_right());
        })
    }

    fn format_missing_inner<F: Fn(&mut FmtVisitor, &str, &str)>(
        &mut self,
        end: BytePos,
        process_last_snippet: F,
    ) {
        let start = self.last_pos;

        if start == end {
            // Do nothing if this is the beginning of the file.
            if !self.output_at_start() {
                process_last_snippet(self, "", "");
            }
            return;
        }

        assert!(
            start < end,
            "Request to format inverted span: {:?} to {:?}",
            self.codemap.lookup_char_pos(start),
            self.codemap.lookup_char_pos(end)
        );

        self.last_pos = end;
        let span = mk_sp(start, end);
        let snippet = self.snippet(span);

        // Do nothing for spaces in the beginning of the file
        if start == BytePos(0) && end.0 as usize == snippet.len() && snippet.trim().is_empty() {
            return;
        }

        if snippet.trim().is_empty() && !out_of_file_lines_range!(self, span) {
            // Keep vertical spaces within range.
            self.push_vertical_spaces(count_newlines(snippet));
            process_last_snippet(self, "", snippet);
        } else {
            self.write_snippet(span, &process_last_snippet);
        }
    }

    fn push_vertical_spaces(&mut self, mut newline_count: usize) {
        let offset = self.count_trailing_newlines();
        let newline_upper_bound = self.config.blank_lines_upper_bound() + 1;
        let newline_lower_bound = self.config.blank_lines_lower_bound() + 1;

        if newline_count + offset > newline_upper_bound {
            if offset >= newline_upper_bound {
                newline_count = 0;
            } else {
                newline_count = newline_upper_bound - offset;
            }
        } else if newline_count + offset < newline_lower_bound {
            if offset >= newline_lower_bound {
                newline_count = 0;
            } else {
                newline_count = newline_lower_bound - offset;
            }
        }

        let blank_lines = "\n".repeat(newline_count);
        self.push_str(&blank_lines);
    }

    fn count_trailing_newlines(&self) -> usize {
        let mut buf = &*self.buffer;
        let mut result = 0;
        while buf.ends_with('\n') {
            buf = &buf[..buf.len() - 1];
            result += 1;
        }
        result
    }

    fn write_snippet<F>(&mut self, span: Span, process_last_snippet: F)
    where
        F: Fn(&mut FmtVisitor, &str, &str),
    {
        // Get a snippet from the file start to the span's hi without allocating.
        // We need it to determine what precedes the current comment. If the comment
        // follows code on the same line, we won't touch it.
        let big_span_lo = self.codemap.lookup_char_pos(span.lo()).file.start_pos;
        let local_begin = self.codemap.lookup_byte_offset(big_span_lo);
        let local_end = self.codemap.lookup_byte_offset(span.hi());
        let start_index = local_begin.pos.to_usize();
        let end_index = local_end.pos.to_usize();
        let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index];

        let big_diff = (span.lo() - big_span_lo).to_usize();
        let snippet = self.snippet(span);

        debug!("write_snippet `{}`", snippet);

        self.write_snippet_inner(big_snippet, big_diff, snippet, span, process_last_snippet);
    }

    fn write_snippet_inner<F>(
        &mut self,
        big_snippet: &str,
        big_diff: usize,
        old_snippet: &str,
        span: Span,
        process_last_snippet: F,
    ) where
        F: Fn(&mut FmtVisitor, &str, &str),
    {
        // Trim whitespace from the right hand side of each line.
        // Annoyingly, the library functions for splitting by lines etc. are not
        // quite right, so we must do it ourselves.
        let char_pos = self.codemap.lookup_char_pos(span.lo());
        let file_name = &char_pos.file.name.clone().into();
        let mut status = SnippetStatus::new(char_pos.line);

        let snippet = &*match self.config.emit_mode() {
            EmitMode::Coverage => Cow::from(replace_chars(old_snippet)),
            _ => Cow::from(old_snippet),
        };

        for (kind, offset, subslice) in CommentCodeSlices::new(snippet) {
            debug!("{:?}: {:?}", kind, subslice);

            let newline_count = count_newlines(subslice);
            let within_file_lines_range = self.config.file_lines().intersects_range(
                file_name,
                status.cur_line,
                status.cur_line + newline_count,
            );

            if CodeCharKind::Comment == kind && within_file_lines_range {
                // 1: comment.
                self.process_comment(
                    &mut status,
                    snippet,
                    &big_snippet[..(offset + big_diff)],
                    offset,
                    subslice,
                );
            } else if subslice.trim().is_empty() && newline_count > 0 && within_file_lines_range {
                // 2: blank lines.
                self.push_vertical_spaces(newline_count);
                status.cur_line += newline_count;
                status.line_start = offset + newline_count;
            } else {
                // 3: code which we failed to format or which is not within file-lines range.
                self.process_missing_code(&mut status, snippet, subslice, offset, file_name);
            }
        }

        process_last_snippet(self, &snippet[status.line_start..], snippet);
    }

    fn process_comment(
        &mut self,
        status: &mut SnippetStatus,
        snippet: &str,
        big_snippet: &str,
        offset: usize,
        subslice: &str,
    ) {
        let last_char = big_snippet
            .chars()
            .rev()
            .skip_while(|rev_c| [' ', '\t'].contains(rev_c))
            .next();

        let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c));

        let comment_indent = if fix_indent {
            if let Some('{') = last_char {
                self.push_str("\n");
            }
            let indent_str = self.block_indent.to_string(self.config);
            self.push_str(&indent_str);
            self.block_indent
        } else {
            self.push_str(" ");
            Indent::from_width(self.config, last_line_width(&self.buffer))
        };

        let comment_width = ::std::cmp::min(
            self.config.comment_width(),
            self.config.max_width() - self.block_indent.width(),
        );
        let comment_shape = Shape::legacy(comment_width, comment_indent);
        let comment_str = rewrite_comment(subslice, false, comment_shape, self.config)
            .unwrap_or_else(|| String::from(subslice));
        self.push_str(&comment_str);

        status.last_wspace = None;
        status.line_start = offset + subslice.len();

        if let Some('/') = subslice.chars().nth(1) {
            // check that there are no contained block comments
            if !subslice
                .split('\n')
                .map(|s| s.trim_left())
                .any(|s| s.len() >= 2 && &s[0..2] == "/*")
            {
                // Add a newline after line comments
                self.push_str("\n");
            }
        } else if status.line_start <= snippet.len() {
            // For other comments add a newline if there isn't one at the end already
            match snippet[status.line_start..].chars().next() {
                Some('\n') | Some('\r') => (),
                _ => self.push_str("\n"),
            }
        }

        status.cur_line += count_newlines(subslice);
    }

    fn process_missing_code(
        &mut self,
        status: &mut SnippetStatus,
        snippet: &str,
        subslice: &str,
        offset: usize,
        file_name: &FileName,
    ) {
        for (mut i, c) in subslice.char_indices() {
            i += offset;

            if c == '\n' {
                let skip_this_line = !self
                    .config
                    .file_lines()
                    .contains_line(file_name, status.cur_line);
                if skip_this_line {
                    status.last_wspace = None;
                }

                if let Some(lw) = status.last_wspace {
                    self.push_str(&snippet[status.line_start..lw]);
                    self.push_str("\n");
                    status.last_wspace = None;
                } else {
                    self.push_str(&snippet[status.line_start..i + 1]);
                }

                status.cur_line += 1;
                status.line_start = i + 1;
            } else if c.is_whitespace() && status.last_wspace.is_none() {
                status.last_wspace = Some(i);
            } else if c == ';' && status.last_wspace.is_some() {
                status.line_start = i;
                status.last_wspace = None;
            } else {
                status.last_wspace = None;
            }
        }

        let remaining = snippet[status.line_start..subslice.len() + offset].trim();
        if !remaining.is_empty() {
            self.push_str(remaining);
            status.line_start = subslice.len() + offset;
        }
    }
}

fn replace_chars(string: &str) -> String {
    string
        .chars()
        .map(|ch| if ch.is_whitespace() { ch } else { 'X' })
        .collect()
}
<commit_msg>Do not call format_missing_inner in a common case<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 std::borrow::Cow;

use syntax::codemap::{BytePos, Pos, Span};

use codemap::LineRangeUtils;
use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices};
use config::{EmitMode, FileName};
use shape::{Indent, Shape};
use utils::{count_newlines, last_line_width, mk_sp};
use visitor::FmtVisitor;

struct SnippetStatus {
    /// An offset to the current line from the beginnig of the original snippet.
    line_start: usize,
    /// A length of trailing whitespaces on the current line.
    last_wspace: Option<usize>,
    /// The current line number.
    cur_line: usize,
}

impl SnippetStatus {
    fn new(cur_line: usize) -> Self {
        SnippetStatus {
            line_start: 0,
            last_wspace: None,
            cur_line,
        }
    }
}

impl<'a> FmtVisitor<'a> {
    fn output_at_start(&self) -> bool {
        self.buffer.is_empty()
    }

    // TODO these format_missing methods are ugly. Refactor and add unit tests
    // for the central whitespace stripping loop.
    pub fn format_missing(&mut self, end: BytePos) {
        // HACK
        let missing_snippet = self.snippet(mk_sp(self.last_pos, end));
        if missing_snippet.trim() == ";" {
            self.push_str(";");
            self.last_pos = end;
            return;
        }
        self.format_missing_inner(end, |this, last_snippet, _| this.push_str(last_snippet))
    }

    pub fn format_missing_with_indent(&mut self, end: BytePos) {
        let config = self.config;
        self.format_missing_inner(end, |this, last_snippet, snippet| {
            this.push_str(last_snippet.trim_right());
            if last_snippet == snippet && !this.output_at_start() {
                // No new lines in the snippet.
                this.push_str("\n");
            }
            let indent = this.block_indent.to_string(config);
            this.push_str(&indent);
        })
    }

    pub fn format_missing_no_indent(&mut self, end: BytePos) {
        self.format_missing_inner(end, |this, last_snippet, _| {
            this.push_str(last_snippet.trim_right());
        })
    }

    fn format_missing_inner<F: Fn(&mut FmtVisitor, &str, &str)>(
        &mut self,
        end: BytePos,
        process_last_snippet: F,
    ) {
        let start = self.last_pos;

        if start == end {
            // Do nothing if this is the beginning of the file.
            if !self.output_at_start() {
                process_last_snippet(self, "", "");
            }
            return;
        }

        assert!(
            start < end,
            "Request to format inverted span: {:?} to {:?}",
            self.codemap.lookup_char_pos(start),
            self.codemap.lookup_char_pos(end)
        );

        self.last_pos = end;
        let span = mk_sp(start, end);
        let snippet = self.snippet(span);

        // Do nothing for spaces in the beginning of the file
        if start == BytePos(0) && end.0 as usize == snippet.len() && snippet.trim().is_empty() {
            return;
        }

        if snippet.trim().is_empty() && !out_of_file_lines_range!(self, span) {
            // Keep vertical spaces within range.
            self.push_vertical_spaces(count_newlines(snippet));
            process_last_snippet(self, "", snippet);
        } else {
            self.write_snippet(span, &process_last_snippet);
        }
    }

    fn push_vertical_spaces(&mut self, mut newline_count: usize) {
        let offset = self.count_trailing_newlines();
        let newline_upper_bound = self.config.blank_lines_upper_bound() + 1;
        let newline_lower_bound = self.config.blank_lines_lower_bound() + 1;

        if newline_count + offset > newline_upper_bound {
            if offset >= newline_upper_bound {
                newline_count = 0;
            } else {
                newline_count = newline_upper_bound - offset;
            }
        } else if newline_count + offset < newline_lower_bound {
            if offset >= newline_lower_bound {
                newline_count = 0;
            } else {
                newline_count = newline_lower_bound - offset;
            }
        }

        let blank_lines = "\n".repeat(newline_count);
        self.push_str(&blank_lines);
    }

    fn count_trailing_newlines(&self) -> usize {
        let mut buf = &*self.buffer;
        let mut result = 0;
        while buf.ends_with('\n') {
            buf = &buf[..buf.len() - 1];
            result += 1;
        }
        result
    }

    fn write_snippet<F>(&mut self, span: Span, process_last_snippet: F)
    where
        F: Fn(&mut FmtVisitor, &str, &str),
    {
        // Get a snippet from the file start to the span's hi without allocating.
        // We need it to determine what precedes the current comment. If the comment
        // follows code on the same line, we won't touch it.
        let big_span_lo = self.codemap.lookup_char_pos(span.lo()).file.start_pos;
        let local_begin = self.codemap.lookup_byte_offset(big_span_lo);
        let local_end = self.codemap.lookup_byte_offset(span.hi());
        let start_index = local_begin.pos.to_usize();
        let end_index = local_end.pos.to_usize();
        let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index];

        let big_diff = (span.lo() - big_span_lo).to_usize();
        let snippet = self.snippet(span);

        debug!("write_snippet `{}`", snippet);

        self.write_snippet_inner(big_snippet, big_diff, snippet, span, process_last_snippet);
    }

    fn write_snippet_inner<F>(
        &mut self,
        big_snippet: &str,
        big_diff: usize,
        old_snippet: &str,
        span: Span,
        process_last_snippet: F,
    ) where
        F: Fn(&mut FmtVisitor, &str, &str),
    {
        // Trim whitespace from the right hand side of each line.
        // Annoyingly, the library functions for splitting by lines etc. are not
        // quite right, so we must do it ourselves.
        let char_pos = self.codemap.lookup_char_pos(span.lo());
        let file_name = &char_pos.file.name.clone().into();
        let mut status = SnippetStatus::new(char_pos.line);

        let snippet = &*match self.config.emit_mode() {
            EmitMode::Coverage => Cow::from(replace_chars(old_snippet)),
            _ => Cow::from(old_snippet),
        };

        for (kind, offset, subslice) in CommentCodeSlices::new(snippet) {
            debug!("{:?}: {:?}", kind, subslice);

            let newline_count = count_newlines(subslice);
            let within_file_lines_range = self.config.file_lines().intersects_range(
                file_name,
                status.cur_line,
                status.cur_line + newline_count,
            );

            if CodeCharKind::Comment == kind && within_file_lines_range {
                // 1: comment.
                self.process_comment(
                    &mut status,
                    snippet,
                    &big_snippet[..(offset + big_diff)],
                    offset,
                    subslice,
                );
            } else if subslice.trim().is_empty() && newline_count > 0 && within_file_lines_range {
                // 2: blank lines.
                self.push_vertical_spaces(newline_count);
                status.cur_line += newline_count;
                status.line_start = offset + newline_count;
            } else {
                // 3: code which we failed to format or which is not within file-lines range.
                self.process_missing_code(&mut status, snippet, subslice, offset, file_name);
            }
        }

        process_last_snippet(self, &snippet[status.line_start..], snippet);
    }

    fn process_comment(
        &mut self,
        status: &mut SnippetStatus,
        snippet: &str,
        big_snippet: &str,
        offset: usize,
        subslice: &str,
    ) {
        let last_char = big_snippet
            .chars()
            .rev()
            .skip_while(|rev_c| [' ', '\t'].contains(rev_c))
            .next();

        let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c));

        let comment_indent = if fix_indent {
            if let Some('{') = last_char {
                self.push_str("\n");
            }
            let indent_str = self.block_indent.to_string(self.config);
            self.push_str(&indent_str);
            self.block_indent
        } else {
            self.push_str(" ");
            Indent::from_width(self.config, last_line_width(&self.buffer))
        };

        let comment_width = ::std::cmp::min(
            self.config.comment_width(),
            self.config.max_width() - self.block_indent.width(),
        );
        let comment_shape = Shape::legacy(comment_width, comment_indent);
        let comment_str = rewrite_comment(subslice, false, comment_shape, self.config)
            .unwrap_or_else(|| String::from(subslice));
        self.push_str(&comment_str);

        status.last_wspace = None;
        status.line_start = offset + subslice.len();

        if let Some('/') = subslice.chars().nth(1) {
            // check that there are no contained block comments
            if !subslice
                .split('\n')
                .map(|s| s.trim_left())
                .any(|s| s.len() >= 2 && &s[0..2] == "/*")
            {
                // Add a newline after line comments
                self.push_str("\n");
            }
        } else if status.line_start <= snippet.len() {
            // For other comments add a newline if there isn't one at the end already
            match snippet[status.line_start..].chars().next() {
                Some('\n') | Some('\r') => (),
                _ => self.push_str("\n"),
            }
        }

        status.cur_line += count_newlines(subslice);
    }

    fn process_missing_code(
        &mut self,
        status: &mut SnippetStatus,
        snippet: &str,
        subslice: &str,
        offset: usize,
        file_name: &FileName,
    ) {
        for (mut i, c) in subslice.char_indices() {
            i += offset;

            if c == '\n' {
                let skip_this_line = !self
                    .config
                    .file_lines()
                    .contains_line(file_name, status.cur_line);
                if skip_this_line {
                    status.last_wspace = None;
                }

                if let Some(lw) = status.last_wspace {
                    self.push_str(&snippet[status.line_start..lw]);
                    self.push_str("\n");
                    status.last_wspace = None;
                } else {
                    self.push_str(&snippet[status.line_start..i + 1]);
                }

                status.cur_line += 1;
                status.line_start = i + 1;
            } else if c.is_whitespace() && status.last_wspace.is_none() {
                status.last_wspace = Some(i);
            } else if c == ';' && status.last_wspace.is_some() {
                status.line_start = i;
                status.last_wspace = None;
            } else {
                status.last_wspace = None;
            }
        }

        let remaining = snippet[status.line_start..subslice.len() + offset].trim();
        if !remaining.is_empty() {
            self.push_str(remaining);
            status.line_start = subslice.len() + offset;
        }
    }
}

fn replace_chars(string: &str) -> String {
    string
        .chars()
        .map(|ch| if ch.is_whitespace() { ch } else { 'X' })
        .collect()
}
<|endoftext|>


<commit_before>//! The `zcode` module contains a lot of useful functionality
//! to deal with all the zcode related stuff

pub mod zbytes;
pub mod zfile;
pub mod ztext;

use utils::file;
use self::zfile::Zfile;

/// an example to show the current status of the z-code implementation
pub fn temp_create_zcode_example() {

    let mut zfile: Zfile = zfile::Zfile::new();
    /*zfile.start();
    zfile.op_call_1n("main");
    zfile.op_quit();

    zfile.routine("main", 0);
    zfile.op_set_color(0x02, 0x03);
    zfile.op_set_text_style(true, false,false,false);
    zfile.op_print("Z-char 6789abcdef0     1234567\n89abcdef");
    zfile.op_print_unicode_char(0x24);
    zfile.op_set_text_style(false, false,false,false);
    zfile.op_newline();
    zfile.op_print("current   --------------------------");
    zfile.op_set_text_style(false, false,false,false);
    zfile.op_newline();
    zfile.op_print("A0      abcdefghijklmnop\nqrstuvwxyz");
    zfile.op_set_text_style(false, true,false,false);
    zfile.op_newline();
    zfile.op_print("A1      ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    zfile.op_set_text_style(false, false,false,false);
    zfile.op_newline();
    zfile.op_print("A2      ^0123456789.,!?_#'\"/\\-:()");
    zfile.op_set_text_style(false, false,true,false);
    zfile.op_newline();
    zfile.op_print("          --------------------------");
    zfile.op_newline();

    zfile.op_quit();
    zfile.end();*/

    zfile.start();
    //zfile.op_inc(0x10);
    //zfile.op_push_u16(1234);
    //zfile.op_pull_u16(17);
    //zfile.op_print_num_var(17);
    zfile.op_call_1n("main");
    zfile.op_quit();

    zfile.routine("main", 1);
    zfile.op_print("main");
    zfile.op_print_num_var(0x01);
    zfile.op_print("-");
    zfile.op_print_num_var(0x30);
    zfile.op_newline();
    zfile.op_push_u16(1234);
    zfile.op_pull(0x20);

    zfile.op_print("Var 0x20: ");
    zfile.op_print_num_var(0x20);
    zfile.op_newline();
    zfile.op_inc(0x01);
    zfile.op_print("Var 0x01: ");
    zfile.op_print_num_var(0x01);
    zfile.op_newline();
    zfile.op_inc(0x01);
    zfile.op_print("Var 0x01: ");
    zfile.op_print_num_var(0x01);
    zfile.op_newline();

    zfile.label("loop");
    let local_var_id = 1;
    zfile.op_read_char(local_var_id);
    zfile.op_print_num_var(local_var_id);
    zfile.op_je(local_var_id, '1' as u8, "one");
    zfile.op_je(local_var_id, '2' as u8, "two");
    zfile.op_je(local_var_id, '3' as u8, "end");
    zfile.op_jump("loop");

    zfile.label("one");
    zfile.op_print("one");
    zfile.op_jump("loop");

    zfile.label("two");
    zfile.op_print("two");
    zfile.op_jump("loop");

    zfile.op_quit();
    zfile.end();

    file::save_bytes_to_file("helloworld.z8", &(*zfile.data.bytes));
}
<commit_msg>-delete comments<commit_after>//! The `zcode` module contains a lot of useful functionality
//! to deal with all the zcode related stuff

pub mod zbytes;
pub mod zfile;
pub mod ztext;

use utils::file;
use self::zfile::Zfile;

/// an example to show the current status of the z-code implementation
/// zcode playground function
pub fn temp_create_zcode_example() {

    let mut zfile: Zfile = zfile::Zfile::new();

    zfile.start();
    zfile.op_call_1n("main");
    zfile.op_quit();

    zfile.routine("main", 1);
    zfile.op_print("main");
    zfile.op_print_num_var(0x01);
    zfile.op_print("-");
    zfile.op_print_num_var(0x30);
    zfile.op_newline();
    zfile.op_push_u16(1234);
    zfile.op_pull(0x20);

    zfile.op_print("Var 0x20: ");
    zfile.op_print_num_var(0x20);
    zfile.op_newline();
    zfile.op_inc(0x01);
    zfile.op_print("Var 0x01: ");
    zfile.op_print_num_var(0x01);
    zfile.op_newline();
    zfile.op_inc(0x01);
    zfile.op_print("Var 0x01: ");
    zfile.op_print_num_var(0x01);
    zfile.op_newline();

    zfile.label("loop");
    let local_var_id = 1;
    zfile.op_read_char(local_var_id);
    zfile.op_print_num_var(local_var_id);
    zfile.op_je(local_var_id, '1' as u8, "one");
    zfile.op_je(local_var_id, '2' as u8, "two");
    zfile.op_je(local_var_id, '3' as u8, "end");
    zfile.op_jump("loop");

    zfile.label("one");
    zfile.op_print("one");
    zfile.op_jump("loop");

    zfile.label("two");
    zfile.op_print("two");
    zfile.op_jump("loop");

    zfile.op_quit();
    zfile.end();

    file::save_bytes_to_file("helloworld.z8", &(*zfile.data.bytes));
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate mio;

use self::mio::Token;

pub enum ConnectionType {
    TCP
}

/// Base Connection structure for handling base information of connection
pub struct Connection {
    pub value: u64,
    pub socket_token: Token,
    pub api_version: usize,
    pub conn_type: ConnectionType,
    pub from_server: bool
}
<commit_msg>Adding writer to base Connection struct<commit_after>#![allow(dead_code)]
extern crate mio;

use self::mio::Token;
use self::mio::channel::{Sender};
use network::tcp::TcpWriterCommand;

pub enum ConnectionType {
    TCP
}

/// Base Connection structure for handling base information of connection
pub struct Connection {
    pub value: u64,
    pub socket_token: Token,
    pub api_version: usize,
    pub conn_type: ConnectionType,
    pub from_server: bool,

    // writer command for TCP connection
    tcp_writer_chan: Sender<TcpWriterCommand>
}
<|endoftext|>