<commit_before>#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;
extern crate ratel;

use ratel::ast::{Node, ExpressionNode, Loc, Block, Pattern};
use ratel::Module;

mod expression;
mod statement;
mod function;

pub trait Generator: Sized {
    type Output;

    fn consume(self) -> Self::Output;
    fn write_byte(&mut self, u8);
    fn write_bytes(&mut self, &[u8]);
    fn write_pretty(&mut self, u8);

    #[inline]
    fn write<T>(&mut self, item: &T) where
        T: ToCode<Self>,
    {
        item.to_code(self);
    }

    /// Helper that adds parenthesis if required by the binding power of inner expression
    #[inline]
    fn write_expression<'ast>(&mut self, item: &ExpressionNode<'ast>, bp: u8) {
        if item.binding_power() < bp {
            self.write_byte(b'(');
            item.to_code(self);
            self.write_byte(b')');
        } else {
            item.to_code(self);
        }
    }

    #[inline]
    fn write_list<'a, T, I>(&mut self, items: I) where
        T: ToCode<Self> + 'a,
        I: IntoIterator<Item = &'a Node<'a, T>>,
    {
        let mut items = items.into_iter();

        if let Some(item) = items.next() {
            self.write(item);
        }

        for item in items {
            self.write_byte(b',');
            self.write_pretty(b' ');
            self.write(item);
        }
    }

    #[inline]
    fn write_block<'a, T, I>(&mut self, items: I) where
        T: ToCode<Self> + 'a,
        I: IntoIterator<Item = &'a Node<'a, T>>,
    {
        let mut items = items.into_iter();

        match items.next() {
            Some(item) => {
                self.indent();
                self.new_line();
                self.write(item);
            },
            None => return,
        }

        for item in items {
            self.new_line();
            self.write(item);
        }
        self.dedent();
        self.new_line();
    }

    #[inline]
    fn new_line(&mut self) {}

    #[inline]
    fn indent(&mut self) {}

    #[inline]
    fn dedent(&mut self) {}
}

pub struct MinifyingGenerator {
    code: Vec<u8>
}

impl MinifyingGenerator {
    fn new() -> Self {
        MinifyingGenerator {
            code: Vec::with_capacity(128)
        }
    }
}

impl Generator for MinifyingGenerator {
    type Output = String;

    fn consume(self) -> String {
        unsafe { String::from_utf8_unchecked(self.code) }
    }

    #[inline]
    fn write_byte(&mut self, ch: u8) {
        self.code.push(ch);
    }

    #[inline]
    fn write_pretty(&mut self, _: u8) {}

    #[inline]
    fn write_bytes(&mut self, slice: &[u8]) {
        extend_from_slice(&mut self.code, slice);
    }
}

struct PrettyGenerator {
    code: Vec<u8>,
    dent: usize,
}

impl PrettyGenerator {
    fn new() -> Self {
        PrettyGenerator {
            code: Vec::with_capacity(128),
            dent: 0,
        }
    }
}

impl Generator for PrettyGenerator {
    type Output = String;

    fn consume(self) -> String {
        unsafe { String::from_utf8_unchecked(self.code) }
    }

    #[inline]
    fn write_byte(&mut self, ch: u8) {
        self.code.push(ch);
    }

    #[inline]
    fn write_pretty(&mut self, ch: u8) {
        self.code.push(ch);
    }

    #[inline]
    fn write_bytes(&mut self, slice: &[u8]) {
        extend_from_slice(&mut self.code, slice);
    }

    #[inline]
    fn new_line(&mut self) {
        self.write_byte(b'\n');
        for _ in 0..self.dent {
            self.write_bytes(b"    ");
        }
    }

    #[inline]
    fn indent(&mut self) {
        self.dent += 1;
    }

    #[inline]
    fn dedent(&mut self) {
        self.dent -= 1;
    }
}

pub fn codegen(module: &Module, minify: bool) -> String {
    if minify {
        let mut gen = MinifyingGenerator::new();

        for statement in module.body() {
            gen.write(statement);
        }

        gen.consume()
    } else {
        let mut gen = PrettyGenerator::new();
        let mut body = module.body().iter();

        gen.write(&body.next().cloned());

        for statement in body {
            gen.new_line();
            gen.write(statement);
        }

        gen.consume()
    }
}

/// The `ToCode` trait provides an interface to pieces of grammar, that allows
/// to efficiently write characters and string slices to the code `Generator`.
pub trait ToCode<G: Generator> {
    fn to_code(&self, gen: &mut G);
}

impl<'ast, G, T> ToCode<G> for Node<'ast, T> where
    G: Generator,
    T: 'ast + ToCode<G>,
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        (**self).to_code(gen)
    }
}

impl<G, T> ToCode<G> for Loc<T> where
    G: Generator,
    T: ToCode<G>,
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        self.item.to_code(gen)
    }
}

impl<'a, G, T> ToCode<G> for &'a Loc<T> where
    G: Generator,
    T: ToCode<G>,
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        self.item.to_code(gen)
    }
}

impl<'a, G> ToCode<G> for &'a str where
    G: Generator,
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        gen.write_bytes(self.as_bytes())
    }
}

impl<G: Generator> ToCode<G> for u64 {
    #[inline]
    fn to_code(&self, gen: &mut G) {
        gen.write_bytes(format!("{}", self).as_str().as_bytes())
    }
}

impl<G, T> ToCode<G> for Option<T> where
    G: Generator,
    T: ToCode<G>
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        if let Some(ref val) = *self {
            gen.write(val);
        }
    }
}

impl<'ast, G, T> ToCode<G> for Block<'ast, T> where
    G: Generator,
    T: ToCode<G>
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        gen.write_byte(b'{');
        gen.write_block(&self.body);
        gen.write_byte(b'}');
    }
}

impl<'ast, G: Generator> ToCode<G> for Pattern<'ast> {
    #[inline]
    fn to_code(&self, gen: &mut G) {
        use ratel::ast::Pattern::*;

        match *self {
            Void => {},
            Identifier(ref ident) => gen.write(ident),
            ObjectPattern {
                ref properties,
            } => {
                gen.write_byte(b'{');
                gen.write_list(properties);
                gen.write_byte(b'}');
            },
            ArrayPattern {
                ref elements,
            } => {
                gen.write_byte(b'[');
                gen.write_list(elements);
                gen.write_byte(b']');
            },
            RestElement {
                ref argument,
            } => {
                gen.write_bytes(b"...");
                gen.write(argument);
            },
            AssignmentPattern {
                ref left,
                ref right,
            } => {
                gen.write(left);
                gen.write_pretty(b' ');
                gen.write_byte(b'=');
                gen.write_pretty(b' ');
                gen.write(right);
            }
        }
    }
}

// From: https://github.com/dtolnay/fastwrite/blob/master/src/lib.rs#L68
//
// LLVM is not able to lower `Vec::extend_from_slice` into a memcpy, so this
// helps eke out that last bit of performance.
#[inline]
fn extend_from_slice(dst: &mut Vec<u8>, src: &[u8]) {
    let dst_len = dst.len();
    let src_len = src.len();

    dst.reserve(src_len);

    unsafe {
        // We would have failed if `reserve` overflowed
        dst.set_len(dst_len + src_len);

        ::std::ptr::copy_nonoverlapping(
            src.as_ptr(),
            dst.as_mut_ptr().add(dst_len),
            src_len);
    }
}

#[cfg(test)]
fn assert_min(source: &str, expected: &str) {
    use ratel::parse;

    let module = parse(source).unwrap();

    assert_eq!(codegen(&module, true).as_str(), expected);
}

#[cfg(test)]
fn assert_pretty(source: &str, expected: &str) {
    use ratel::parse;

    let module = parse(source).unwrap();

    assert_eq!(codegen(&module, false).as_str(), expected);
}
<commit_msg>Make ratel_codegen::PrettyGenerator and new methods public<commit_after>#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;
extern crate ratel;

use ratel::ast::{Node, ExpressionNode, Loc, Block, Pattern};
use ratel::Module;

mod expression;
mod statement;
mod function;

pub trait Generator: Sized {
    type Output;

    fn consume(self) -> Self::Output;
    fn write_byte(&mut self, u8);
    fn write_bytes(&mut self, &[u8]);
    fn write_pretty(&mut self, u8);

    #[inline]
    fn write<T>(&mut self, item: &T) where
        T: ToCode<Self>,
    {
        item.to_code(self);
    }

    /// Helper that adds parenthesis if required by the binding power of inner expression
    #[inline]
    fn write_expression<'ast>(&mut self, item: &ExpressionNode<'ast>, bp: u8) {
        if item.binding_power() < bp {
            self.write_byte(b'(');
            item.to_code(self);
            self.write_byte(b')');
        } else {
            item.to_code(self);
        }
    }

    #[inline]
    fn write_list<'a, T, I>(&mut self, items: I) where
        T: ToCode<Self> + 'a,
        I: IntoIterator<Item = &'a Node<'a, T>>,
    {
        let mut items = items.into_iter();

        if let Some(item) = items.next() {
            self.write(item);
        }

        for item in items {
            self.write_byte(b',');
            self.write_pretty(b' ');
            self.write(item);
        }
    }

    #[inline]
    fn write_block<'a, T, I>(&mut self, items: I) where
        T: ToCode<Self> + 'a,
        I: IntoIterator<Item = &'a Node<'a, T>>,
    {
        let mut items = items.into_iter();

        match items.next() {
            Some(item) => {
                self.indent();
                self.new_line();
                self.write(item);
            },
            None => return,
        }

        for item in items {
            self.new_line();
            self.write(item);
        }
        self.dedent();
        self.new_line();
    }

    #[inline]
    fn new_line(&mut self) {}

    #[inline]
    fn indent(&mut self) {}

    #[inline]
    fn dedent(&mut self) {}
}

pub struct MinifyingGenerator {
    code: Vec<u8>
}

impl MinifyingGenerator {
    pub fn new() -> Self {
        MinifyingGenerator {
            code: Vec::with_capacity(128)
        }
    }
}

impl Generator for MinifyingGenerator {
    type Output = String;

    fn consume(self) -> String {
        unsafe { String::from_utf8_unchecked(self.code) }
    }

    #[inline]
    fn write_byte(&mut self, ch: u8) {
        self.code.push(ch);
    }

    #[inline]
    fn write_pretty(&mut self, _: u8) {}

    #[inline]
    fn write_bytes(&mut self, slice: &[u8]) {
        extend_from_slice(&mut self.code, slice);
    }
}

pub struct PrettyGenerator {
    code: Vec<u8>,
    dent: usize,
}

impl PrettyGenerator {
    pub fn new() -> Self {
        PrettyGenerator {
            code: Vec::with_capacity(128),
            dent: 0,
        }
    }
}

impl Generator for PrettyGenerator {
    type Output = String;

    fn consume(self) -> String {
        unsafe { String::from_utf8_unchecked(self.code) }
    }

    #[inline]
    fn write_byte(&mut self, ch: u8) {
        self.code.push(ch);
    }

    #[inline]
    fn write_pretty(&mut self, ch: u8) {
        self.code.push(ch);
    }

    #[inline]
    fn write_bytes(&mut self, slice: &[u8]) {
        extend_from_slice(&mut self.code, slice);
    }

    #[inline]
    fn new_line(&mut self) {
        self.write_byte(b'\n');
        for _ in 0..self.dent {
            self.write_bytes(b"    ");
        }
    }

    #[inline]
    fn indent(&mut self) {
        self.dent += 1;
    }

    #[inline]
    fn dedent(&mut self) {
        self.dent -= 1;
    }
}

pub fn codegen(module: &Module, minify: bool) -> String {
    if minify {
        let mut gen = MinifyingGenerator::new();

        for statement in module.body() {
            gen.write(statement);
        }

        gen.consume()
    } else {
        let mut gen = PrettyGenerator::new();
        let mut body = module.body().iter();

        gen.write(&body.next().cloned());

        for statement in body {
            gen.new_line();
            gen.write(statement);
        }

        gen.consume()
    }
}

/// The `ToCode` trait provides an interface to pieces of grammar, that allows
/// to efficiently write characters and string slices to the code `Generator`.
pub trait ToCode<G: Generator> {
    fn to_code(&self, gen: &mut G);
}

impl<'ast, G, T> ToCode<G> for Node<'ast, T> where
    G: Generator,
    T: 'ast + ToCode<G>,
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        (**self).to_code(gen)
    }
}

impl<G, T> ToCode<G> for Loc<T> where
    G: Generator,
    T: ToCode<G>,
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        self.item.to_code(gen)
    }
}

impl<'a, G, T> ToCode<G> for &'a Loc<T> where
    G: Generator,
    T: ToCode<G>,
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        self.item.to_code(gen)
    }
}

impl<'a, G> ToCode<G> for &'a str where
    G: Generator,
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        gen.write_bytes(self.as_bytes())
    }
}

impl<G: Generator> ToCode<G> for u64 {
    #[inline]
    fn to_code(&self, gen: &mut G) {
        gen.write_bytes(format!("{}", self).as_str().as_bytes())
    }
}

impl<G, T> ToCode<G> for Option<T> where
    G: Generator,
    T: ToCode<G>
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        if let Some(ref val) = *self {
            gen.write(val);
        }
    }
}

impl<'ast, G, T> ToCode<G> for Block<'ast, T> where
    G: Generator,
    T: ToCode<G>
{
    #[inline]
    fn to_code(&self, gen: &mut G) {
        gen.write_byte(b'{');
        gen.write_block(&self.body);
        gen.write_byte(b'}');
    }
}

impl<'ast, G: Generator> ToCode<G> for Pattern<'ast> {
    #[inline]
    fn to_code(&self, gen: &mut G) {
        use ratel::ast::Pattern::*;

        match *self {
            Void => {},
            Identifier(ref ident) => gen.write(ident),
            ObjectPattern {
                ref properties,
            } => {
                gen.write_byte(b'{');
                gen.write_list(properties);
                gen.write_byte(b'}');
            },
            ArrayPattern {
                ref elements,
            } => {
                gen.write_byte(b'[');
                gen.write_list(elements);
                gen.write_byte(b']');
            },
            RestElement {
                ref argument,
            } => {
                gen.write_bytes(b"...");
                gen.write(argument);
            },
            AssignmentPattern {
                ref left,
                ref right,
            } => {
                gen.write(left);
                gen.write_pretty(b' ');
                gen.write_byte(b'=');
                gen.write_pretty(b' ');
                gen.write(right);
            }
        }
    }
}

// From: https://github.com/dtolnay/fastwrite/blob/master/src/lib.rs#L68
//
// LLVM is not able to lower `Vec::extend_from_slice` into a memcpy, so this
// helps eke out that last bit of performance.
#[inline]
fn extend_from_slice(dst: &mut Vec<u8>, src: &[u8]) {
    let dst_len = dst.len();
    let src_len = src.len();

    dst.reserve(src_len);

    unsafe {
        // We would have failed if `reserve` overflowed
        dst.set_len(dst_len + src_len);

        ::std::ptr::copy_nonoverlapping(
            src.as_ptr(),
            dst.as_mut_ptr().add(dst_len),
            src_len);
    }
}

#[cfg(test)]
fn assert_min(source: &str, expected: &str) {
    use ratel::parse;

    let module = parse(source).unwrap();

    assert_eq!(codegen(&module, true).as_str(), expected);
}

#[cfg(test)]
fn assert_pretty(source: &str, expected: &str) {
    use ratel::parse;

    let module = parse(source).unwrap();

    assert_eq!(codegen(&module, false).as_str(), expected);
}
<|endoftext|>


<commit_before>//! This file contains the types necessary to collect various types of stats.
use crate::loom::sync::atomic::{AtomicU64, Ordering::Relaxed};

use std::convert::TryFrom;
use std::time::{Duration, Instant};

/// This type contains methods to retrieve stats from a Tokio runtime.
#[derive(Debug)]
pub struct RuntimeStats {
    workers: Box<[WorkerStats]>,
}

/// This type contains methods to retrieve stats from a worker thread on a Tokio runtime.
#[derive(Debug)]
#[repr(align(128))]
pub struct WorkerStats {
    park_count: AtomicU64,
    steal_count: AtomicU64,
    poll_count: AtomicU64,
    busy_duration_min: AtomicU64,
    busy_duration_max: AtomicU64,
    busy_duration_last: AtomicU64,
    busy_duration_total: AtomicU64,
}

impl RuntimeStats {
    pub(crate) fn new(worker_threads: usize) -> Self {
        let mut workers = Vec::with_capacity(worker_threads);
        for _ in 0..worker_threads {
            workers.push(WorkerStats {
                park_count: AtomicU64::new(0),
                steal_count: AtomicU64::new(0),
                poll_count: AtomicU64::new(0),
                busy_duration_min: AtomicU64::new(0),
                busy_duration_max: AtomicU64::new(0),
                busy_duration_last: AtomicU64::new(0),
                busy_duration_total: AtomicU64::new(0),
            });
        }

        Self {
            workers: workers.into_boxed_slice(),
        }
    }

    /// Returns a slice containing the worker stats for each worker thread.
    pub fn workers(&self) -> impl Iterator<Item = &WorkerStats> {
        self.workers.iter()
    }
}

impl WorkerStats {
    /// Returns the total number of times this worker thread has parked.
    pub fn park_count(&self) -> u64 {
        self.park_count.load(Relaxed)
    }

    /// Returns the number of tasks this worker has stolen from other worker
    /// threads.
    pub fn steal_count(&self) -> u64 {
        self.steal_count.load(Relaxed)
    }

    /// Returns the number of times this worker has polled a task.
    pub fn poll_count(&self) -> u64 {
        self.poll_count.load(Relaxed)
    }

    /// Returns the duration for which the runtime was busy last time it was busy.
    pub fn busy_duration_last(&self) -> Duration {
        Duration::from_nanos(self.busy_duration_last.load(Relaxed))
    }

    /// Returns the total amount of time this worker has been busy for.
    pub fn busy_duration_total(&self) -> Duration {
        Duration::from_nanos(self.busy_duration_total.load(Relaxed))
    }

    /// Returns the smallest busy duration since the last 16 parks.
    pub fn busy_duration_min(&self) -> Duration {
        Duration::from_nanos(self.busy_duration_min.load(Relaxed))
    }

    /// Returns the largest busy duration since the last 16 parks.
    pub fn busy_duration_max(&self) -> Duration {
        Duration::from_nanos(self.busy_duration_max.load(Relaxed))
    }
}

pub(crate) struct WorkerStatsBatcher {
    my_index: usize,
    park_count: u64,
    steal_count: u64,
    poll_count: u64,
    /// The last 16 busy durations in nanoseconds.
    ///
    /// This array is set to contain the same value 16 times after the first
    /// iteration. Since we only publish the min, max and last value in the
    /// array, then this gives the correct result.
    busy_duration: [u64; 16],
    busy_duration_i: usize,
    /// The total busy duration in nanoseconds.
    busy_duration_total: u64,
    last_resume_time: Instant,
}

impl WorkerStatsBatcher {
    pub(crate) fn new(my_index: usize) -> Self {
        Self {
            my_index,
            park_count: 0,
            steal_count: 0,
            poll_count: 0,
            busy_duration: [0; 16],
            busy_duration_i: usize::MAX,
            busy_duration_total: 0,
            last_resume_time: Instant::now(),
        }
    }
    pub(crate) fn submit(&mut self, to: &RuntimeStats) {
        let worker = &to.workers[self.my_index];

        worker.park_count.store(self.park_count, Relaxed);
        worker.steal_count.store(self.steal_count, Relaxed);
        worker.poll_count.store(self.poll_count, Relaxed);

        let mut min = u64::MAX;
        let mut max = 0;
        let last = self.busy_duration[self.busy_duration_i % 16];
        for &val in &self.busy_duration {
            if val <= min {
                min = val;
            }
            if val >= max {
                max = val;
            }
        }
        worker.busy_duration_min.store(min, Relaxed);
        worker.busy_duration_max.store(max, Relaxed);
        worker.busy_duration_last.store(last, Relaxed);
        worker
            .busy_duration_total
            .store(self.busy_duration_total, Relaxed);
    }

    pub(crate) fn about_to_park(&mut self) {
        self.park_count += 1;

        let busy_duration = self.last_resume_time.elapsed();
        let busy_duration = u64::try_from(busy_duration.as_nanos()).unwrap_or(u64::MAX);
        self.busy_duration_total += busy_duration;
        if self.busy_duration_i == usize::MAX {
            // We are parking for the first time. Set array to contain current
            // duration in every slot.
            self.busy_duration_i = 0;
            self.busy_duration = [busy_duration; 16];
        } else {
            self.busy_duration_i = (self.busy_duration_i + 1) % 16;
            self.busy_duration[self.busy_duration_i] = busy_duration;
        }
    }

    pub(crate) fn returned_from_park(&mut self) {
        self.last_resume_time = Instant::now();
    }

    #[cfg(feature = "rt-multi-thread")]
    pub(crate) fn incr_steal_count(&mut self, by: u16) {
        self.steal_count += u64::from(by);
    }

    pub(crate) fn incr_poll_count(&mut self) {
        self.poll_count += 1;
    }
}
<commit_msg>stats: only expose `busy_duration_total` (#4223)<commit_after>//! This file contains the types necessary to collect various types of stats.
use crate::loom::sync::atomic::{AtomicU64, Ordering::Relaxed};

use std::convert::TryFrom;
use std::time::{Duration, Instant};

/// This type contains methods to retrieve stats from a Tokio runtime.
#[derive(Debug)]
pub struct RuntimeStats {
    workers: Box<[WorkerStats]>,
}

/// This type contains methods to retrieve stats from a worker thread on a Tokio runtime.
#[derive(Debug)]
#[repr(align(128))]
pub struct WorkerStats {
    park_count: AtomicU64,
    steal_count: AtomicU64,
    poll_count: AtomicU64,
    busy_duration_total: AtomicU64,
}

impl RuntimeStats {
    pub(crate) fn new(worker_threads: usize) -> Self {
        let mut workers = Vec::with_capacity(worker_threads);
        for _ in 0..worker_threads {
            workers.push(WorkerStats {
                park_count: AtomicU64::new(0),
                steal_count: AtomicU64::new(0),
                poll_count: AtomicU64::new(0),
                busy_duration_total: AtomicU64::new(0),
            });
        }

        Self {
            workers: workers.into_boxed_slice(),
        }
    }

    /// Returns a slice containing the worker stats for each worker thread.
    pub fn workers(&self) -> impl Iterator<Item = &WorkerStats> {
        self.workers.iter()
    }
}

impl WorkerStats {
    /// Returns the total number of times this worker thread has parked.
    pub fn park_count(&self) -> u64 {
        self.park_count.load(Relaxed)
    }

    /// Returns the number of tasks this worker has stolen from other worker
    /// threads.
    pub fn steal_count(&self) -> u64 {
        self.steal_count.load(Relaxed)
    }

    /// Returns the number of times this worker has polled a task.
    pub fn poll_count(&self) -> u64 {
        self.poll_count.load(Relaxed)
    }

    /// Returns the total amount of time this worker has been busy for.
    pub fn total_busy_duration(&self) -> Duration {
        Duration::from_nanos(self.busy_duration_total.load(Relaxed))
    }
}

pub(crate) struct WorkerStatsBatcher {
    my_index: usize,
    park_count: u64,
    steal_count: u64,
    poll_count: u64,
    /// The total busy duration in nanoseconds.
    busy_duration_total: u64,
    last_resume_time: Instant,
}

impl WorkerStatsBatcher {
    pub(crate) fn new(my_index: usize) -> Self {
        Self {
            my_index,
            park_count: 0,
            steal_count: 0,
            poll_count: 0,
            busy_duration_total: 0,
            last_resume_time: Instant::now(),
        }
    }
    pub(crate) fn submit(&mut self, to: &RuntimeStats) {
        let worker = &to.workers[self.my_index];

        worker.park_count.store(self.park_count, Relaxed);
        worker.steal_count.store(self.steal_count, Relaxed);
        worker.poll_count.store(self.poll_count, Relaxed);

        worker
            .busy_duration_total
            .store(self.busy_duration_total, Relaxed);
    }

    pub(crate) fn about_to_park(&mut self) {
        self.park_count += 1;

        let busy_duration = self.last_resume_time.elapsed();
        let busy_duration = u64::try_from(busy_duration.as_nanos()).unwrap_or(u64::MAX);
        self.busy_duration_total += busy_duration;
    }

    pub(crate) fn returned_from_park(&mut self) {
        self.last_resume_time = Instant::now();
    }

    #[cfg(feature = "rt-multi-thread")]
    pub(crate) fn incr_steal_count(&mut self, by: u16) {
        self.steal_count += u64::from(by);
    }

    pub(crate) fn incr_poll_count(&mut self) {
        self.poll_count += 1;
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use ipc_channel::ipc;
use net::resource_task::new_resource_task;
use net_traits::hosts::{parse_hostsfile, host_replacement};
use net_traits::{ControlMsg, LoadData, LoadConsumer, ProgressMsg};
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::sync::mpsc::channel;
use url::Url;

#[test]
fn test_exit() {
    let resource_task = new_resource_task("".to_owned(), None);
    resource_task.send(ControlMsg::Exit).unwrap();
}

#[test]
fn test_bad_scheme() {
    let resource_task = new_resource_task("".to_owned(), None);
    let (start_chan, start) = ipc::channel().unwrap();
    let url = Url::parse("bogus://whatever").unwrap();
    resource_task.send(ControlMsg::Load(LoadData::new(url, None), LoadConsumer::Channel(start_chan))).unwrap();
    let response = start.recv().unwrap();
    match response.progress_port.recv().unwrap() {
      ProgressMsg::Done(result) => { assert!(result.is_err()) }
      _ => panic!("bleh")
    }
    resource_task.send(ControlMsg::Exit).unwrap();
}

#[test]
fn test_parse_hostsfile() {
    let mock_hosts_file_content = "127.0.0.1 foo.bar.com\n127.0.0.2 servo.test.server";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(2, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
    assert_eq!("127.0.0.2".to_owned(), *hosts_table.get(&"servo.test.server".to_owned()).unwrap());
}

#[test]
fn test_parse_malformed_hostsfile() {
    let mock_hosts_file_content = "malformed file\n127.0.0.1 foo.bar.com\nservo.test.server 127.0.0.1";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(1, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_line_comment() {
    let mock_hosts_file_content = "# this is a line comment\n127.0.0.1 foo.bar.com\n# anothercomment";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(1, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_end_of_line_comment() {
    let mock_hosts_file_content = "127.0.0.1 foo.bar.com # line ending comment\n127.0.0.2 servo.test.server #comment";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(2, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
    assert_eq!("127.0.0.2".to_owned(), *hosts_table.get(&"servo.test.server".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_2_hostnames_for_1_address() {
    let mock_hosts_file_content = "127.0.0.1 foo.bar.com baz.bar.com";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(2, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"baz.bar.com".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_4_hostnames_for_1_address() {
    let mock_hosts_file_content = "127.0.0.1 moz.foo.com moz.bar.com moz.baz.com moz.moz.com";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(4, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"moz.foo.com".to_owned()).unwrap());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"moz.bar.com".to_owned()).unwrap());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"moz.baz.com".to_owned()).unwrap());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"moz.moz.com".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_tabs_instead_spaces() {
    let mock_hosts_file_content = "127.0.0.1\tfoo.bar.com\n127.0.0.2\tservo.test.server";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(2, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
    assert_eq!("127.0.0.2".to_owned(), *hosts_table.get(&"servo.test.server".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_valid_ipv4_addresses()
{
    let mock_hosts_file_content =
        "255.255.255.255 foo.bar.com\n169.0.1.201 servo.test.server\n192.168.5.0 servo.foo.com";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(3, (*hosts_table).len());
}

#[test]
fn test_parse_hostsfile_with_invalid_ipv4_addresses()
{
    let mock_hosts_file_content = "256.255.255.255 foo.bar.com\n169.0.1000.201 servo.test.server \
                                   \n192.168.5.500 servo.foo.com\n192.abc.100.2 test.servo.com";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(0, (*hosts_table).len());
}

#[test]
fn test_parse_hostsfile_with_valid_ipv6_addresses()
{
    let mock_hosts_file_content = "2001:0db8:0000:0000:0000:ff00:0042:8329 foo.bar.com\n\
                                   2001:db8:0:0:0:ff00:42:8329 moz.foo.com\n\
                                   2001:db8::ff00:42:8329 foo.moz.com moz.moz.com\n\
                                   0000:0000:0000:0000:0000:0000:0000:0001 bar.moz.com\n\
                                   ::1 foo.bar.baz baz.foo.com\n\
                                   2001:0DB8:85A3:0042:1000:8A2E:0370:7334 baz.bar.moz\n\
                                   2002:0DB8:85A3:0042:1000:8A2E:0370:7334/96 baz2.bar.moz\n\
                                   2002:0DB8:85A3:0042:1000:8A2E:0370:7334/128 baz3.bar.moz\n\
                                   :: unspecified.moz.com\n\
                                   ::/128 unspecified.address.com";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(12, (*hosts_table).len());
}

#[test]
fn test_parse_hostsfile_with_invalid_ipv6_addresses()
{
    let mock_hosts_file_content = "12001:0db8:0000:0000:0000:ff00:0042:8329 foo.bar.com\n\
                                   2001:zdb8:0:0:0:gg00:42:t329 moz.foo.com\n\
                                   2001:db8::ff00:42:8329:1111:1111:42 foo.moz.com moz.moz.com\n\
                                   2002:0DB8:85A3:0042:1000:8A2E:0370:7334/1289 baz3.bar.moz";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(0, (*hosts_table).len());
}

#[test]
fn test_parse_hostsfile_with_end_of_line_whitespace()
{
    let mock_hosts_file_content = "127.0.0.1 foo.bar.com \n\
                                   2001:db8:0:0:0:ff00:42:8329 moz.foo.com\n \
                                   127.0.0.2 servo.test.server ";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(3, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
    assert_eq!("2001:db8:0:0:0:ff00:42:8329".to_owned(), *hosts_table.get(&"moz.foo.com".to_owned()).unwrap());
    assert_eq!("127.0.0.2".to_owned(), *hosts_table.get(&"servo.test.server".to_owned()).unwrap());
}

#[test]
fn test_replace_hosts() {
    let mut host_table_box = Box::new(HashMap::new());
    host_table_box.insert("foo.bar.com".to_owned(), "127.0.0.1".to_owned());
    host_table_box.insert("servo.test.server".to_owned(), "127.0.0.2".to_owned());

    let host_table: *mut HashMap<String, String> = Box::into_raw(host_table_box);

    let url = Url::parse("http://foo.bar.com:8000/foo").unwrap();
    assert_eq!(host_replacement(host_table, &url).domain().unwrap(), "127.0.0.1");

    let url = Url::parse("http://servo.test.server").unwrap();
    assert_eq!(host_replacement(host_table, &url).domain().unwrap(), "127.0.0.2");

    let url = Url::parse("http://a.foo.bar.com").unwrap();
    assert_eq!(host_replacement(host_table, &url).domain().unwrap(), "a.foo.bar.com");
}
<commit_msg>Disable tests that hit a race condition in rust-openssl<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use ipc_channel::ipc;
use net::resource_task::new_resource_task;
use net_traits::hosts::{parse_hostsfile, host_replacement};
use net_traits::{ControlMsg, LoadData, LoadConsumer, ProgressMsg};
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::sync::mpsc::channel;
use url::Url;

// Disabled, per https://github.com/sfackler/rust-openssl/issues/281
//#[test]
fn test_exit() {
    let resource_task = new_resource_task("".to_owned(), None);
    resource_task.send(ControlMsg::Exit).unwrap();
}

// Disabled, per https://github.com/sfackler/rust-openssl/issues/281
//#[test]
fn test_bad_scheme() {
    let resource_task = new_resource_task("".to_owned(), None);
    let (start_chan, start) = ipc::channel().unwrap();
    let url = Url::parse("bogus://whatever").unwrap();
    resource_task.send(ControlMsg::Load(LoadData::new(url, None), LoadConsumer::Channel(start_chan))).unwrap();
    let response = start.recv().unwrap();
    match response.progress_port.recv().unwrap() {
      ProgressMsg::Done(result) => { assert!(result.is_err()) }
      _ => panic!("bleh")
    }
    resource_task.send(ControlMsg::Exit).unwrap();
}

#[test]
fn test_parse_hostsfile() {
    let mock_hosts_file_content = "127.0.0.1 foo.bar.com\n127.0.0.2 servo.test.server";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(2, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
    assert_eq!("127.0.0.2".to_owned(), *hosts_table.get(&"servo.test.server".to_owned()).unwrap());
}

#[test]
fn test_parse_malformed_hostsfile() {
    let mock_hosts_file_content = "malformed file\n127.0.0.1 foo.bar.com\nservo.test.server 127.0.0.1";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(1, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_line_comment() {
    let mock_hosts_file_content = "# this is a line comment\n127.0.0.1 foo.bar.com\n# anothercomment";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(1, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_end_of_line_comment() {
    let mock_hosts_file_content = "127.0.0.1 foo.bar.com # line ending comment\n127.0.0.2 servo.test.server #comment";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(2, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
    assert_eq!("127.0.0.2".to_owned(), *hosts_table.get(&"servo.test.server".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_2_hostnames_for_1_address() {
    let mock_hosts_file_content = "127.0.0.1 foo.bar.com baz.bar.com";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(2, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"baz.bar.com".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_4_hostnames_for_1_address() {
    let mock_hosts_file_content = "127.0.0.1 moz.foo.com moz.bar.com moz.baz.com moz.moz.com";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(4, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"moz.foo.com".to_owned()).unwrap());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"moz.bar.com".to_owned()).unwrap());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"moz.baz.com".to_owned()).unwrap());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"moz.moz.com".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_tabs_instead_spaces() {
    let mock_hosts_file_content = "127.0.0.1\tfoo.bar.com\n127.0.0.2\tservo.test.server";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(2, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
    assert_eq!("127.0.0.2".to_owned(), *hosts_table.get(&"servo.test.server".to_owned()).unwrap());
}

#[test]
fn test_parse_hostsfile_with_valid_ipv4_addresses()
{
    let mock_hosts_file_content =
        "255.255.255.255 foo.bar.com\n169.0.1.201 servo.test.server\n192.168.5.0 servo.foo.com";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(3, (*hosts_table).len());
}

#[test]
fn test_parse_hostsfile_with_invalid_ipv4_addresses()
{
    let mock_hosts_file_content = "256.255.255.255 foo.bar.com\n169.0.1000.201 servo.test.server \
                                   \n192.168.5.500 servo.foo.com\n192.abc.100.2 test.servo.com";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(0, (*hosts_table).len());
}

#[test]
fn test_parse_hostsfile_with_valid_ipv6_addresses()
{
    let mock_hosts_file_content = "2001:0db8:0000:0000:0000:ff00:0042:8329 foo.bar.com\n\
                                   2001:db8:0:0:0:ff00:42:8329 moz.foo.com\n\
                                   2001:db8::ff00:42:8329 foo.moz.com moz.moz.com\n\
                                   0000:0000:0000:0000:0000:0000:0000:0001 bar.moz.com\n\
                                   ::1 foo.bar.baz baz.foo.com\n\
                                   2001:0DB8:85A3:0042:1000:8A2E:0370:7334 baz.bar.moz\n\
                                   2002:0DB8:85A3:0042:1000:8A2E:0370:7334/96 baz2.bar.moz\n\
                                   2002:0DB8:85A3:0042:1000:8A2E:0370:7334/128 baz3.bar.moz\n\
                                   :: unspecified.moz.com\n\
                                   ::/128 unspecified.address.com";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(12, (*hosts_table).len());
}

#[test]
fn test_parse_hostsfile_with_invalid_ipv6_addresses()
{
    let mock_hosts_file_content = "12001:0db8:0000:0000:0000:ff00:0042:8329 foo.bar.com\n\
                                   2001:zdb8:0:0:0:gg00:42:t329 moz.foo.com\n\
                                   2001:db8::ff00:42:8329:1111:1111:42 foo.moz.com moz.moz.com\n\
                                   2002:0DB8:85A3:0042:1000:8A2E:0370:7334/1289 baz3.bar.moz";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(0, (*hosts_table).len());
}

#[test]
fn test_parse_hostsfile_with_end_of_line_whitespace()
{
    let mock_hosts_file_content = "127.0.0.1 foo.bar.com \n\
                                   2001:db8:0:0:0:ff00:42:8329 moz.foo.com\n \
                                   127.0.0.2 servo.test.server ";
    let hosts_table = parse_hostsfile(mock_hosts_file_content);
    assert_eq!(3, (*hosts_table).len());
    assert_eq!("127.0.0.1".to_owned(), *hosts_table.get(&"foo.bar.com".to_owned()).unwrap());
    assert_eq!("2001:db8:0:0:0:ff00:42:8329".to_owned(), *hosts_table.get(&"moz.foo.com".to_owned()).unwrap());
    assert_eq!("127.0.0.2".to_owned(), *hosts_table.get(&"servo.test.server".to_owned()).unwrap());
}

#[test]
fn test_replace_hosts() {
    let mut host_table_box = Box::new(HashMap::new());
    host_table_box.insert("foo.bar.com".to_owned(), "127.0.0.1".to_owned());
    host_table_box.insert("servo.test.server".to_owned(), "127.0.0.2".to_owned());

    let host_table: *mut HashMap<String, String> = Box::into_raw(host_table_box);

    let url = Url::parse("http://foo.bar.com:8000/foo").unwrap();
    assert_eq!(host_replacement(host_table, &url).domain().unwrap(), "127.0.0.1");

    let url = Url::parse("http://servo.test.server").unwrap();
    assert_eq!(host_replacement(host_table, &url).domain().unwrap(), "127.0.0.2");

    let url = Url::parse("http://a.foo.bar.com").unwrap();
    assert_eq!(host_replacement(host_table, &url).domain().unwrap(), "a.foo.bar.com");
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate tokio_core;

#[macro_use]
extern crate reql;
extern crate reql_types;

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use reql_types::Change;
use futures::stream::Stream;
use tokio_core::reactor::Core;
use reql::{Client, Document, Run};

/**
 * rethinkdb changelog example
 * After running, access your admin panel at localhost:8080
 *
 * setup a "test" database, with a "test" table, and run:
 *
 * // Insert an item
 * r.db('test').table('test').insert({ test: 1 });
 *
 * // Give the first item a random number
 * r.db('test').table('test').nth(0).update({ test: r.random(0, 100) }, { nonAtomic: true });
 *
 * // Remove the first item
 * r.db('test').table('test').nth(0).delete();
 */

/**
 * Or, in another rust context, you could run the following:
 *
 * // Insert an item
 * r.db("test").table("test").insert(json!({ test: 1 })) // => run & unwrap
 *
 * // Give the first item a random number
 * r.db("test").table("test").nth(0).update(args!(
 *     { test: r.random(0, 100) },
 *     { nonAtomic: true }
 * ))  // => run & unwrap
 *
 * // Remove the first item
 * r.db("test").table("test").nth(0).delete() // => run & unwrap
 *
 */

#[derive(Debug, Serialize, Deserialize)]
struct TestItem {
    test: i32,
    id: String,
}

fn main()
{
    // Create a new ReQL client
    let r = Client::new();

    // Create an even loop
    let core = Core::new().unwrap();

    // Create a connection pool
    let conn = r.connect(&core.handle()).unwrap();

    // Run the query
    let query =
        r.db("test")
        .table("test")
        .filter(args!(|doc| {

            // Filter only documents which match our current TestItem trait
            doc.has_fields("test").and(doc.get_field("test").type_of().eq("NUMBER"))
        }))
        .changes()

    // We want rethinkdb to inform us of the change type
        .with_args(args!({
            include_types: true
        }))
        .run::<Change<TestItem, TestItem>>(conn)
        .unwrap();

    // Process the results
    let stati = query.and_then(|change| {
        match change {
            // The server returned the response we were expecting,
            // and deserialized the data into our Change structure
            Some(Document::Expected(change)) => {

                // Match our result_type vs rethinkdb's possible types
                match &change.result_type {

                    // We've got a String change-type
                    &Some(ref action) => {

                        // Extract the change type
                        print!("{:?} action received\n\t=> ", action);

                        match action.as_ref() {
                            "add" => println!("{:?}", change.new_val),
                            "remove" => println!("{:?}", change.old_val),
                            "change" => println!("from {:?} to {:?}", change.old_val, change.new_val),

                            _ => println!("{:?}", change)
                        }
                    },
                    &None => println!("Invalid change type!")
                };
            }

            // We got a response alright, but it wasn't the one we were
            // expecting plus it's not an error either, otherwise it would
            // have been returned as such (This simply means that the response
            // we got couldn't be serialised into the type we were expecting)
            Some(Document::Unexpected(change)) => {
                println!("Got unexpected change: {}",change)
            }
            // This is impossible in this particular example since there
            // needs to be at least one server available to give this
            // response otherwise we would have run into an error for
            // failing to connect
            None => {
                println!("got no documents in the database");
            }
        }
        Ok(())
    })
    // Our query ran into an error
        .or_else(|error| {
            println!("{:?}", error);
            Err(())
        });

    // Wait for all the results to be processed
    for _ in stati.wait() {}
}
<commit_msg>Cleaned up<commit_after>extern crate futures;
extern crate tokio_core;

#[macro_use]
extern crate reql;
extern crate reql_types;

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use reql_types::Change;
use futures::stream::Stream;
use tokio_core::reactor::Core;
use reql::{Client, Document, Run};

/**
 * rethinkdb changelog example
 * After running, access your admin panel at localhost:8080
 *
 * setup a "test" database, with a "test" table, and run:
 *
 * // Insert an item
 * r.db('test').table('test').insert({ test: 1 });
 *
 * // Give the first item a random number
 * r.db('test').table('test').nth(0).update({ test: r.random(0, 100) }, { nonAtomic: true });
 *
 * // Remove the first item
 * r.db('test').table('test').nth(0).delete();
 */

/**
 * Or, in another rust context, you could run the following:
 *
 * // Insert an item
 * r.db("test").table("test").insert(json!({ test: 1 })) // => run & unwrap
 *
 * // Give the first item a random number
 * r.db("test").table("test").nth(0).update(args!(
 *     { test: r.random(0, 100) },
 *     { nonAtomic: true }
 * ))  // => run & unwrap
 *
 * // Remove the first item
 * r.db("test").table("test").nth(0).delete() // => run & unwrap
 *
 */

#[derive(Debug, Serialize, Deserialize)]
struct TestItem {
    test: i32,
    id: String,
}

fn main()
{
    // Create a new ReQL client
    let r = Client::new();

    // Create an even loop
    let core = Core::new().unwrap();

    // Create a connection pool
    let conn = r.connect(&core.handle()).unwrap();

    // Run the query
    let query =
        r.db("test")
        .table("test")
        .filter(args!(|doc| {

            // Filter only documents which match our current TestItem trait
            doc.has_fields("test").and(doc.get_field("test").type_of().eq("NUMBER"))
        }))
        .changes()

    // We want rethinkdb to inform us of the change type
        .with_args(args!({
            include_types: true
        }))
        .run::<Change<TestItem, TestItem>>(conn)
        .unwrap();

    // Process the results
    let stati = query.and_then(|change| {
        match change {
            // The server returned the response we were expecting,
            // and deserialized the data into our Change structure
            Some(Document::Expected(change)) => {

                // Valid String change type
                if let Some(action) = change.result_type {

                    // Extract the change type
                    print!("{:?} action received\n\t=> ", action);

                    // Match the change type
                    match action.as_str() {
                        "add" => println!("{:?}", change.new_val),
                        "remove" => println!("{:?}", change.old_val),
                        "change" => println!("from {:?} to {:?}", change.old_val, change.new_val),

                        _ => println!("Unsupported change type: {:?}", action)
                    }
                } else {
                    println!("Invalid change type");
                }
            }

            // We got a response alright, but it wasn't the one we were
            // expecting plus it's not an error either, otherwise it would
            // have been returned as such (This simply means that the response
            // we got couldn't be serialised into the type we were expecting)
            Some(Document::Unexpected(change)) => {
                println!("Got unexpected change: {}",change)
            }
            // This is impossible in this particular example since there
            // needs to be at least one server available to give this
            // response otherwise we would have run into an error for
            // failing to connect
            None => {
                println!("got no documents in the database");
            }
        }
        Ok(())
    })
    // Our query ran into an error
        .or_else(|error| {
            println!("{:?}", error);
            Err(())
        });

    // Wait for all the results to be processed
    for _ in stati.wait() {}
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate diesel;
extern crate dotenv;
extern crate futures;
extern crate hyper;
#[macro_use]
extern crate lazy_static;
extern crate r2d2;
extern crate rand;
extern crate reqwest;
extern crate serde_json;
extern crate server;
extern crate tokio_core;
mod common;

use dotenv::dotenv;
use futures::{oneshot, Future, Stream};
use hyper::server::Http;
use serde_json::Value;
use reqwest::header::{qitem, AcceptLanguage, LanguageTag};
use reqwest::{Client, Response};
use server::server::AdServer;
use std::{env, thread};
use std::default::Default;
use std::sync::Mutex;
use tokio_core::reactor::Core;
use std::sync::mpsc::channel;

lazy_static! {
    static ref LOCK: Mutex<()> = Mutex::new(());
}

fn http_test<T>(url: &str, test: T)
where
    T: Fn(Response),
{
    let _locked = LOCK.lock().unwrap();
    let conn = common::connect();
    dotenv().ok();
    common::seed(&conn);
    common::seed_political(&conn);
    let (tx, rx) = oneshot();
    let (start_tx, start_rx) = channel();
    // Start server
    thread::spawn(move || {
        let mut core = Core::new().unwrap();
        let handle = core.handle();
        let addr = "127.0.0.1:0".parse().unwrap();
        let url = env::var("TEST_DATABASE_URL").unwrap();
        let server_handle = handle.clone();
        let server = Http::new()
            .serve_addr_handle(&addr, &server_handle, || {
                Ok(AdServer::new(handle.clone(), url.clone()))
            })
            .unwrap();

        let h2 = handle.clone();
        let server_addr = server.incoming_ref().local_addr();
        let srv = server
            .for_each(move |conn| {
                h2.spawn(conn.map(|_| ()).map_err(|_| ()));
                Ok(())
            })
            .map_err(|_| ());
        start_tx.send(server_addr).unwrap();
        // signaled when the test is over, and the other pair is dropped
        let _ = core.run(rx.then(|_| Ok(())).select(srv));
    });
    // wait until it starts
    let local = start_rx.recv().unwrap();
    let body = Client::new()
        .get(&format!("http://{}{}", local, url))
        .header(AcceptLanguage(vec![
            qitem(LanguageTag {
                language: Some("en".to_owned()),
                region: Some("US".to_owned()),
                ..Default::default()
            }),
        ]))
        .send()
        .unwrap();
    test(body);
    tx.send(true).unwrap();
    common::unseed(&conn);
}

fn ads(mut response: Response) {
    let json: Result<Value, reqwest::Error> = response.json();
    assert!(json.unwrap()["ads"].as_array().unwrap().len() > 0);
}

#[test]
fn test_ads_url() {
    http_test("/facebook-ads/ads", ads);
    http_test("/facebook-ads/ads/", ads);
}

#[test]
fn test_individual_ad_url() {
    http_test("/facebook-ads/ads/1", |mut resp| {
        let json: Result<Value, reqwest::Error> = resp.json();
        assert_eq!(json.unwrap()["id"].as_str().unwrap(), "1");
    });
}

fn admin(mut response: Response) {
    let text = response.text().unwrap();
    assert!(text.contains("<title>Admin: Facebook Political Ad Collector</title>"));
}

// ensuring we return the right HTML page for React to do its thing.
#[test]
fn test_admin_url() {
    http_test("/facebook-ads/admin", admin);
    http_test("/facebook-ads/admin/", admin);
}

fn index(mut response: Response) {
    let text = response.text().unwrap();
    assert!(text.contains("<title>Facebook Political Ad Collector</title>"));
}

#[test]
fn test_index_url() {
    http_test("/facebook-ads", index);
    http_test("/facebook-ads/", index);
    http_test("/facebook-ads/ad/1", index);
}
<commit_msg>cleanup<commit_after>extern crate chrono;
extern crate diesel;
extern crate dotenv;
extern crate futures;
extern crate hyper;
#[macro_use]
extern crate lazy_static;
extern crate r2d2;
extern crate rand;
extern crate reqwest;
extern crate serde_json;
extern crate server;
extern crate tokio_core;
mod common;

use dotenv::dotenv;
use futures::{oneshot, Future, Stream};
use hyper::server::Http;
use serde_json::Value;
use reqwest::header::{qitem, AcceptLanguage, LanguageTag};
use reqwest::{Client, Response};
use server::server::AdServer;
use std::{env, thread};
use std::default::Default;
use std::sync::Mutex;
use tokio_core::reactor::Core;
use std::sync::mpsc::channel;

lazy_static! {
    static ref LOCK: Mutex<()> = Mutex::new(());
}

fn http_test<T>(url: &str, test: T)
where
    T: Fn(Response),
{
    let _locked = LOCK.lock().unwrap();
    let conn = common::connect();
    dotenv().ok();
    common::seed(&conn);
    common::seed_political(&conn);
    let (tx, rx) = oneshot();
    let (start_tx, start_rx) = channel();
    thread::spawn(move || {
        let mut core = Core::new().unwrap();
        let handle = core.handle();
        let addr = "127.0.0.1:0".parse().unwrap();
        let url = env::var("TEST_DATABASE_URL").unwrap();
        let server_handle = handle.clone();
        let server = Http::new()
            .serve_addr_handle(&addr, &server_handle, || {
                Ok(AdServer::new(handle.clone(), url.clone()))
            })
            .unwrap();
        let h2 = handle.clone();
        let server_addr = server.incoming_ref().local_addr();
        let srv = server
            .for_each(move |conn| {
                h2.spawn(conn.map(|_| ()).map_err(|_| ()));
                Ok(())
            })
            .map_err(|_| ());
        start_tx.send(server_addr).unwrap();
        let _ = core.run(rx.then(|_| Ok(())).select(srv));
    });
    let local = start_rx.recv().unwrap();
    let body = Client::new()
        .get(&format!("http://{}{}", local, url))
        .header(AcceptLanguage(vec![
            qitem(LanguageTag {
                language: Some("en".to_owned()),
                region: Some("US".to_owned()),
                ..Default::default()
            }),
        ]))
        .send()
        .unwrap();
    test(body);
    tx.send(true).unwrap();
    common::unseed(&conn);
}

fn ads(mut response: Response) {
    let json: Result<Value, reqwest::Error> = response.json();
    assert!(json.unwrap()["ads"].as_array().unwrap().len() > 0);
}

#[test]
fn test_ads_url() {
    http_test("/facebook-ads/ads", ads);
    http_test("/facebook-ads/ads/", ads);
}

#[test]
fn test_individual_ad_url() {
    http_test("/facebook-ads/ads/1", |mut resp| {
        let json: Result<Value, reqwest::Error> = resp.json();
        assert_eq!(json.unwrap()["id"].as_str().unwrap(), "1");
    });
}

fn admin(mut response: Response) {
    let text = response.text().unwrap();
    assert!(text.contains("<title>Admin: Facebook Political Ad Collector</title>"));
}

#[test]
fn test_admin_url() {
    http_test("/facebook-ads/admin", admin);
    http_test("/facebook-ads/admin/", admin);
}

fn index(mut response: Response) {
    let text = response.text().unwrap();
    assert!(text.contains("<title>Facebook Political Ad Collector</title>"));
}

#[test]
fn test_index_url() {
    http_test("/facebook-ads", index);
    http_test("/facebook-ads/", index);
    http_test("/facebook-ads/ad/1", index);
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
//    https://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 autocxx_parser::IncludeCpp;
use proc_macro2::{Ident, Span};
use proc_macro_error::{abort, proc_macro_error};
use quote::quote;
use syn::parse::{Parse, ParseStream, Parser};
use syn::{parse_macro_input, Fields, ItemStruct, Result as ParseResult};

struct SelfOwned(bool);

impl Parse for SelfOwned {
    fn parse(input: ParseStream) -> ParseResult<Self> {
        // TODO make this less liberal
        let id = input.parse::<Option<Ident>>()?;
        match id {
            Some(id) if id == "self_owned" => Ok(Self(true)),
            _ => Ok(Self(false)),
        }
    }
}

/// Implementation of the `include_cpp` macro. See documentation for `autocxx` crate.
#[proc_macro_error]
#[proc_macro]
pub fn include_cpp_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let include_cpp = parse_macro_input!(input as IncludeCpp);
    proc_macro::TokenStream::from(include_cpp.generate_rs())
}

/// Attribute to state that a Rust `struct` is a C++ subclass.
/// This adds an additional field to the struct which autocxx uses to
/// track a C++ instantiation of this Rust subclass.
#[proc_macro_error]
#[proc_macro_attribute]
pub fn is_subclass(
    attr: proc_macro::TokenStream,
    item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let mut s: ItemStruct =
        syn::parse(item).unwrap_or_else(|_| abort!(Span::call_site(), "Expected a struct"));
    let id = &s.ident;
    let cpp_ident = Ident::new(&format!("{}Cpp", id.to_string()), Span::call_site());
    match &mut s.fields {
        Fields::Named(fields) => {
            let input = quote! {
                cpp_peer: autocxx::subclass::CppSubclassCppPeerHolder<ffi:: #cpp_ident>
            };
            let parser = syn::Field::parse_named;
            let f = parser.parse2(input).unwrap();
            fields.named.push(f);
        }
        _ => abort!(Span::call_site(), "Expect a struct with named fields"),
    }
    let self_owned: SelfOwned = syn::parse(attr)
        .unwrap_or_else(|_| abort!(Span::call_site(), "Unable to parse attributes"));
    let self_owned_bit = if self_owned.0 {
        Some(quote! {
            impl autocxx::subclass::CppSubclassSelfOwned<ffi::#cpp_ident> for #id {}
        })
    } else {
        None
    };
    let toks = quote! {
        #s

        impl autocxx::subclass::CppSubclass<ffi::#cpp_ident> for #id {
            fn peer_holder_mut(&mut self) -> &mut autocxx::subclass::CppSubclassCppPeerHolder<ffi::#cpp_ident> {
                &mut self.cpp_peer
            }
            fn peer_holder(&self) -> &autocxx::subclass::CppSubclassCppPeerHolder<ffi::#cpp_ident> {
                &self.cpp_peer
            }
        }

        #self_owned_bit
    };
    toks.into()
}
<commit_msg>Fix overly liberal subclass parsing.<commit_after>// Copyright 2020 Google LLC
//
// 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
//
//    https://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 autocxx_parser::IncludeCpp;
use proc_macro2::{Ident, Span};
use proc_macro_error::{abort, proc_macro_error};
use quote::{quote, ToTokens};
use syn::parse::{Parse, ParseStream, Parser};
use syn::{parse_macro_input, Fields, ItemStruct, Result as ParseResult};

struct SelfOwned(bool);

impl Parse for SelfOwned {
    fn parse(input: ParseStream) -> ParseResult<Self> {
        let id = input.parse::<Option<Ident>>()?;
        match id {
            Some(id) if id == "self_owned" => Ok(Self(true)),
            Some(id) => Err(syn::Error::new_spanned(
                id.into_token_stream(),
                "Expected self_owned",
            )),
            None => Ok(Self(false)),
        }
    }
}

/// Implementation of the `include_cpp` macro. See documentation for `autocxx` crate.
#[proc_macro_error]
#[proc_macro]
pub fn include_cpp_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let include_cpp = parse_macro_input!(input as IncludeCpp);
    proc_macro::TokenStream::from(include_cpp.generate_rs())
}

/// Attribute to state that a Rust `struct` is a C++ subclass.
/// This adds an additional field to the struct which autocxx uses to
/// track a C++ instantiation of this Rust subclass.
#[proc_macro_error]
#[proc_macro_attribute]
pub fn is_subclass(
    attr: proc_macro::TokenStream,
    item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let mut s: ItemStruct =
        syn::parse(item).unwrap_or_else(|_| abort!(Span::call_site(), "Expected a struct"));
    let id = &s.ident;
    let cpp_ident = Ident::new(&format!("{}Cpp", id.to_string()), Span::call_site());
    match &mut s.fields {
        Fields::Named(fields) => {
            let input = quote! {
                cpp_peer: autocxx::subclass::CppSubclassCppPeerHolder<ffi:: #cpp_ident>
            };
            let parser = syn::Field::parse_named;
            let f = parser.parse2(input).unwrap();
            fields.named.push(f);
        }
        _ => abort!(Span::call_site(), "Expect a struct with named fields"),
    }
    let self_owned: SelfOwned = syn::parse(attr)
        .unwrap_or_else(|_| abort!(Span::call_site(), "Unable to parse attributes"));
    let self_owned_bit = if self_owned.0 {
        Some(quote! {
            impl autocxx::subclass::CppSubclassSelfOwned<ffi::#cpp_ident> for #id {}
        })
    } else {
        None
    };
    let toks = quote! {
        #s

        impl autocxx::subclass::CppSubclass<ffi::#cpp_ident> for #id {
            fn peer_holder_mut(&mut self) -> &mut autocxx::subclass::CppSubclassCppPeerHolder<ffi::#cpp_ident> {
                &mut self.cpp_peer
            }
            fn peer_holder(&self) -> &autocxx::subclass::CppSubclassCppPeerHolder<ffi::#cpp_ident> {
                &self.cpp_peer
            }
        }

        #self_owned_bit
    };
    toks.into()
}
<|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.

macro_rules! Tuple {
    { $A:ty,$B:ty } => { ($A, $B) }
}

fn main() {
    let x: Tuple!(i32, i32) = (1, 2);
}
<commit_msg>Add regression test.<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.

macro_rules! Tuple {
    { $A:ty,$B:ty } => { ($A, $B) }
}

fn main() {
    let x: Tuple!(i32, i32) = (1, 2);
}

fn issue_36540() {
    let i32 = 0;
    macro_rules! m { () => { i32 } }
    struct S<T = m!()>(m!(), T) where T: Trait<m!()>;

    let x: m!() = m!();
    std::cell::Cell::<m!()>::new(m!());
    impl<T = m!()> std::ops::Index<m!()> for Trait<(m!(), T)>
        where T: Trait<m!()>
    {
        type Output = m!();
        fn index(&self, i: m!()) -> &m!() {
            unimplemented!()
        }
    }
}

trait Trait<T> {}
<|endoftext|>


<commit_before>//! Auto-generate stub docs for the unstable book

#![deny(rust_2018_idioms)]
#![deny(warnings)]

use tidy::features::{Feature, Features, collect_lib_features, collect_lang_features};
use tidy::unstable_book::{collect_unstable_feature_names, collect_unstable_book_section_file_names,
                          PATH_STR, LANG_FEATURES_DIR, LIB_FEATURES_DIR};
use std::collections::BTreeSet;
use std::io::Write;
use std::fs::{self, File};
use std::env;
use std::path::Path;

/// A helper macro to `unwrap` a result except also print out details like:
///
/// * The file/line of the panic
/// * The expression that failed
/// * The error itself
macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn generate_stub_issue(path: &Path, name: &str, issue: u32) {
    let mut file = t!(File::create(path));
    t!(file.write_fmt(format_args!(include_str!("stub-issue.md"),
                                   name = name,
                                   issue = issue)));
}

fn generate_stub_no_issue(path: &Path, name: &str) {
    let mut file = t!(File::create(path));
    t!(file.write_fmt(format_args!(include_str!("stub-no-issue.md"),
                                   name = name)));
}

fn set_to_summary_str(set: &BTreeSet<String>, dir: &str
) -> String {
    set
        .iter()
        .map(|ref n| format!("    - [{}]({}/{}.md)",
                                      n.replace('-', "_"),
                                      dir,
                                      n))
        .fold("".to_owned(), |s, a| s + &a + "\n")
}

fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Features) {
    let compiler_flags = collect_unstable_book_section_file_names(
        &path.join("compiler-flags"));

    let compiler_flags_str = set_to_summary_str(&compiler_flags,
                                                "compiler-flags");

    let unstable_lang_features = collect_unstable_feature_names(&lang_features);
    let unstable_lib_features = collect_unstable_feature_names(&lib_features);

    let lang_features_str = set_to_summary_str(&unstable_lang_features,
                                               LANG_FEATURES_DIR);
    let lib_features_str = set_to_summary_str(&unstable_lib_features,
                                              LIB_FEATURES_DIR);

    let mut file = t!(File::create(&path.join("SUMMARY.md")));
    t!(file.write_fmt(format_args!(include_str!("SUMMARY.md"),
                                   compiler_flags = compiler_flags_str,
                                   language_features = lang_features_str,
                                   library_features = lib_features_str)));

}

fn has_valid_tracking_issue(f: &Feature) -> bool {
    if let Some(n) = f.tracking_issue {
        if n > 0 {
            return true;
        }
    }
    false
}

fn generate_unstable_book_files(src :&Path, out: &Path, features :&Features) {
    let unstable_features = collect_unstable_feature_names(features);
    let unstable_section_file_names = collect_unstable_book_section_file_names(src);
    t!(fs::create_dir_all(&out));
    for feature_name in &unstable_features - &unstable_section_file_names {
        let feature_name_underscore = feature_name.replace('-', "_");
        let file_name = format!("{}.md", feature_name);
        let out_file_path = out.join(&file_name);
        let feature = &features[&feature_name_underscore];

        if has_valid_tracking_issue(&feature) {
            generate_stub_issue(&out_file_path,
                                &feature_name_underscore,
                                feature.tracking_issue.unwrap());
        } else {
            generate_stub_no_issue(&out_file_path, &feature_name_underscore);
        }
    }
}

fn copy_recursive(path: &Path, to: &Path) {
    for entry in t!(fs::read_dir(path)) {
        let e = t!(entry);
        let t = t!(e.metadata());
        let dest = &to.join(e.file_name());
        if t.is_file() {
            t!(fs::copy(&e.path(), dest));
        } else if t.is_dir() {
            t!(fs::create_dir_all(dest));
            copy_recursive(&e.path(), dest);
        }
    }
}

fn copy_book_toml(path: &Path) {
    let mut file = t!(File::create(&path.join("book.toml")));
    t!(file.write_fmt(format_args!(include_str!("book.toml"));
}

fn main() {
    let src_path_str = env::args_os().skip(1).next().expect("source path required");
    let dest_path_str = env::args_os().skip(2).next().expect("destination path required");
    let src_path = Path::new(&src_path_str);
    let dest_path = Path::new(&dest_path_str).join("src");

    let lang_features = collect_lang_features(src_path, &mut false);
    let lib_features = collect_lib_features(src_path).into_iter().filter(|&(ref name, _)| {
        !lang_features.contains_key(name)
    }).collect();

    let doc_src_path = src_path.join(PATH_STR);

    t!(fs::create_dir_all(&dest_path));

    generate_unstable_book_files(&doc_src_path.join(LANG_FEATURES_DIR),
                                 &dest_path.join(LANG_FEATURES_DIR),
                                 &lang_features);
    generate_unstable_book_files(&doc_src_path.join(LIB_FEATURES_DIR),
                                 &dest_path.join(LIB_FEATURES_DIR),
                                 &lib_features);

    copy_recursive(&doc_src_path, &dest_path);

    generate_summary(&dest_path, &lang_features, &lib_features);

    copy_book_toml(&dest_path);
}
<commit_msg>Remove copy_book_toml method in favor for copy_recursive<commit_after>//! Auto-generate stub docs for the unstable book

#![deny(rust_2018_idioms)]
#![deny(warnings)]

use tidy::features::{Feature, Features, collect_lib_features, collect_lang_features};
use tidy::unstable_book::{collect_unstable_feature_names, collect_unstable_book_section_file_names,
                          PATH_STR, LANG_FEATURES_DIR, LIB_FEATURES_DIR};
use std::collections::BTreeSet;
use std::io::Write;
use std::fs::{self, File};
use std::env;
use std::path::Path;

/// A helper macro to `unwrap` a result except also print out details like:
///
/// * The file/line of the panic
/// * The expression that failed
/// * The error itself
macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn generate_stub_issue(path: &Path, name: &str, issue: u32) {
    let mut file = t!(File::create(path));
    t!(file.write_fmt(format_args!(include_str!("stub-issue.md"),
                                   name = name,
                                   issue = issue)));
}

fn generate_stub_no_issue(path: &Path, name: &str) {
    let mut file = t!(File::create(path));
    t!(file.write_fmt(format_args!(include_str!("stub-no-issue.md"),
                                   name = name)));
}

fn set_to_summary_str(set: &BTreeSet<String>, dir: &str
) -> String {
    set
        .iter()
        .map(|ref n| format!("    - [{}]({}/{}.md)",
                                      n.replace('-', "_"),
                                      dir,
                                      n))
        .fold("".to_owned(), |s, a| s + &a + "\n")
}

fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Features) {
    let compiler_flags = collect_unstable_book_section_file_names(
        &path.join("compiler-flags"));

    let compiler_flags_str = set_to_summary_str(&compiler_flags,
                                                "compiler-flags");

    let unstable_lang_features = collect_unstable_feature_names(&lang_features);
    let unstable_lib_features = collect_unstable_feature_names(&lib_features);

    let lang_features_str = set_to_summary_str(&unstable_lang_features,
                                               LANG_FEATURES_DIR);
    let lib_features_str = set_to_summary_str(&unstable_lib_features,
                                              LIB_FEATURES_DIR);

    let mut file = t!(File::create(&path.join("SUMMARY.md")));
    t!(file.write_fmt(format_args!(include_str!("SUMMARY.md"),
                                   compiler_flags = compiler_flags_str,
                                   language_features = lang_features_str,
                                   library_features = lib_features_str)));

}

fn has_valid_tracking_issue(f: &Feature) -> bool {
    if let Some(n) = f.tracking_issue {
        if n > 0 {
            return true;
        }
    }
    false
}

fn generate_unstable_book_files(src :&Path, out: &Path, features :&Features) {
    let unstable_features = collect_unstable_feature_names(features);
    let unstable_section_file_names = collect_unstable_book_section_file_names(src);
    t!(fs::create_dir_all(&out));
    for feature_name in &unstable_features - &unstable_section_file_names {
        let feature_name_underscore = feature_name.replace('-', "_");
        let file_name = format!("{}.md", feature_name);
        let out_file_path = out.join(&file_name);
        let feature = &features[&feature_name_underscore];

        if has_valid_tracking_issue(&feature) {
            generate_stub_issue(&out_file_path,
                                &feature_name_underscore,
                                feature.tracking_issue.unwrap());
        } else {
            generate_stub_no_issue(&out_file_path, &feature_name_underscore);
        }
    }
}

fn copy_recursive(path: &Path, to: &Path) {
    for entry in t!(fs::read_dir(path)) {
        let e = t!(entry);
        let t = t!(e.metadata());
        let dest = &to.join(e.file_name());
        if t.is_file() {
            t!(fs::copy(&e.path(), dest));
        } else if t.is_dir() {
            t!(fs::create_dir_all(dest));
            copy_recursive(&e.path(), dest);
        }
    }
}

fn main() {
    let src_path_str = env::args_os().skip(1).next().expect("source path required");
    let dest_path_str = env::args_os().skip(2).next().expect("destination path required");
    let src_path = Path::new(&src_path_str);
    let dest_path = Path::new(&dest_path_str).join("src");

    let lang_features = collect_lang_features(src_path, &mut false);
    let lib_features = collect_lib_features(src_path).into_iter().filter(|&(ref name, _)| {
        !lang_features.contains_key(name)
    }).collect();

    let doc_src_path = src_path.join(PATH_STR);

    t!(fs::create_dir_all(&dest_path));

    generate_unstable_book_files(&doc_src_path.join(LANG_FEATURES_DIR),
                                 &dest_path.join(LANG_FEATURES_DIR),
                                 &lang_features);
    generate_unstable_book_files(&doc_src_path.join(LIB_FEATURES_DIR),
                                 &dest_path.join(LIB_FEATURES_DIR),
                                 &lib_features);

    copy_recursive(&doc_src_path, &dest_path);

    generate_summary(&dest_path, &lang_features, &lib_features);
}
<|endoftext|>


<commit_before>use super::util;
use crate::error::Result;
use crate::loader::Loader;
use ansi_term::Color;
use lazy_static::lazy_static;
use serde::ser::SerializeMap;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_json::{json, Value};
use std::collections::HashMap;
use std::sync::atomic::AtomicUsize;
use std::time::Instant;
use std::{fs, io, path, str, usize};
use tree_sitter_highlight::{HighlightConfiguration, HighlightEvent, Highlighter, HtmlRenderer};

pub const HTML_HEADER: &'static str = "
<!doctype HTML>

  <title>Tree-sitter Highlighting</title>

";

pub const HTML_FOOTER: &'static str = "

";

lazy_static! {
    static ref CSS_STYLES_BY_COLOR_ID: Vec<String> =
        serde_json::from_str(include_str!("../vendor/xterm-colors.json")).unwrap();
}

#[derive(Debug, Default)]
pub struct Style {
    pub ansi: ansi_term::Style,
    pub css: Option<String>,
}

#[derive(Debug)]
pub struct Theme {
    pub styles: Vec

";

pub const HTML_FOOTER: &'static str = "

";

lazy_static! {
    static ref CSS_STYLES_BY_COLOR_ID: Vec<String> =
        serde_json::from_str(include_str!("../vendor/xterm-colors.json")).unwrap();
}

#[derive(Debug, Default)]
pub struct Style {
    pub ansi: ansi_term::Style,
    pub css: Option<String>,
}

#[derive(Debug)]
pub struct Theme {
    pub styles: Vec


<commit_before>
extern mod sax;

use self::sax::*;

pub struct Registry {
    enum_nss: ~[EnumNs],
    cmd_nss: ~[CmdNs],
}

impl Registry {
    pub fn from_xml(data: &str) -> Registry {
        RegistryBuilder::parse(data)
    }
}

pub struct EnumNs {
    namespace: ~str,
    group: Option<~str>,
    ty: Option<~str>,
    start: Option<~str>,
    end: Option<~str>,
    vendor: Option<~str>,
    comment: Option<~str>,
    enums: ~[Enum],
}

pub struct Enum {
    ident: ~str,
    value: ~str,
    alias: Option<~str>,
}

pub struct CmdNs {
    namespace: ~str,
    cmds: ~[Cmd],
}

pub struct Binding {
    ident: ~str,
    ty: ~str,
    group: Option<~str>,
}

pub struct Cmd {
    proto: Binding,
    params: ~[Binding],
    alias: Option<~str>,
    vecequiv: Option<~str>,
    glx: Option<GlxOpcode>,
}

pub struct GlxOpcode {
    ty: ~str,
    opcode: ~str,
    name: Option<~str>,
    comment: Option<~str>,
}

struct RegistryBuilder {
    priv port: SaxPort,
}

impl<'self> RegistryBuilder {
    fn parse(data: &str) -> Registry {
        RegistryBuilder {
            port: parse_xml(data)
        }.consume_registry()
    }

    fn recv(&self) -> ParseEvent {
        loop {
            match self.port.recv() {
                Ok(StartDocument) => (),
                Ok(Comment(_)) => (),
                Ok(Characters(ref ch)) if ch.is_whitespace() => (),
                Ok(EndDocument) => fail!("The end of the document has been reached"),
                Ok(event) => return event,
                Err(err) => fail!("XML error: %s", err.to_str()),
            }
        }
    }

    fn expect_characters(&self) -> ~str {
        match self.recv() {
            Characters(ref ch) => ch.clone(),
            msg => fail!("Expected characters, found: %s", msg.to_str()),
        }
    }

    fn expect_start_element(&self, name: &str) -> Attributes {
        match self.recv() {
            StartElement(ref n, ref atts) if name == *n => atts.clone(),
            msg => fail!("Expected <%s>, found: %s", name, msg.to_str()),
        }
    }

    fn expect_end_element(&self, name: &str) {
        match self.recv() {
            EndElement(ref n) if name == *n => (),
            msg => fail!("Expected </%s>, found: %s", name, msg.to_str()),
        }
    }

    fn skip_until(&self, event: ParseEvent) {
        loop {
            let msg = self.recv();
            if msg == event || msg == EndDocument { break }
        }
    }

    fn consume_registry(&self) -> Registry {
        self.expect_start_element("registry");
        let mut registry = Registry { enum_nss: ~[], cmd_nss: ~[] };
        loop {
            match self.recv() {
                // ignores
                Characters(_) | Comment(_) => (),
                StartElement(~"comment", _) => self.skip_until(EndElement(~"comment")),
                StartElement(~"types", _) => self.skip_until(EndElement(~"types")),
                StartElement(~"groups", _) => self.skip_until(EndElement(~"groups")),
                StartElement(~"feature", _) => self.skip_until(EndElement(~"feature")),
                StartElement(~"extensions", _) => self.skip_until(EndElement(~"extensions")),

                // add enum namespace
                StartElement(~"enums", ref atts) => {
                    registry.enum_nss.push(
                        EnumNs {
                            namespace:  atts.get_clone("namespace"),
                            group:      atts.find_clone("group"),
                            ty:         atts.find_clone("type"),
                            start:      atts.find_clone("start"),
                            end:        atts.find_clone("end"),
                            vendor:     atts.find_clone("vendor"),
                            comment:    atts.find_clone("comment"),
                            enums:      self.consume_enums(),
                        }
                    )
                }

                // add command namespace
                StartElement(~"commands", ref atts) => {
                    registry.cmd_nss.push(
                        CmdNs {
                            namespace:  atts.get_clone("namespace"),
                            cmds:       self.consume_cmds(),
                        }
                    );
                }

                // finished building the registry
                EndElement(~"registry") => break,

                // error handling
                msg => fail!("Expected </registry>, found: %s", msg.to_str()),
            }
        }
        registry
    }

    fn consume_enums(&self) -> ~[Enum] {
        let mut enums = ~[];
        loop {
            match self.recv() {
                // ignores
                Characters(_) | Comment(_) => (),
                StartElement(~"unused", _) => self.skip_until(EndElement(~"unused")),

                // add enum definition
                StartElement(~"enum", ref atts) => {
                    enums.push(
                        Enum {
                            ident:  atts.get_clone("name"),
                            value:  atts.get_clone("value"),
                            alias:  atts.find_clone("alias"),
                        }
                    );
                    self.expect_end_element("enum");
                }

                // finished building the namespace
                EndElement(~"enums") => break,
                // error handling
                msg => fail!("Expected </enums>, found: %s", msg.to_str()),
            }
        }
        enums
    }

    fn consume_cmds(&self) -> ~[Cmd] {
        let mut cmds = ~[];
        loop {
            match self.recv() {
                // add command definition
                StartElement(~"command", _) => {
                    cmds.push(self.consume_cmd());
                }
                // finished building the namespace
                EndElement(~"commands") => break,
                // error handling
                msg => fail!("Expected </commands>, found: %s", msg.to_str()),
            }
        }
        cmds
    }

    fn consume_cmd(&self) -> Cmd {
        // consume command prototype
        let proto_atts = self.expect_start_element("proto");
        let proto = self.consume_binding(proto_atts.find_clone("group"));
        self.expect_end_element("proto");

        let mut params = ~[];
        let mut alias = None;
        let mut vecequiv = None;
        let mut glx = None;
        loop {
            match self.recv() {
                StartElement(~"param", ref atts) => {
                    params.push(
                        self.consume_binding(atts.find_clone("group"))
                    );
                    self.expect_end_element("param");
                }
                StartElement(~"alias", ref atts) => {
                    alias = atts.find_clone("alias");
                    self.expect_end_element("alias");
                }
                StartElement(~"vecequiv", ref atts) => {
                    vecequiv = atts.find_clone("vecequiv");
                    self.expect_end_element("vecequiv");
                }
                StartElement(~"glx", ref atts) => {
                    glx = Some(GlxOpcode {
                        ty:      atts.get_clone("type"),
                        opcode:  atts.get_clone("opcode"),
                        name:    atts.find_clone("name"),
                        comment: atts.find_clone("comment"),
                    });
                    self.expect_end_element("glx");
                }
                EndElement(~"command") => break,
                msg => fail!("Expected </command>, found: %s", msg.to_str()),
            }
        }

        Cmd {
            proto: proto,
            params: params,
            alias: alias,
            vecequiv: vecequiv,
            glx: glx,
        }
    }

    fn consume_binding(&self, group: Option<~str>) -> Binding {
        // consume type
        let mut ty = ~"";
        loop {
            match self.recv() {
                Characters(ch) => ty.push_str(ch),
                StartElement(~"ptype", _) => (),
                EndElement(~"ptype") => (),
                StartElement(~"name", _) => break,
                msg => fail!("Expected binding, found: %s", msg.to_str()),
            }
        }
        // consume identifier
        let ident = self.expect_characters();
        self.expect_end_element("name");
        Binding {
            ident: ident,
            ty: ty,
            group: group,
        }
    }
}
<commit_msg>Rename some fields<commit_after>
extern mod sax;

use self::sax::*;

pub struct Registry {
    enums: ~[EnumNs],
    cmds: ~[CmdNs],
}

impl Registry {
    pub fn from_xml(data: &str) -> Registry {
        RegistryBuilder::parse(data)
    }
}

pub struct EnumNs {
    namespace: ~str,
    group: Option<~str>,
    ty: Option<~str>,
    start: Option<~str>,
    end: Option<~str>,
    vendor: Option<~str>,
    comment: Option<~str>,
    defs: ~[Enum],
}

pub struct Enum {
    ident: ~str,
    value: ~str,
    alias: Option<~str>,
}

pub struct CmdNs {
    namespace: ~str,
    defs: ~[Cmd],
}

pub struct Binding {
    ident: ~str,
    ty: ~str,
    group: Option<~str>,
}

pub struct Cmd {
    proto: Binding,
    params: ~[Binding],
    alias: Option<~str>,
    vecequiv: Option<~str>,
    glx: Option<GlxOpcode>,
}

pub struct GlxOpcode {
    ty: ~str,
    opcode: ~str,
    name: Option<~str>,
    comment: Option<~str>,
}

struct RegistryBuilder {
    priv port: SaxPort,
}

impl<'self> RegistryBuilder {
    fn parse(data: &str) -> Registry {
        RegistryBuilder {
            port: parse_xml(data)
        }.consume_registry()
    }

    fn recv(&self) -> ParseEvent {
        loop {
            match self.port.recv() {
                Ok(StartDocument) => (),
                Ok(Comment(_)) => (),
                Ok(Characters(ref ch)) if ch.is_whitespace() => (),
                Ok(EndDocument) => fail!("The end of the document has been reached"),
                Ok(event) => return event,
                Err(err) => fail!("XML error: %s", err.to_str()),
            }
        }
    }

    fn expect_characters(&self) -> ~str {
        match self.recv() {
            Characters(ref ch) => ch.clone(),
            msg => fail!("Expected characters, found: %s", msg.to_str()),
        }
    }

    fn expect_start_element(&self, name: &str) -> Attributes {
        match self.recv() {
            StartElement(ref n, ref atts) if name == *n => atts.clone(),
            msg => fail!("Expected <%s>, found: %s", name, msg.to_str()),
        }
    }

    fn expect_end_element(&self, name: &str) {
        match self.recv() {
            EndElement(ref n) if name == *n => (),
            msg => fail!("Expected </%s>, found: %s", name, msg.to_str()),
        }
    }

    fn skip_until(&self, event: ParseEvent) {
        loop {
            let msg = self.recv();
            if msg == event || msg == EndDocument { break }
        }
    }

    fn consume_registry(&self) -> Registry {
        self.expect_start_element("registry");
        let mut registry = Registry { enums: ~[], cmds: ~[] };
        loop {
            match self.recv() {
                // ignores
                Characters(_) | Comment(_) => (),
                StartElement(~"comment", _) => self.skip_until(EndElement(~"comment")),
                StartElement(~"types", _) => self.skip_until(EndElement(~"types")),
                StartElement(~"groups", _) => self.skip_until(EndElement(~"groups")),
                StartElement(~"feature", _) => self.skip_until(EndElement(~"feature")),
                StartElement(~"extensions", _) => self.skip_until(EndElement(~"extensions")),

                // add enum namespace
                StartElement(~"enums", ref atts) => {
                    registry.enums.push(
                        EnumNs {
                            namespace:  atts.get_clone("namespace"),
                            group:      atts.find_clone("group"),
                            ty:         atts.find_clone("type"),
                            start:      atts.find_clone("start"),
                            end:        atts.find_clone("end"),
                            vendor:     atts.find_clone("vendor"),
                            comment:    atts.find_clone("comment"),
                            defs:       self.consume_enums(),
                        }
                    )
                }

                // add command namespace
                StartElement(~"commands", ref atts) => {
                    registry.cmds.push(
                        CmdNs {
                            namespace:  atts.get_clone("namespace"),
                            defs:       self.consume_cmds(),
                        }
                    );
                }

                // finished building the registry
                EndElement(~"registry") => break,

                // error handling
                msg => fail!("Expected </registry>, found: %s", msg.to_str()),
            }
        }
        registry
    }

    fn consume_enums(&self) -> ~[Enum] {
        let mut enums = ~[];
        loop {
            match self.recv() {
                // ignores
                Characters(_) | Comment(_) => (),
                StartElement(~"unused", _) => self.skip_until(EndElement(~"unused")),

                // add enum definition
                StartElement(~"enum", ref atts) => {
                    enums.push(
                        Enum {
                            ident:  atts.get_clone("name"),
                            value:  atts.get_clone("value"),
                            alias:  atts.find_clone("alias"),
                        }
                    );
                    self.expect_end_element("enum");
                }

                // finished building the namespace
                EndElement(~"enums") => break,
                // error handling
                msg => fail!("Expected </enums>, found: %s", msg.to_str()),
            }
        }
        enums
    }

    fn consume_cmds(&self) -> ~[Cmd] {
        let mut cmds = ~[];
        loop {
            match self.recv() {
                // add command definition
                StartElement(~"command", _) => {
                    cmds.push(self.consume_cmd());
                }
                // finished building the namespace
                EndElement(~"commands") => break,
                // error handling
                msg => fail!("Expected </commands>, found: %s", msg.to_str()),
            }
        }
        cmds
    }

    fn consume_cmd(&self) -> Cmd {
        // consume command prototype
        let proto_atts = self.expect_start_element("proto");
        let proto = self.consume_binding(proto_atts.find_clone("group"));
        self.expect_end_element("proto");

        let mut params = ~[];
        let mut alias = None;
        let mut vecequiv = None;
        let mut glx = None;
        loop {
            match self.recv() {
                StartElement(~"param", ref atts) => {
                    params.push(
                        self.consume_binding(atts.find_clone("group"))
                    );
                    self.expect_end_element("param");
                }
                StartElement(~"alias", ref atts) => {
                    alias = atts.find_clone("alias");
                    self.expect_end_element("alias");
                }
                StartElement(~"vecequiv", ref atts) => {
                    vecequiv = atts.find_clone("vecequiv");
                    self.expect_end_element("vecequiv");
                }
                StartElement(~"glx", ref atts) => {
                    glx = Some(GlxOpcode {
                        ty:      atts.get_clone("type"),
                        opcode:  atts.get_clone("opcode"),
                        name:    atts.find_clone("name"),
                        comment: atts.find_clone("comment"),
                    });
                    self.expect_end_element("glx");
                }
                EndElement(~"command") => break,
                msg => fail!("Expected </command>, found: %s", msg.to_str()),
            }
        }

        Cmd {
            proto: proto,
            params: params,
            alias: alias,
            vecequiv: vecequiv,
            glx: glx,
        }
    }

    fn consume_binding(&self, group: Option<~str>) -> Binding {
        // consume type
        let mut ty = ~"";
        loop {
            match self.recv() {
                Characters(ch) => ty.push_str(ch),
                StartElement(~"ptype", _) => (),
                EndElement(~"ptype") => (),
                StartElement(~"name", _) => break,
                msg => fail!("Expected binding, found: %s", msg.to_str()),
            }
        }
        // consume identifier
        let ident = self.expect_characters();
        self.expect_end_element("name");
        Binding {
            ident: ident,
            ty: ty,
            group: group,
        }
    }
}
<|endoftext|>


<commit_before>//! This file defines system store APIs that operates data not part of the Libra core data
//! structures but information with regard to system running status, statistics, etc.

use crate::{
    ledger_counters::{LedgerCounterBumps, LedgerCounters},
    schema::ledger_counters::LedgerCountersSchema,
};
use failure::prelude::*;
use logger::prelude::*;
use schemadb::{SchemaBatch, DB};
use std::sync::Arc;
use types::transaction::Version;

pub(crate) struct SystemStore {
    db: Arc<DB>,
}

impl SystemStore {
    pub fn new(db: Arc<DB>) -> Self {
        Self { db }
    }

    /// Increase ledger counters.
    ///
    /// The base values are read out of db, to which the `diff` is combined to, and the result is
    /// stored to the db, keyed by `last_version`.
    #[allow(dead_code)]
    pub fn bump_ledger_counters(
        &self,
        first_version: Version,
        last_version: Version,
        bumps: LedgerCounterBumps,
        batch: &mut SchemaBatch,
    ) -> Result<LedgerCounters> {
        assert!(first_version <= last_version);

        let mut counters = if first_version > 0 {
            let base_version = first_version - 1;
            if let Some(counters) = self.db.get::<LedgerCountersSchema>(&base_version)? {
                counters
            } else {
                crit!(
                    "Base version ({}) ledger counters not found. Assuming zeros.",
                    base_version
                );
                LedgerCounters::new()
            }
        } else {
            LedgerCounters::new()
        };

        counters.bump(bumps);
        batch.put::<LedgerCountersSchema>(&last_version, &counters)?;

        Ok(counters)
    }
}

#[cfg(test)]
mod test;
<commit_msg>[storage] trivial: remove a unnecessary `#[allow(dead_code)]`<commit_after>//! This file defines system store APIs that operates data not part of the Libra core data
//! structures but information with regard to system running status, statistics, etc.

use crate::{
    ledger_counters::{LedgerCounterBumps, LedgerCounters},
    schema::ledger_counters::LedgerCountersSchema,
};
use failure::prelude::*;
use logger::prelude::*;
use schemadb::{SchemaBatch, DB};
use std::sync::Arc;
use types::transaction::Version;

pub(crate) struct SystemStore {
    db: Arc<DB>,
}

impl SystemStore {
    pub fn new(db: Arc<DB>) -> Self {
        Self { db }
    }

    /// Increase ledger counters.
    ///
    /// The base values are read out of db, to which the `diff` is combined to, and the result is
    /// stored to the db, keyed by `last_version`.
    pub fn bump_ledger_counters(
        &self,
        first_version: Version,
        last_version: Version,
        bumps: LedgerCounterBumps,
        batch: &mut SchemaBatch,
    ) -> Result<LedgerCounters> {
        assert!(first_version <= last_version);

        let mut counters = if first_version > 0 {
            let base_version = first_version - 1;
            if let Some(counters) = self.db.get::<LedgerCountersSchema>(&base_version)? {
                counters
            } else {
                crit!(
                    "Base version ({}) ledger counters not found. Assuming zeros.",
                    base_version
                );
                LedgerCounters::new()
            }
        } else {
            LedgerCounters::new()
        };

        counters.bump(bumps);
        batch.put::<LedgerCountersSchema>(&last_version, &counters)?;

        Ok(counters)
    }
}

#[cfg(test)]
mod test;
<|endoftext|>