<commit_before>use crate::loom::sync::atomic::AtomicU64;
use crate::sync::AtomicWaker;
use crate::time::driver::{Handle, Inner};
use crate::time::{Duration, Error, Instant};

use std::cell::UnsafeCell;
use std::ptr;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::SeqCst;
use std::sync::{Arc, Weak};
use std::task::{self, Poll};
use std::u64;

/// Internal state shared between a `Delay` instance and the timer.
///
/// This struct is used as a node in two intrusive data structures:
///
/// * An atomic stack used to signal to the timer thread that the entry state
///   has changed. The timer thread will observe the entry on this stack and
///   perform any actions as necessary.
///
/// * A doubly linked list used **only** by the timer thread. Each slot in the
///   timer wheel is a head pointer to the list of entries that must be
///   processed during that timer tick.
#[derive(Debug)]
pub(crate) struct Entry {
    /// Only accessed from `Registration`.
    time: CachePadded<UnsafeCell<Time>>,

    /// Timer internals. Using a weak pointer allows the timer to shutdown
    /// without all `Delay` instances having completed.
    ///
    /// When `None`, the entry has not yet been linked with a timer instance.
    inner: Weak<Inner>,

    /// Tracks the entry state. This value contains the following information:
    ///
    /// * The deadline at which the entry must be "fired".
    /// * A flag indicating if the entry has already been fired.
    /// * Whether or not the entry transitioned to the error state.
    ///
    /// When an `Entry` is created, `state` is initialized to the instant at
    /// which the entry must be fired. When a timer is reset to a different
    /// instant, this value is changed.
    state: AtomicU64,

    /// Task to notify once the deadline is reached.
    waker: AtomicWaker,

    /// True when the entry is queued in the "process" stack. This value
    /// is set before pushing the value and unset after popping the value.
    ///
    /// TODO: This could possibly be rolled up into `state`.
    pub(super) queued: AtomicBool,

    /// Next entry in the "process" linked list.
    ///
    /// Access to this field is coordinated by the `queued` flag.
    ///
    /// Represents a strong Arc ref.
    pub(super) next_atomic: UnsafeCell<*mut Entry>,

    /// When the entry expires, relative to the `start` of the timer
    /// (Inner::start). This is only used by the timer.
    ///
    /// A `Delay` instance can be reset to a different deadline by the thread
    /// that owns the `Delay` instance. In this case, the timer thread will not
    /// immediately know that this has happened. The timer thread must know the
    /// last deadline that it saw as it uses this value to locate the entry in
    /// its wheel.
    ///
    /// Once the timer thread observes that the instant has changed, it updates
    /// the wheel and sets this value. The idea is that this value eventually
    /// converges to the value of `state` as the timer thread makes updates.
    when: UnsafeCell<Option<u64>>,

    /// Next entry in the State's linked list.
    ///
    /// This is only accessed by the timer
    pub(super) next_stack: UnsafeCell<Option<Arc<Entry>>>,

    /// Previous entry in the State's linked list.
    ///
    /// This is only accessed by the timer and is used to unlink a canceled
    /// entry.
    ///
    /// This is a weak reference.
    pub(super) prev_stack: UnsafeCell<*const Entry>,
}

/// Stores the info for `Delay`.
#[derive(Debug)]
pub(crate) struct Time {
    pub(crate) deadline: Instant,
    pub(crate) duration: Duration,
}

/// Flag indicating a timer entry has elapsed
const ELAPSED: u64 = 1 << 63;

/// Flag indicating a timer entry has reached an error state
const ERROR: u64 = u64::MAX;

// ===== impl Entry =====

impl Entry {
    pub(crate) fn new(handle: &Handle, deadline: Instant, duration: Duration) -> Arc<Entry> {
        let inner = handle.inner().unwrap();
        let entry: Entry;

        // Increment the number of active timeouts
        if inner.increment().is_err() {
            entry = Entry::new2(deadline, duration, Weak::new(), ERROR)
        } else {
            let when = inner.normalize_deadline(deadline);
            let state = if when <= inner.elapsed() {
                ELAPSED
            } else {
                when
            };
            entry = Entry::new2(deadline, duration, Arc::downgrade(&inner), state);
        }

        let entry = Arc::new(entry);
        if inner.queue(&entry).is_err() {
            entry.error();
        }

        entry
    }

    /// Only called by `Registration`
    pub(crate) fn time_ref(&self) -> &Time {
        unsafe { &*self.time.0.get() }
    }

    /// Only called by `Registration`
    #[allow(clippy::mut_from_ref)] // https://github.com/rust-lang/rust-clippy/issues/4281
    pub(crate) unsafe fn time_mut(&self) -> &mut Time {
        &mut *self.time.0.get()
    }

    /// The current entry state as known by the timer. This is not the value of
    /// `state`, but lets the timer know how to converge its state to `state`.
    pub(crate) fn when_internal(&self) -> Option<u64> {
        unsafe { *self.when.get() }
    }

    pub(crate) fn set_when_internal(&self, when: Option<u64>) {
        unsafe {
            *self.when.get() = when;
        }
    }

    /// Called by `Timer` to load the current value of `state` for processing
    pub(crate) fn load_state(&self) -> Option<u64> {
        let state = self.state.load(SeqCst);

        if is_elapsed(state) {
            None
        } else {
            Some(state)
        }
    }

    pub(crate) fn is_elapsed(&self) -> bool {
        let state = self.state.load(SeqCst);
        is_elapsed(state)
    }

    pub(crate) fn fire(&self, when: u64) {
        let mut curr = self.state.load(SeqCst);

        loop {
            if is_elapsed(curr) || curr > when {
                return;
            }

            let next = ELAPSED | curr;
            let actual = self.state.compare_and_swap(curr, next, SeqCst);

            if curr == actual {
                break;
            }

            curr = actual;
        }

        self.waker.wake();
    }

    pub(crate) fn error(&self) {
        // Only transition to the error state if not currently elapsed
        let mut curr = self.state.load(SeqCst);

        loop {
            if is_elapsed(curr) {
                return;
            }

            let next = ERROR;

            let actual = self.state.compare_and_swap(curr, next, SeqCst);

            if curr == actual {
                break;
            }

            curr = actual;
        }

        self.waker.wake();
    }

    pub(crate) fn cancel(entry: &Arc<Entry>) {
        let state = entry.state.fetch_or(ELAPSED, SeqCst);

        if is_elapsed(state) {
            // Nothing more to do
            return;
        }

        // If registered with a timer instance, try to upgrade the Arc.
        let inner = match entry.upgrade_inner() {
            Some(inner) => inner,
            None => return,
        };

        let _ = inner.queue(entry);
    }

    pub(crate) fn poll_elapsed(&self, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>> {
        let mut curr = self.state.load(SeqCst);

        if is_elapsed(curr) {
            return Poll::Ready(if curr == ERROR {
                Err(Error::shutdown())
            } else {
                Ok(())
            });
        }

        self.waker.register_by_ref(cx.waker());

        curr = self.state.load(SeqCst);

        if is_elapsed(curr) {
            return Poll::Ready(if curr == ERROR {
                Err(Error::shutdown())
            } else {
                Ok(())
            });
        }

        Poll::Pending
    }

    /// Only called by `Registration`
    pub(crate) fn reset(entry: &mut Arc<Entry>) {
        let inner = match entry.upgrade_inner() {
            Some(inner) => inner,
            None => return,
        };

        let deadline = entry.time_ref().deadline;
        let when = inner.normalize_deadline(deadline);
        let elapsed = inner.elapsed();

        let next = if when <= elapsed { ELAPSED } else { when };

        let mut curr = entry.state.load(SeqCst);

        loop {
            // In these two cases, there is no work to do when resetting the
            // timer. If the `Entry` is in an error state, then it cannot be
            // used anymore. If resetting the entry to the current value, then
            // the reset is a noop.
            if curr == ERROR || curr == when {
                return;
            }

            let actual = entry.state.compare_and_swap(curr, next, SeqCst);

            if curr == actual {
                break;
            }

            curr = actual;
        }

        // If the state has transitioned to 'elapsed' then wake the task as
        // this entry is ready to be polled.
        if !is_elapsed(curr) && is_elapsed(next) {
            entry.waker.wake();
        }

        // The driver tracks all non-elapsed entries; notify the driver that it
        // should update its state for this entry unless the entry had already
        // elapsed and remains elapsed.
        if !is_elapsed(curr) || !is_elapsed(next) {
            let _ = inner.queue(entry);
        }
    }

    fn new2(deadline: Instant, duration: Duration, inner: Weak<Inner>, state: u64) -> Self {
        Self {
            time: CachePadded(UnsafeCell::new(Time { deadline, duration })),
            inner,
            waker: AtomicWaker::new(),
            state: AtomicU64::new(state),
            queued: AtomicBool::new(false),
            next_atomic: UnsafeCell::new(ptr::null_mut()),
            when: UnsafeCell::new(None),
            next_stack: UnsafeCell::new(None),
            prev_stack: UnsafeCell::new(ptr::null_mut()),
        }
    }

    fn upgrade_inner(&self) -> Option<Arc<Inner>> {
        self.inner.upgrade()
    }
}

fn is_elapsed(state: u64) -> bool {
    state & ELAPSED == ELAPSED
}

impl Drop for Entry {
    fn drop(&mut self) {
        let inner = match self.upgrade_inner() {
            Some(inner) => inner,
            None => return,
        };

        inner.decrement();
    }
}

unsafe impl Send for Entry {}
unsafe impl Sync for Entry {}

#[cfg_attr(target_arch = "x86_64", repr(align(128)))]
#[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
#[derive(Debug)]
struct CachePadded<T>(T);
<commit_msg>time: improve Entry field comment (#2671)<commit_after>use crate::loom::sync::atomic::AtomicU64;
use crate::sync::AtomicWaker;
use crate::time::driver::{Handle, Inner};
use crate::time::{Duration, Error, Instant};

use std::cell::UnsafeCell;
use std::ptr;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::SeqCst;
use std::sync::{Arc, Weak};
use std::task::{self, Poll};
use std::u64;

/// Internal state shared between a `Delay` instance and the timer.
///
/// This struct is used as a node in two intrusive data structures:
///
/// * An atomic stack used to signal to the timer thread that the entry state
///   has changed. The timer thread will observe the entry on this stack and
///   perform any actions as necessary.
///
/// * A doubly linked list used **only** by the timer thread. Each slot in the
///   timer wheel is a head pointer to the list of entries that must be
///   processed during that timer tick.
#[derive(Debug)]
pub(crate) struct Entry {
    /// Only accessed from `Registration`.
    time: CachePadded<UnsafeCell<Time>>,

    /// Timer internals. Using a weak pointer allows the timer to shutdown
    /// without all `Delay` instances having completed.
    ///
    /// When empty, it means that the entry has not yet been linked with a
    /// timer instance.
    inner: Weak<Inner>,

    /// Tracks the entry state. This value contains the following information:
    ///
    /// * The deadline at which the entry must be "fired".
    /// * A flag indicating if the entry has already been fired.
    /// * Whether or not the entry transitioned to the error state.
    ///
    /// When an `Entry` is created, `state` is initialized to the instant at
    /// which the entry must be fired. When a timer is reset to a different
    /// instant, this value is changed.
    state: AtomicU64,

    /// Task to notify once the deadline is reached.
    waker: AtomicWaker,

    /// True when the entry is queued in the "process" stack. This value
    /// is set before pushing the value and unset after popping the value.
    ///
    /// TODO: This could possibly be rolled up into `state`.
    pub(super) queued: AtomicBool,

    /// Next entry in the "process" linked list.
    ///
    /// Access to this field is coordinated by the `queued` flag.
    ///
    /// Represents a strong Arc ref.
    pub(super) next_atomic: UnsafeCell<*mut Entry>,

    /// When the entry expires, relative to the `start` of the timer
    /// (Inner::start). This is only used by the timer.
    ///
    /// A `Delay` instance can be reset to a different deadline by the thread
    /// that owns the `Delay` instance. In this case, the timer thread will not
    /// immediately know that this has happened. The timer thread must know the
    /// last deadline that it saw as it uses this value to locate the entry in
    /// its wheel.
    ///
    /// Once the timer thread observes that the instant has changed, it updates
    /// the wheel and sets this value. The idea is that this value eventually
    /// converges to the value of `state` as the timer thread makes updates.
    when: UnsafeCell<Option<u64>>,

    /// Next entry in the State's linked list.
    ///
    /// This is only accessed by the timer
    pub(super) next_stack: UnsafeCell<Option<Arc<Entry>>>,

    /// Previous entry in the State's linked list.
    ///
    /// This is only accessed by the timer and is used to unlink a canceled
    /// entry.
    ///
    /// This is a weak reference.
    pub(super) prev_stack: UnsafeCell<*const Entry>,
}

/// Stores the info for `Delay`.
#[derive(Debug)]
pub(crate) struct Time {
    pub(crate) deadline: Instant,
    pub(crate) duration: Duration,
}

/// Flag indicating a timer entry has elapsed
const ELAPSED: u64 = 1 << 63;

/// Flag indicating a timer entry has reached an error state
const ERROR: u64 = u64::MAX;

// ===== impl Entry =====

impl Entry {
    pub(crate) fn new(handle: &Handle, deadline: Instant, duration: Duration) -> Arc<Entry> {
        let inner = handle.inner().unwrap();
        let entry: Entry;

        // Increment the number of active timeouts
        if inner.increment().is_err() {
            entry = Entry::new2(deadline, duration, Weak::new(), ERROR)
        } else {
            let when = inner.normalize_deadline(deadline);
            let state = if when <= inner.elapsed() {
                ELAPSED
            } else {
                when
            };
            entry = Entry::new2(deadline, duration, Arc::downgrade(&inner), state);
        }

        let entry = Arc::new(entry);
        if inner.queue(&entry).is_err() {
            entry.error();
        }

        entry
    }

    /// Only called by `Registration`
    pub(crate) fn time_ref(&self) -> &Time {
        unsafe { &*self.time.0.get() }
    }

    /// Only called by `Registration`
    #[allow(clippy::mut_from_ref)] // https://github.com/rust-lang/rust-clippy/issues/4281
    pub(crate) unsafe fn time_mut(&self) -> &mut Time {
        &mut *self.time.0.get()
    }

    /// The current entry state as known by the timer. This is not the value of
    /// `state`, but lets the timer know how to converge its state to `state`.
    pub(crate) fn when_internal(&self) -> Option<u64> {
        unsafe { *self.when.get() }
    }

    pub(crate) fn set_when_internal(&self, when: Option<u64>) {
        unsafe {
            *self.when.get() = when;
        }
    }

    /// Called by `Timer` to load the current value of `state` for processing
    pub(crate) fn load_state(&self) -> Option<u64> {
        let state = self.state.load(SeqCst);

        if is_elapsed(state) {
            None
        } else {
            Some(state)
        }
    }

    pub(crate) fn is_elapsed(&self) -> bool {
        let state = self.state.load(SeqCst);
        is_elapsed(state)
    }

    pub(crate) fn fire(&self, when: u64) {
        let mut curr = self.state.load(SeqCst);

        loop {
            if is_elapsed(curr) || curr > when {
                return;
            }

            let next = ELAPSED | curr;
            let actual = self.state.compare_and_swap(curr, next, SeqCst);

            if curr == actual {
                break;
            }

            curr = actual;
        }

        self.waker.wake();
    }

    pub(crate) fn error(&self) {
        // Only transition to the error state if not currently elapsed
        let mut curr = self.state.load(SeqCst);

        loop {
            if is_elapsed(curr) {
                return;
            }

            let next = ERROR;

            let actual = self.state.compare_and_swap(curr, next, SeqCst);

            if curr == actual {
                break;
            }

            curr = actual;
        }

        self.waker.wake();
    }

    pub(crate) fn cancel(entry: &Arc<Entry>) {
        let state = entry.state.fetch_or(ELAPSED, SeqCst);

        if is_elapsed(state) {
            // Nothing more to do
            return;
        }

        // If registered with a timer instance, try to upgrade the Arc.
        let inner = match entry.upgrade_inner() {
            Some(inner) => inner,
            None => return,
        };

        let _ = inner.queue(entry);
    }

    pub(crate) fn poll_elapsed(&self, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>> {
        let mut curr = self.state.load(SeqCst);

        if is_elapsed(curr) {
            return Poll::Ready(if curr == ERROR {
                Err(Error::shutdown())
            } else {
                Ok(())
            });
        }

        self.waker.register_by_ref(cx.waker());

        curr = self.state.load(SeqCst);

        if is_elapsed(curr) {
            return Poll::Ready(if curr == ERROR {
                Err(Error::shutdown())
            } else {
                Ok(())
            });
        }

        Poll::Pending
    }

    /// Only called by `Registration`
    pub(crate) fn reset(entry: &mut Arc<Entry>) {
        let inner = match entry.upgrade_inner() {
            Some(inner) => inner,
            None => return,
        };

        let deadline = entry.time_ref().deadline;
        let when = inner.normalize_deadline(deadline);
        let elapsed = inner.elapsed();

        let next = if when <= elapsed { ELAPSED } else { when };

        let mut curr = entry.state.load(SeqCst);

        loop {
            // In these two cases, there is no work to do when resetting the
            // timer. If the `Entry` is in an error state, then it cannot be
            // used anymore. If resetting the entry to the current value, then
            // the reset is a noop.
            if curr == ERROR || curr == when {
                return;
            }

            let actual = entry.state.compare_and_swap(curr, next, SeqCst);

            if curr == actual {
                break;
            }

            curr = actual;
        }

        // If the state has transitioned to 'elapsed' then wake the task as
        // this entry is ready to be polled.
        if !is_elapsed(curr) && is_elapsed(next) {
            entry.waker.wake();
        }

        // The driver tracks all non-elapsed entries; notify the driver that it
        // should update its state for this entry unless the entry had already
        // elapsed and remains elapsed.
        if !is_elapsed(curr) || !is_elapsed(next) {
            let _ = inner.queue(entry);
        }
    }

    fn new2(deadline: Instant, duration: Duration, inner: Weak<Inner>, state: u64) -> Self {
        Self {
            time: CachePadded(UnsafeCell::new(Time { deadline, duration })),
            inner,
            waker: AtomicWaker::new(),
            state: AtomicU64::new(state),
            queued: AtomicBool::new(false),
            next_atomic: UnsafeCell::new(ptr::null_mut()),
            when: UnsafeCell::new(None),
            next_stack: UnsafeCell::new(None),
            prev_stack: UnsafeCell::new(ptr::null_mut()),
        }
    }

    fn upgrade_inner(&self) -> Option<Arc<Inner>> {
        self.inner.upgrade()
    }
}

fn is_elapsed(state: u64) -> bool {
    state & ELAPSED == ELAPSED
}

impl Drop for Entry {
    fn drop(&mut self) {
        let inner = match self.upgrade_inner() {
            Some(inner) => inner,
            None => return,
        };

        inner.decrement();
    }
}

unsafe impl Send for Entry {}
unsafe impl Sync for Entry {}

#[cfg_attr(target_arch = "x86_64", repr(align(128)))]
#[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
#[derive(Debug)]
struct CachePadded<T>(T);
<|endoftext|>


<commit_before>use std::convert::From;

use binding::{class, global};
use types;

use super::traits::RawObject;

pub struct Class {
    value: types::rb_value
}

impl Class {
    // TODO: replace rb_cObject with optional superclass
    pub fn new(name: &str) -> Self {
        Class {
            value: class::define_class(name, global::rb_cObject)
        }
    }

    pub fn define_method(&self,
                         name: &str,
                         callback: extern fn(types::rb_value) -> types::rb_value,
                         argc: i32) {
        class::define_method(self.value, name, callback, 0);
    }

    pub fn def_with_closure(&self,
                         name: &str,
                         callback: extern fn(types::rb_value) -> types::rb_value,
                         argc: i32) {
        class::define_method(self.value, name, callback, 0);
    }
}

impl From<types::rb_value> for Class {
    fn from(value: types::rb_value) -> Self {
        Class {
            value: value
        }
    }
}

impl RawObject for Class {
    fn value(&self) -> types::rb_value {
        self.value
    }
}
<commit_msg>Remove Class def_with_closure()<commit_after>use std::convert::From;

use binding::{class, global};
use types;

use super::traits::RawObject;

pub struct Class {
    value: types::rb_value
}

impl Class {
    // TODO: replace rb_cObject with optional superclass
    pub fn new(name: &str) -> Self {
        Class {
            value: class::define_class(name, global::rb_cObject)
        }
    }

    pub fn define_method(&self,
                         name: &str,
                         callback: extern fn(types::rb_value) -> types::rb_value,
                         argc: i32) {
        class::define_method(self.value, name, callback, 0);
    }
}

impl From<types::rb_value> for Class {
    fn from(value: types::rb_value) -> Self {
        Class {
            value: value
        }
    }
}

impl RawObject for Class {
    fn value(&self) -> types::rb_value {
        self.value
    }
}
<|endoftext|>


<commit_before>use clap::ArgMatches;

use config::Config;

pub fn run(m: &ArgMatches, cfg: &Config) {
    match m.subcommand() {
        ("show-action", Some(m)) => {
            // PLACEHOLDER
            println!("Retrieving action id: {}", m.value_of("id").unwrap());
        },
        ("", None)               => {
            println!("Showing account info")
        },
        _ => unreachable!()
    }
}
<commit_msg>wip(account): begin real implementation<commit_after>use clap::ArgMatches;

use config::Config;
use libdo::DoManager;

pub fn run(m: &ArgMatches, cfg: &Config) {
    match m.subcommand() {
        ("show-action", Some(m)) => {
            // PLACEHOLDER
            println!("Retrieving action id: {}", m.value_of("id").unwrap());
        },
        ("", None)               => {
            if cfg.debug { println!("Displaying account with token:\n\t{}", &cfg.auth[..])}
            let domgr = DoManager::with_token(&cfg.auth[..]);
            let acct = domgr.account.request;
            if cfg.debug { println!("Sending request: {:?}", acct); }
            if !cfg.no_send {
                println!("{}", domgr.account.retrieve());
            }
        },
        _ => unreachable!()
    }
}
<|endoftext|>


<commit_before>mod init;
mod set;
mod sweep;
mod burn;
mod start;
mod end;
mod destroy;

use self::init::Init;
use self::set::Set;
use self::sweep::Sweep;
use self::burn::Burn;
use self::start::Start;
use self::end::End;
use self::destroy::Destroy;

use constant::*;
use lib::setting::*;

trait Command {
    fn validation(&self) -> bool;
    fn validate(&self) -> Result<(), String> {
        fn message(subject: String) -> String {
            format!(r#"WARNING: {} does not exist. Please use "init" command."#, subject)
        }

        if !working_dir_exists() {
            return Err(message(format!(r#""{}" directory"#, WORKING_DIR_NAME)));
        }
        if !storage_dir_exists() {
            return Err(message(format!(r#""{}" directory"#, STORAGE_DIR_NAME)));
        }
        if !config_file_exists() {
            return Err(message(format!(r#""{}" file"#, CONFIG_FILE_NAME)));
        }
        if !ignore_file_exists() {
            return Err(message(format!(r#""{}" file"#, IGNORE_FILE_NAME)));
        }

        Ok(())
    }

    fn help_message(&self) -> &'static str;
    fn help(&self) {
        println!("{}", self.help_message());
    }

    fn main(&self);

    fn exec(&self, need_help: bool) {
        if self.validation() {
            if let Err(message) = self.validate() {
                return println!("{}", message);
            }
        }

        if need_help {
            self.help();
        } else {
            self.main();
        }
    }
}

pub fn execute(args: Vec<String>) {
    if args.is_empty() {
        return print_usage();
    }

    let need_help = args.iter().any(|a| *a == "-h" || *a == "--help");

    let command: Box<Command> = match args[0].as_ref() {
        "init"    => Box::new(Init   ),
        "set"     => Box::new(Set    ),
        "sweep"   => Box::new(Sweep  ),
        "burn"    => Box::new(Burn   ),
        "start"   => Box::new(Start  ),
        "end"     => Box::new(End    ),
        "destroy" => Box::new(Destroy),
        _         => return print_usage(),
    };

    command.exec(need_help);
}

pub fn print_usage() {
    println!(
r#"Usage:
    {} <command> [--help|-h]

Command:
    init    # Register current directory.
    set     # Set parameters.
    sweep   # Sweep files in current directory.
    burn    # Burn sweeped files.
    start   # Start "{}".
    end     # End "{}".
    destroy # Destroy "{}"."#,
        ME,
        ME,
        ME,
        ME,
    );
}
<commit_msg>[Refactor] Rename the variable "need_help" => "help"<commit_after>mod init;
mod set;
mod sweep;
mod burn;
mod start;
mod end;
mod destroy;

use self::init::Init;
use self::set::Set;
use self::sweep::Sweep;
use self::burn::Burn;
use self::start::Start;
use self::end::End;
use self::destroy::Destroy;

use constant::*;
use lib::setting::*;

trait Command {
    fn validation(&self) -> bool;
    fn validate(&self) -> Result<(), String> {
        fn message(subject: String) -> String {
            format!(r#"WARNING: {} does not exist. Please use "init" command."#, subject)
        }

        if !working_dir_exists() {
            return Err(message(format!(r#""{}" directory"#, WORKING_DIR_NAME)));
        }
        if !storage_dir_exists() {
            return Err(message(format!(r#""{}" directory"#, STORAGE_DIR_NAME)));
        }
        if !config_file_exists() {
            return Err(message(format!(r#""{}" file"#, CONFIG_FILE_NAME)));
        }
        if !ignore_file_exists() {
            return Err(message(format!(r#""{}" file"#, IGNORE_FILE_NAME)));
        }

        Ok(())
    }

    fn help_message(&self) -> &'static str;
    fn help(&self) {
        println!("{}", self.help_message());
    }

    fn main(&self);

    fn exec(&self, help: bool) {
        if self.validation() {
            if let Err(message) = self.validate() {
                return println!("{}", message);
            }
        }

        if help {
            self.help();
        } else {
            self.main();
        }
    }
}

pub fn execute(args: Vec<String>) {
    if args.is_empty() {
        return print_usage();
    }

    let help = args.iter().any(|a| *a == "-h" || *a == "--help");

    let command: Box<Command> = match args[0].as_ref() {
        "init"    => Box::new(Init   ),
        "set"     => Box::new(Set    ),
        "sweep"   => Box::new(Sweep  ),
        "burn"    => Box::new(Burn   ),
        "start"   => Box::new(Start  ),
        "end"     => Box::new(End    ),
        "destroy" => Box::new(Destroy),
        _         => return print_usage(),
    };

    command.exec(help);
}

pub fn print_usage() {
    println!(
r#"Usage:
    {} <command> [--help|-h]

Command:
    init    # Register current directory.
    set     # Set parameters.
    sweep   # Sweep files in current directory.
    burn    # Burn sweeped files.
    start   # Start "{}".
    end     # End "{}".
    destroy # Destroy "{}"."#,
        ME,
        ME,
        ME,
        ME,
    );
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use super::{Idle, Poll, PrepareDownload, SharedState, State, StateChangeImpl, StateMachine};
use crate::client::Api;
use slog_scope::{debug, error, info};

#[derive(Debug, PartialEq, Clone)]
pub(super) enum ServerAddress {
    Default,
    Custom(String),
}

#[derive(Debug, PartialEq)]
pub(super) struct Probe {
    pub(super) server_address: ServerAddress,
}

create_state_step!(Probe => Idle);
create_state_step!(Probe => Poll);

/// Implements the state change for State<Probe>.
impl StateChangeImpl for State<Probe> {
    fn name(&self) -> &'static str {
        "probe"
    }

    fn handle(self, shared_state: &mut SharedState) -> Result<StateMachine, failure::Error> {
        use crate::client::ProbeResponse;
        use chrono::{Duration, Utc};
        use std::thread;

        let server_address = match self.0.server_address.clone() {
            ServerAddress::Default => shared_state.settings.network.server_address.clone(),
            ServerAddress::Custom(s) => s,
        };

        let r = loop {
            let probe = Api::new(&server_address)
                .probe(&shared_state.runtime_settings, &shared_state.firmware);
            if let Err(e) = probe {
                error!("{}", e);
                shared_state.runtime_settings.inc_retries();
                thread::sleep(Duration::seconds(1).to_std().unwrap());
            } else {
                shared_state.runtime_settings.clear_retries();
                break probe?;
            }
        };

        if let ProbeResponse::ExtraPoll(s) = r {
            info!("Delaying the probing as requested by the server.");
            shared_state
                .runtime_settings
                .set_polling_extra_interval(Duration::seconds(s))?;
        };

        match r {
            ProbeResponse::NoUpdate => {
                debug!("Moving to Idle state as no update is available.");

                // Store timestamp of last polling
                shared_state.runtime_settings.set_last_polling(Utc::now())?;
                Ok(StateMachine::Idle(self.into()))
            }

            ProbeResponse::ExtraPoll(_) => {
                debug!("Moving to Poll state due the extra polling interval.");
                Ok(StateMachine::Poll(self.into()))
            }

            ProbeResponse::Update(u) => {
                // Ensure the package is compatible
                u.compatible_with(&shared_state.firmware)?;
                // Store timestamp of last polling
                shared_state.runtime_settings.set_last_polling(Utc::now())?;

                if Some(u.package_uid()) == shared_state.runtime_settings.applied_package_uid() {
                    info!(
                        "Not applying the update package. Same package has already been installed."
                    );
                    debug!("Moving to Idle state as this update package is already installed.");
                    Ok(StateMachine::Idle(self.into()))
                } else {
                    debug!("Moving to PrepareDownload state to process the update package.");
                    Ok(StateMachine::PrepareDownload(State(PrepareDownload {
                        update_package: u,
                    })))
                }
            }
        }
    }
}

#[test]
fn update_not_available() {
    use super::*;
    use crate::{
        client::tests::{create_mock_server, FakeServer},
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    let mock = create_mock_server(FakeServer::NoUpdate);

    let settings = Settings::default();
    let runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::NoUpdate)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state)
    .unwrap();

    mock.assert();

    assert_state!(machine, Idle);
}

#[test]
fn update_available() {
    use super::*;
    use crate::{
        client::tests::{create_mock_server, FakeServer},
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    let mock = create_mock_server(FakeServer::HasUpdate);

    let settings = Settings::default();
    let runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::HasUpdate)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state)
    .unwrap();

    mock.assert();

    assert_state!(machine, PrepareDownload);
}

#[test]
fn invalid_hardware() {
    use super::*;
    use crate::{
        client::tests::{create_mock_server, FakeServer},
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    let mock = create_mock_server(FakeServer::InvalidHardware);

    let settings = Settings::default();
    let runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::InvalidHardware)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state);

    mock.assert();

    assert!(machine.is_err(), "Did not catch an incompatible hardware");
}

#[test]
fn extra_poll_interval() {
    use super::*;
    use crate::{
        client::tests::{create_mock_server, FakeServer},
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    let mock = create_mock_server(FakeServer::ExtraPoll);

    let settings = Settings::default();
    let runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::ExtraPoll)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state)
    .unwrap();

    mock.assert();

    assert_state!(machine, Poll);
}

#[test]
fn skip_same_package_uid() {
    use super::*;
    use crate::{
        client::{
            tests::{create_mock_server, FakeServer},
            ProbeResponse,
        },
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    let mock = create_mock_server(FakeServer::HasUpdate).expect(2);

    let mut runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();

    // We first get the package_uid that will be returned so we can
    // use it for the upcoming test.
    //
    // This has been done so we don't need to manually update it every
    // time we change the package payload.
    let probe = Api::new(&Settings::default().network.server_address)
        .probe(
            &RuntimeSettings::default(),
            &Metadata::from_path(&create_fake_metadata(FakeDevice::HasUpdate)).unwrap(),
        )
        .unwrap();

    if let ProbeResponse::Update(u) = probe {
        runtime_settings
            .set_applied_package_uid(&u.package_uid())
            .unwrap();
    }

    let settings = Settings::default();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::HasUpdate)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state)
    .unwrap();

    mock.assert();

    assert_state!(machine, Idle);
}

#[test]
fn error() {
    use super::*;
    use crate::{
        client::tests::{create_mock_server, FakeServer},
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    // The server here waits for the second request which includes the
    // retries to succeed.
    let mock = create_mock_server(FakeServer::ErrorOnce);

    let settings = Settings::default();
    let runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::NoUpdate)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state)
    .unwrap();

    mock.assert();

    assert_state!(machine, Idle);
}
<commit_msg>updatehub: Probe state now accepts probe request in order to change the probing server<commit_after>// Copyright (C) 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use super::{Idle, Poll, PrepareDownload, SharedState, State, StateChangeImpl, StateMachine};
use crate::client::Api;
use slog_scope::{debug, error, info};

#[derive(Debug, PartialEq, Clone)]
pub(super) enum ServerAddress {
    Default,
    Custom(String),
}

#[derive(Debug, PartialEq)]
pub(super) struct Probe {
    pub(super) server_address: ServerAddress,
}

create_state_step!(Probe => Idle);
create_state_step!(Probe => Poll);

/// Implements the state change for State<Probe>.
impl StateChangeImpl for State<Probe> {
    fn name(&self) -> &'static str {
        "probe"
    }

    fn handle_trigger_probe(&self) -> actor::probe::Response {
        actor::probe::Response::RequestAccepted(self.name().to_owned())
    }

    fn handle(self, shared_state: &mut SharedState) -> Result<StateMachine, failure::Error> {
        use crate::client::ProbeResponse;
        use chrono::{Duration, Utc};
        use std::thread;

        let server_address = match self.0.server_address.clone() {
            ServerAddress::Default => shared_state.settings.network.server_address.clone(),
            ServerAddress::Custom(s) => s,
        };

        let r = loop {
            let probe = Api::new(&server_address)
                .probe(&shared_state.runtime_settings, &shared_state.firmware);
            if let Err(e) = probe {
                error!("{}", e);
                shared_state.runtime_settings.inc_retries();
                thread::sleep(Duration::seconds(1).to_std().unwrap());
            } else {
                shared_state.runtime_settings.clear_retries();
                break probe?;
            }
        };

        if let ProbeResponse::ExtraPoll(s) = r {
            info!("Delaying the probing as requested by the server.");
            shared_state
                .runtime_settings
                .set_polling_extra_interval(Duration::seconds(s))?;
        };

        match r {
            ProbeResponse::NoUpdate => {
                debug!("Moving to Idle state as no update is available.");

                // Store timestamp of last polling
                shared_state.runtime_settings.set_last_polling(Utc::now())?;
                Ok(StateMachine::Idle(self.into()))
            }

            ProbeResponse::ExtraPoll(_) => {
                debug!("Moving to Poll state due the extra polling interval.");
                Ok(StateMachine::Poll(self.into()))
            }

            ProbeResponse::Update(u) => {
                // Ensure the package is compatible
                u.compatible_with(&shared_state.firmware)?;
                // Store timestamp of last polling
                shared_state.runtime_settings.set_last_polling(Utc::now())?;

                if Some(u.package_uid()) == shared_state.runtime_settings.applied_package_uid() {
                    info!(
                        "Not applying the update package. Same package has already been installed."
                    );
                    debug!("Moving to Idle state as this update package is already installed.");
                    Ok(StateMachine::Idle(self.into()))
                } else {
                    debug!("Moving to PrepareDownload state to process the update package.");
                    Ok(StateMachine::PrepareDownload(State(PrepareDownload {
                        update_package: u,
                    })))
                }
            }
        }
    }
}

#[test]
fn update_not_available() {
    use super::*;
    use crate::{
        client::tests::{create_mock_server, FakeServer},
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    let mock = create_mock_server(FakeServer::NoUpdate);

    let settings = Settings::default();
    let runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::NoUpdate)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state)
    .unwrap();

    mock.assert();

    assert_state!(machine, Idle);
}

#[test]
fn update_available() {
    use super::*;
    use crate::{
        client::tests::{create_mock_server, FakeServer},
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    let mock = create_mock_server(FakeServer::HasUpdate);

    let settings = Settings::default();
    let runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::HasUpdate)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state)
    .unwrap();

    mock.assert();

    assert_state!(machine, PrepareDownload);
}

#[test]
fn invalid_hardware() {
    use super::*;
    use crate::{
        client::tests::{create_mock_server, FakeServer},
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    let mock = create_mock_server(FakeServer::InvalidHardware);

    let settings = Settings::default();
    let runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::InvalidHardware)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state);

    mock.assert();

    assert!(machine.is_err(), "Did not catch an incompatible hardware");
}

#[test]
fn extra_poll_interval() {
    use super::*;
    use crate::{
        client::tests::{create_mock_server, FakeServer},
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    let mock = create_mock_server(FakeServer::ExtraPoll);

    let settings = Settings::default();
    let runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::ExtraPoll)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state)
    .unwrap();

    mock.assert();

    assert_state!(machine, Poll);
}

#[test]
fn skip_same_package_uid() {
    use super::*;
    use crate::{
        client::{
            tests::{create_mock_server, FakeServer},
            ProbeResponse,
        },
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    let mock = create_mock_server(FakeServer::HasUpdate).expect(2);

    let mut runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();

    // We first get the package_uid that will be returned so we can
    // use it for the upcoming test.
    //
    // This has been done so we don't need to manually update it every
    // time we change the package payload.
    let probe = Api::new(&Settings::default().network.server_address)
        .probe(
            &RuntimeSettings::default(),
            &Metadata::from_path(&create_fake_metadata(FakeDevice::HasUpdate)).unwrap(),
        )
        .unwrap();

    if let ProbeResponse::Update(u) = probe {
        runtime_settings
            .set_applied_package_uid(&u.package_uid())
            .unwrap();
    }

    let settings = Settings::default();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::HasUpdate)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state)
    .unwrap();

    mock.assert();

    assert_state!(machine, Idle);
}

#[test]
fn error() {
    use super::*;
    use crate::{
        client::tests::{create_mock_server, FakeServer},
        firmware::tests::{create_fake_metadata, FakeDevice},
    };
    use std::fs;
    use tempfile::NamedTempFile;

    let tmpfile = NamedTempFile::new().unwrap();
    let tmpfile = tmpfile.path();
    fs::remove_file(&tmpfile).unwrap();

    // The server here waits for the second request which includes the
    // retries to succeed.
    let mock = create_mock_server(FakeServer::ErrorOnce);

    let settings = Settings::default();
    let runtime_settings = RuntimeSettings::new()
        .load(tmpfile.to_str().unwrap())
        .unwrap();
    let firmware = Metadata::from_path(&create_fake_metadata(FakeDevice::NoUpdate)).unwrap();
    let mut shared_state = SharedState {
        settings,
        runtime_settings,
        firmware,
    };

    let machine = StateMachine::Probe(State(Probe {
        server_address: ServerAddress::Default,
    }))
    .move_to_next_state(&mut shared_state)
    .unwrap();

    mock.assert();

    assert_state!(machine, Idle);
}
<|endoftext|>


<commit_before>// This file is @generated by no_atomic.sh.
// It is not intended for manual editing.

const NO_ATOMIC_CAS: &[&str] = &[
    "avr-unknown-gnu-atmega328",
    "bpfeb-unknown-none",
    "bpfel-unknown-none",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32im-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
];

#[allow(dead_code)] // Only crossbeam-utils uses this.
const NO_ATOMIC_64: &[&str] = &[
    "arm-linux-androideabi",
    "armebv7r-none-eabi",
    "armebv7r-none-eabihf",
    "armv4t-unknown-linux-gnueabi",
    "armv5te-unknown-linux-gnueabi",
    "armv5te-unknown-linux-musleabi",
    "armv5te-unknown-linux-uclibceabi",
    "armv6k-nintendo-3ds",
    "armv7r-none-eabi",
    "armv7r-none-eabihf",
    "avr-unknown-gnu-atmega328",
    "hexagon-unknown-linux-musl",
    "m68k-unknown-linux-gnu",
    "mips-unknown-linux-gnu",
    "mips-unknown-linux-musl",
    "mips-unknown-linux-uclibc",
    "mipsel-sony-psp",
    "mipsel-unknown-linux-gnu",
    "mipsel-unknown-linux-musl",
    "mipsel-unknown-linux-uclibc",
    "mipsel-unknown-none",
    "mipsisa32r6-unknown-linux-gnu",
    "mipsisa32r6el-unknown-linux-gnu",
    "msp430-none-elf",
    "powerpc-unknown-freebsd",
    "powerpc-unknown-linux-gnu",
    "powerpc-unknown-linux-gnuspe",
    "powerpc-unknown-linux-musl",
    "powerpc-unknown-netbsd",
    "powerpc-unknown-openbsd",
    "powerpc-wrs-vxworks",
    "powerpc-wrs-vxworks-spe",
    "riscv32gc-unknown-linux-gnu",
    "riscv32gc-unknown-linux-musl",
    "riscv32i-unknown-none-elf",
    "riscv32im-unknown-none-elf",
    "riscv32imac-unknown-none-elf",
    "riscv32imac-unknown-xous-elf",
    "riscv32imc-unknown-none-elf",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
    "thumbv7em-none-eabi",
    "thumbv7em-none-eabihf",
    "thumbv7m-none-eabi",
    "thumbv8m.base-none-eabi",
    "thumbv8m.main-none-eabi",
    "thumbv8m.main-none-eabihf",
];

#[allow(dead_code)] // Only crossbeam-utils uses this.
const NO_ATOMIC: &[&str] = &[
    "avr-unknown-gnu-atmega328",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32im-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
];
<commit_msg>Update no_atomic.rs<commit_after>// This file is @generated by no_atomic.sh.
// It is not intended for manual editing.

const NO_ATOMIC_CAS: &[&str] = &[
    "armv4t-none-eabi",
    "avr-unknown-gnu-atmega328",
    "bpfeb-unknown-none",
    "bpfel-unknown-none",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32im-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
];

#[allow(dead_code)] // Only crossbeam-utils uses this.
const NO_ATOMIC_64: &[&str] = &[
    "arm-linux-androideabi",
    "armebv7r-none-eabi",
    "armebv7r-none-eabihf",
    "armv4t-none-eabi",
    "armv4t-unknown-linux-gnueabi",
    "armv5te-unknown-linux-gnueabi",
    "armv5te-unknown-linux-musleabi",
    "armv5te-unknown-linux-uclibceabi",
    "armv6k-nintendo-3ds",
    "armv7r-none-eabi",
    "armv7r-none-eabihf",
    "avr-unknown-gnu-atmega328",
    "hexagon-unknown-linux-musl",
    "m68k-unknown-linux-gnu",
    "mips-unknown-linux-gnu",
    "mips-unknown-linux-musl",
    "mips-unknown-linux-uclibc",
    "mipsel-sony-psp",
    "mipsel-unknown-linux-gnu",
    "mipsel-unknown-linux-musl",
    "mipsel-unknown-linux-uclibc",
    "mipsel-unknown-none",
    "mipsisa32r6-unknown-linux-gnu",
    "mipsisa32r6el-unknown-linux-gnu",
    "msp430-none-elf",
    "powerpc-unknown-freebsd",
    "powerpc-unknown-linux-gnu",
    "powerpc-unknown-linux-gnuspe",
    "powerpc-unknown-linux-musl",
    "powerpc-unknown-netbsd",
    "powerpc-unknown-openbsd",
    "powerpc-wrs-vxworks",
    "powerpc-wrs-vxworks-spe",
    "riscv32gc-unknown-linux-gnu",
    "riscv32gc-unknown-linux-musl",
    "riscv32i-unknown-none-elf",
    "riscv32im-unknown-none-elf",
    "riscv32imac-unknown-none-elf",
    "riscv32imac-unknown-xous-elf",
    "riscv32imc-unknown-none-elf",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
    "thumbv7em-none-eabi",
    "thumbv7em-none-eabihf",
    "thumbv7m-none-eabi",
    "thumbv8m.base-none-eabi",
    "thumbv8m.main-none-eabi",
    "thumbv8m.main-none-eabihf",
];

#[allow(dead_code)] // Only crossbeam-utils uses this.
const NO_ATOMIC: &[&str] = &[
    "avr-unknown-gnu-atmega328",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32im-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
];
<|endoftext|>


<commit_before>use test::Bencher;
use rand::{self, Rng};

use super::cluster::*;
use super::util::*;

/// Once [issue 18043](https://github.com/rust-lang/rust/issues/18043) is resolved,
/// use this function to generate test datas.
fn generate_random_kvs(n: usize, value_length: usize) -> Vec<(Vec<u8>, Vec<u8>)> {
    let mut kvs = Vec::with_capacity(n);
    let mut rng = rand::thread_rng();
    for i in 0..n {
        let k = format!("{:010}", i);
        let mut v = Vec::with_capacity(value_length);
        rng.fill_bytes(&mut v);
        kvs.push((k.into_bytes(), v));
    }
    kvs
}

#[bench]
fn bench_store_set_128_bytes_in_1_node(b: &mut Bencher) {
    bench_set(b, 1, 128)
}

#[bench]
fn bench_store_set_128_bytes_in_3_node(b: &mut Bencher) {
    bench_set(b, 3, 128)
}

#[bench]
fn bench_store_set_128_bytes_in_5_node(b: &mut Bencher) {
    bench_set(b, 5, 128)
}

#[bench]
fn bench_store_set_1024_bytes_in_5_node(b: &mut Bencher) {
    bench_set(b, 5, 1024)
}

#[bench]
fn bench_store_set_4096_bytes_in_5_node(b: &mut Bencher) {
    bench_set(b, 5, 4096)
}

fn bench_set(b: &mut Bencher, node_count: usize, value_size: usize) {
    let mut cluster = Cluster::new(0, node_count);
    cluster.bootstrap_single_region().expect("");
    cluster.run_all_stores();

    sleep_ms(100);

    assert!(cluster.leader_of_region(1).is_some());

    // Because we can't get the iteration count from Bencher currently,
    // so we use the max possible iteration round count here.
    // See also [Issue 18043](https://github.com/rust-lang/rust/issues/18043).
    // And https://github.com/rust-lang/rust/blob/master/src/libtest/lib.rs#L1239
    // TODO: use actual iteration count to initialize kvs.
    let mut kvs = generate_random_kvs(1_000_000, value_size);
    let mut iter = kvs.drain(..);

    b.iter(|| {
        let (k, v) = iter.next().unwrap();
        cluster.put(&k, &v);
    });
}

fn bench_delete(b: &mut Bencher, node_count: usize, value_size: usize) {
    let mut cluster = Cluster::new(0, node_count);
    cluster.bootstrap_single_region().expect("");
    cluster.run_all_stores();

    sleep_ms(300);

}<commit_msg>add delete bench<commit_after>use test::Bencher;
use rand::{self, Rng};

use super::cluster::*;
use super::util::*;

/// assume one action takes 2μs, then very iteration will try 1,000,000 / 2,000 = 500 times.
/// see also https://github.com/rust-lang/rust/blob/master/src/libtest/lib.rs#L1239
const DEFAULT_SAMPLE_SIZE: usize = 500;

/// Once [issue 18043](https://github.com/rust-lang/rust/issues/18043) is resolved,
/// use this function to generate test datas.
fn generate_random_kvs(n: usize, value_length: usize) -> Vec<(Vec<u8>, Vec<u8>)> {
    let mut kvs = Vec::with_capacity(n);
    let mut rng = rand::thread_rng();
    for i in 0..n {
        let k = i.to_string();
        let mut v = Vec::with_capacity(value_length);
        rng.fill_bytes(&mut v);
        kvs.push((k.into_bytes(), v));
    }
    kvs
}

#[bench]
fn bench_store_set_8_bytes_in_5_node(b: &mut Bencher) {
    bench_set(b, 1, 8)
}

#[bench]
fn bench_store_set_128_bytes_in_1_node(b: &mut Bencher) {
    bench_set(b, 1, 128)
}

#[bench]
fn bench_store_set_128_bytes_in_3_node(b: &mut Bencher) {
    bench_set(b, 3, 128)
}

#[bench]
fn bench_store_set_128_bytes_in_5_node(b: &mut Bencher) {
    bench_set(b, 5, 128)
}

#[bench]
fn bench_store_set_1024_bytes_in_5_node(b: &mut Bencher) {
    bench_set(b, 5, 1024)
}

#[bench]
fn bench_store_set_4096_bytes_in_5_node(b: &mut Bencher) {
    bench_set(b, 5, 4096)
}

fn prepare_cluster(node_count: usize) -> Cluster {
    let mut cluster = Cluster::new(0, node_count);
    cluster.bootstrap_single_region().expect("");
    cluster.run_all_stores();
    sleep_ms(200);
    assert!(cluster.leader_of_region(1).is_some());
    cluster
}

fn bench_set(b: &mut Bencher, node_count: usize, value_size: usize) {
    let mut cluster = prepare_cluster(node_count);

    // Because we can't get the iteration count from Bencher currently,
    // so we use the max possible iteration round count here.
    // See also [Issue 18043](https://github.com/rust-lang/rust/issues/18043).
    // TODO: use actual iteration count to initialize kvs.
    let mut kvs = generate_random_kvs(DEFAULT_SAMPLE_SIZE, value_size);
    let mut iter = kvs.drain(..);

    b.iter(|| {
        let (k, v) = iter.next().unwrap();
        cluster.put(&k, &v);
    });
}

#[bench]
fn bench_store_delete_in_1_node(b: &mut Bencher) {
    bench_delete(b, 1);
}

#[bench]
fn bench_store_delete_in_3_node(b: &mut Bencher) {
    bench_delete(b, 3);
}

#[bench]
fn bench_store_delete_in_5_node(b: &mut Bencher) {
    bench_delete(b, 5);
}

fn bench_delete(b: &mut Bencher, node_count: usize) {
    let mut cluster = prepare_cluster(node_count);

    // TODO: use actual iteration count to initialize kvs.
    let mut kvs = generate_random_kvs(DEFAULT_SAMPLE_SIZE, 128);
    for &(ref k, ref v) in &kvs {
        cluster.put(&k, &v);
    }

    let mut iter = kvs.drain(..);
    b.iter(|| {
        let (k, _) = iter.next().unwrap();
        cluster.delete(&k);
    });
}<|endoftext|>


<commit_before>generate_error_imports!();
use std::convert::Into;

generate_error_types!(HookError, HookErrorKind,
    HookExecutionError  => "Hook exec error",
    AccessTypeViolation => "Hook access type violation"
);

pub trait IntoHookError {
    fn into_hookerror(self) -> HookError;
    fn into_hookerror_with_cause(self, cause: Box<Error>) -> HookError;
}

impl Into<HookError> for (HookErrorKind, Box<Error>) {

    fn into(self) -> HookError {
        HookError::new(self.0, Some(self.1))
    }

}

<commit_msg>Remove old error code which is unused<commit_after>generate_error_imports!();
use std::convert::Into;

generate_error_types!(HookError, HookErrorKind,
    HookExecutionError  => "Hook exec error",
    AccessTypeViolation => "Hook access type violation"
);

<|endoftext|>


<commit_before>//! Functions related to adding and removing indentation from lines of
//! text.
//!
//! The functions here can be used to uniformly indent or dedent
//! (unindent) word wrapped lines of text.

/// Indent each line by the given prefix.
///
/// # Examples
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("First line.\nSecond line.\n", "  "),
///            "  First line.\n  Second line.\n");
/// ```
///
/// When indenting, trailing whitespace is stripped from the prefix.
/// This means that empty lines remain empty afterwards:
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("First line.\n\n\nSecond line.\n", "  "),
///            "  First line.\n\n\n  Second line.\n");
/// ```
///
/// Notice how `"\n\n\n"` remained as `"\n\n\n"`.
///
/// This feature is useful when you want to indent text and have a
/// space between your prefix and the text. In this case, you _don't_
/// want a trailing space on empty lines:
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("foo = 123\n\nprint(foo)\n", "# "),
///            "# foo = 123\n#\n# print(foo)\n");
/// ```
///
/// Notice how `"\n\n"` became `"\n#\n"` instead of `"\n# \n"` which
/// would have trailing whitespace.
///
/// Leading and trailing whitespace coming from the text itself is
/// kept unchanged:
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent(" \t  Foo   ", "->"), "-> \t  Foo   ");
/// ```
pub fn indent(s: &str, prefix: &str) -> String {
    let mut result = String::new();
    let trimmed_prefix = prefix.trim_end();
    for (idx, line) in s.split_terminator('\n').enumerate() {
        if idx > 0 {
            result.push('\n');
        }
        if line.trim().is_empty() {
            result.push_str(trimmed_prefix);
        } else {
            result.push_str(prefix);
        }
        result.push_str(line);
    }
    if s.ends_with('\n') {
        // split_terminator will have eaten the final '\n'.
        result.push('\n');
    }
    result
}

/// Removes common leading whitespace from each line.
///
/// This function will look at each non-empty line and determine the
/// maximum amount of whitespace that can be removed from all lines:
///
/// ```
/// use textwrap::dedent;
///
/// assert_eq!(dedent("
///     1st line
///       2nd line
///     3rd line
/// "), "
/// 1st line
///   2nd line
/// 3rd line
/// ");
/// ```
pub fn dedent(s: &str) -> String {
    let mut prefix = "";
    let mut lines = s.lines();

    // We first search for a non-empty line to find a prefix.
    for line in &mut lines {
        let mut whitespace_idx = line.len();
        for (idx, ch) in line.char_indices() {
            if !ch.is_whitespace() {
                whitespace_idx = idx;
                break;
            }
        }

        // Check if the line had anything but whitespace
        if whitespace_idx < line.len() {
            prefix = &line[..whitespace_idx];
            break;
        }
    }

    // We then continue looking through the remaining lines to
    // possibly shorten the prefix.
    for line in &mut lines {
        let mut whitespace_idx = line.len();
        for ((idx, a), b) in line.char_indices().zip(prefix.chars()) {
            if a != b {
                whitespace_idx = idx;
                break;
            }
        }

        // Check if the line had anything but whitespace and if we
        // have found a shorter prefix
        if whitespace_idx < line.len() && whitespace_idx < prefix.len() {
            prefix = &line[..whitespace_idx];
        }
    }

    // We now go over the lines a second time to build the result.
    let mut result = String::new();
    for line in s.lines() {
        if line.starts_with(&prefix) && line.chars().any(|c| !c.is_whitespace()) {
            let (_, tail) = line.split_at(prefix.len());
            result.push_str(tail);
        }
        result.push('\n');
    }

    if result.ends_with('\n') && !s.ends_with('\n') {
        let new_len = result.len() - 1;
        result.truncate(new_len);
    }

    result
}

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

    #[test]
    fn indent_empty() {
        assert_eq!(indent("\n", "  "), "\n");
    }

    #[test]
    #[rustfmt::skip]
    fn indent_nonempty() {
        let text = [
            "  foo\n",
            "bar\n",
            "  baz\n",
        ].join("");
        let expected = [
            "//   foo\n",
            "// bar\n",
            "//   baz\n",
        ].join("");
        assert_eq!(indent(&text, "// "), expected);
    }

    #[test]
    #[rustfmt::skip]
    fn indent_empty_line() {
        let text = [
            "  foo",
            "bar",
            "",
            "  baz",
        ].join("\n");
        let expected = [
            "//   foo",
            "// bar",
            "//",
            "//   baz",
        ].join("\n");
        assert_eq!(indent(&text, "// "), expected);
    }

    #[test]
    fn dedent_empty() {
        assert_eq!(dedent(""), "");
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_multi_line() {
        let x = [
            "    foo",
            "  bar",
            "    baz",
        ].join("\n");
        let y = [
            "  foo",
            "bar",
            "  baz"
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_empty_line() {
        let x = [
            "    foo",
            "  bar",
            "   ",
            "    baz"
        ].join("\n");
        let y = [
            "  foo",
            "bar",
            "",
            "  baz"
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_blank_line() {
        let x = [
            "      foo",
            "",
            "        bar",
            "          foo",
            "          bar",
            "          baz",
        ].join("\n");
        let y = [
            "foo",
            "",
            "  bar",
            "    foo",
            "    bar",
            "    baz",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_whitespace_line() {
        let x = [
            "      foo",
            " ",
            "        bar",
            "          foo",
            "          bar",
            "          baz",
        ].join("\n");
        let y = [
            "foo",
            "",
            "  bar",
            "    foo",
            "    bar",
            "    baz",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_mixed_whitespace() {
        let x = [
            "\tfoo",
            "  bar",
        ].join("\n");
        let y = [
            "\tfoo",
            "  bar",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_tabbed_whitespace() {
        let x = [
            "\t\tfoo",
            "\t\t\tbar",
        ].join("\n");
        let y = [
            "foo",
            "\tbar",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_mixed_tabbed_whitespace() {
        let x = [
            "\t  \tfoo",
            "\t  \t\tbar",
        ].join("\n");
        let y = [
            "foo",
            "\tbar",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_mixed_tabbed_whitespace2() {
        let x = [
            "\t  \tfoo",
            "\t    \tbar",
        ].join("\n");
        let y = [
            "\tfoo",
            "  \tbar",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_preserve_no_terminating_newline() {
        let x = [
            "  foo",
            "    bar",
        ].join("\n");
        let y = [
            "foo",
            "  bar",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }
}
<commit_msg>Preallocate output string for `indent`<commit_after>//! Functions related to adding and removing indentation from lines of
//! text.
//!
//! The functions here can be used to uniformly indent or dedent
//! (unindent) word wrapped lines of text.

/// Indent each line by the given prefix.
///
/// # Examples
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("First line.\nSecond line.\n", "  "),
///            "  First line.\n  Second line.\n");
/// ```
///
/// When indenting, trailing whitespace is stripped from the prefix.
/// This means that empty lines remain empty afterwards:
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("First line.\n\n\nSecond line.\n", "  "),
///            "  First line.\n\n\n  Second line.\n");
/// ```
///
/// Notice how `"\n\n\n"` remained as `"\n\n\n"`.
///
/// This feature is useful when you want to indent text and have a
/// space between your prefix and the text. In this case, you _don't_
/// want a trailing space on empty lines:
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("foo = 123\n\nprint(foo)\n", "# "),
///            "# foo = 123\n#\n# print(foo)\n");
/// ```
///
/// Notice how `"\n\n"` became `"\n#\n"` instead of `"\n# \n"` which
/// would have trailing whitespace.
///
/// Leading and trailing whitespace coming from the text itself is
/// kept unchanged:
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent(" \t  Foo   ", "->"), "-> \t  Foo   ");
/// ```
pub fn indent(s: &str, prefix: &str) -> String {
    // We know we'll need more than s.len() bytes for the output, but
    // without counting '\n' characters (which is somewhat slow), we
    // don't know exactly how much. However, we can preemptively do
    // the first doubling of the output size.
    let mut result = String::with_capacity(2 * s.len());
    let trimmed_prefix = prefix.trim_end();
    for (idx, line) in s.split_terminator('\n').enumerate() {
        if idx > 0 {
            result.push('\n');
        }
        if line.trim().is_empty() {
            result.push_str(trimmed_prefix);
        } else {
            result.push_str(prefix);
        }
        result.push_str(line);
    }
    if s.ends_with('\n') {
        // split_terminator will have eaten the final '\n'.
        result.push('\n');
    }
    result
}

/// Removes common leading whitespace from each line.
///
/// This function will look at each non-empty line and determine the
/// maximum amount of whitespace that can be removed from all lines:
///
/// ```
/// use textwrap::dedent;
///
/// assert_eq!(dedent("
///     1st line
///       2nd line
///     3rd line
/// "), "
/// 1st line
///   2nd line
/// 3rd line
/// ");
/// ```
pub fn dedent(s: &str) -> String {
    let mut prefix = "";
    let mut lines = s.lines();

    // We first search for a non-empty line to find a prefix.
    for line in &mut lines {
        let mut whitespace_idx = line.len();
        for (idx, ch) in line.char_indices() {
            if !ch.is_whitespace() {
                whitespace_idx = idx;
                break;
            }
        }

        // Check if the line had anything but whitespace
        if whitespace_idx < line.len() {
            prefix = &line[..whitespace_idx];
            break;
        }
    }

    // We then continue looking through the remaining lines to
    // possibly shorten the prefix.
    for line in &mut lines {
        let mut whitespace_idx = line.len();
        for ((idx, a), b) in line.char_indices().zip(prefix.chars()) {
            if a != b {
                whitespace_idx = idx;
                break;
            }
        }

        // Check if the line had anything but whitespace and if we
        // have found a shorter prefix
        if whitespace_idx < line.len() && whitespace_idx < prefix.len() {
            prefix = &line[..whitespace_idx];
        }
    }

    // We now go over the lines a second time to build the result.
    let mut result = String::new();
    for line in s.lines() {
        if line.starts_with(&prefix) && line.chars().any(|c| !c.is_whitespace()) {
            let (_, tail) = line.split_at(prefix.len());
            result.push_str(tail);
        }
        result.push('\n');
    }

    if result.ends_with('\n') && !s.ends_with('\n') {
        let new_len = result.len() - 1;
        result.truncate(new_len);
    }

    result
}

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

    #[test]
    fn indent_empty() {
        assert_eq!(indent("\n", "  "), "\n");
    }

    #[test]
    #[rustfmt::skip]
    fn indent_nonempty() {
        let text = [
            "  foo\n",
            "bar\n",
            "  baz\n",
        ].join("");
        let expected = [
            "//   foo\n",
            "// bar\n",
            "//   baz\n",
        ].join("");
        assert_eq!(indent(&text, "// "), expected);
    }

    #[test]
    #[rustfmt::skip]
    fn indent_empty_line() {
        let text = [
            "  foo",
            "bar",
            "",
            "  baz",
        ].join("\n");
        let expected = [
            "//   foo",
            "// bar",
            "//",
            "//   baz",
        ].join("\n");
        assert_eq!(indent(&text, "// "), expected);
    }

    #[test]
    fn dedent_empty() {
        assert_eq!(dedent(""), "");
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_multi_line() {
        let x = [
            "    foo",
            "  bar",
            "    baz",
        ].join("\n");
        let y = [
            "  foo",
            "bar",
            "  baz"
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_empty_line() {
        let x = [
            "    foo",
            "  bar",
            "   ",
            "    baz"
        ].join("\n");
        let y = [
            "  foo",
            "bar",
            "",
            "  baz"
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_blank_line() {
        let x = [
            "      foo",
            "",
            "        bar",
            "          foo",
            "          bar",
            "          baz",
        ].join("\n");
        let y = [
            "foo",
            "",
            "  bar",
            "    foo",
            "    bar",
            "    baz",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_whitespace_line() {
        let x = [
            "      foo",
            " ",
            "        bar",
            "          foo",
            "          bar",
            "          baz",
        ].join("\n");
        let y = [
            "foo",
            "",
            "  bar",
            "    foo",
            "    bar",
            "    baz",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_mixed_whitespace() {
        let x = [
            "\tfoo",
            "  bar",
        ].join("\n");
        let y = [
            "\tfoo",
            "  bar",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_tabbed_whitespace() {
        let x = [
            "\t\tfoo",
            "\t\t\tbar",
        ].join("\n");
        let y = [
            "foo",
            "\tbar",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_mixed_tabbed_whitespace() {
        let x = [
            "\t  \tfoo",
            "\t  \t\tbar",
        ].join("\n");
        let y = [
            "foo",
            "\tbar",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_mixed_tabbed_whitespace2() {
        let x = [
            "\t  \tfoo",
            "\t    \tbar",
        ].join("\n");
        let y = [
            "\tfoo",
            "  \tbar",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }

    #[test]
    #[rustfmt::skip]
    fn dedent_preserve_no_terminating_newline() {
        let x = [
            "  foo",
            "    bar",
        ].join("\n");
        let y = [
            "foo",
            "  bar",
        ].join("\n");
        assert_eq!(dedent(&x), y);
    }
}
<|endoftext|>


<commit_before>use crate::assist_context::{AssistContext, Assists};
use hir::HirDisplay;
use ide_db::{
    assists::{AssistId, AssistKind},
    defs::NameRefClass,
};
use syntax::{
    ast::{self, edit::IndentLevel},
    AstNode,
};

// Assist: generate_constant
//
// Generate a named constant.
//
// ```
// struct S { i: usize }
// impl S { pub fn new(n: usize) {} }
// fn main() {
//     let v = S::new(CAPA$0CITY);
// }
// ```
// ->
// ```
// struct S { i: usize }
// impl S { pub fn new(n: usize) {} }
// fn main() {
//     const CAPACITY: usize = $0;
//     let v = S::new(CAPACITY);
// }
// ```

pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let constant_token = ctx.find_node_at_offset::<ast::NameRef>()?;
    let expr = constant_token.syntax().ancestors().find_map(ast::Expr::cast)?;
    let statement = expr.syntax().ancestors().find_map(ast::Stmt::cast)?;
    let ty = ctx.sema.type_of_expr(&expr)?;
    let scope = ctx.sema.scope(statement.syntax());
    let module = scope.module()?;
    let type_name = ty.original().display_source_code(ctx.db(), module.into()).ok()?;
    let indent = IndentLevel::from_node(statement.syntax());
    if !arg_list.syntax().text_range().contains_range(constant_token.syntax().text_range()) {
        return None;
    }
    if constant_token.to_string().chars().any(|it| !(it.is_uppercase() || it == '_')) {
        cov_mark::hit!(not_constant_name);
        return None;
    }
    if NameRefClass::classify(&ctx.sema, &constant_token).is_some() {
        cov_mark::hit!(already_defined);
        return None;
    }
    let target = statement.syntax().parent()?.text_range();
    let statement_syntax = statement.syntax().clone_for_update();
    acc.add(
        AssistId("generate_constant", AssistKind::QuickFix),
        "Generate constant",
        target,
        |builder| {
            builder.replace(
                statement.syntax().text_range(),
                format!(
                    "const {}: {} = $0;\n{}{}",
                    constant_token,
                    type_name,
                    indent,
                    statement_syntax.text()
                ),
            );
        },
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::tests::{check_assist, check_assist_not_applicable};

    #[test]
    fn test_trivial() {
        check_assist(
            generate_constant,
            r#"struct S { i: usize }
impl S {
    pub fn new(n: usize) {}
}
fn main() {
    let v = S::new(CAPA$0CITY);
}"#,
            r#"struct S { i: usize }
impl S {
    pub fn new(n: usize) {}
}
fn main() {
    const CAPACITY: usize = $0;
    let v = S::new(CAPACITY);
}"#,
        );
    }
    #[test]
    fn test_wont_apply_when_defined() {
        cov_mark::check!(already_defined);
        check_assist_not_applicable(
            generate_constant,
            r#"struct S { i: usize }
impl S {
    pub fn new(n: usize) {}
}
fn main() {
    const CAPACITY: usize = 10;
    let v = S::new(CAPAC$0ITY);
}"#,
        );
    }
    #[test]
    fn test_wont_apply_when_maybe_not_constant() {
        cov_mark::check!(not_constant_name);
        check_assist_not_applicable(
            generate_constant,
            r#"struct S { i: usize }
impl S {
    pub fn new(n: usize) {}
}
fn main() {
    let v = S::new(capa$0city);
}"#,
        );
    }
}
<commit_msg>Update crates/ide_assists/src/handlers/generate_constant.rs<commit_after>use crate::assist_context::{AssistContext, Assists};
use hir::HirDisplay;
use ide_db::{
    assists::{AssistId, AssistKind},
    defs::NameRefClass,
};
use syntax::{
    ast::{self, edit::IndentLevel},
    AstNode,
};

// Assist: generate_constant
//
// Generate a named constant.
//
// ```
// struct S { i: usize }
// impl S { pub fn new(n: usize) {} }
// fn main() {
//     let v = S::new(CAPA$0CITY);
// }
// ```
// ->
// ```
// struct S { i: usize }
// impl S { pub fn new(n: usize) {} }
// fn main() {
//     const CAPACITY: usize = $0;
//     let v = S::new(CAPACITY);
// }
// ```

pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let constant_token = ctx.find_node_at_offset::<ast::NameRef>()?;
    let expr = constant_token.syntax().ancestors().find_map(ast::Expr::cast)?;
    let statement = expr.syntax().ancestors().find_map(ast::Stmt::cast)?;
    let ty = ctx.sema.type_of_expr(&expr)?;
    let scope = ctx.sema.scope(statement.syntax());
    let module = scope.module()?;
    let type_name = ty.original().display_source_code(ctx.db(), module.into()).ok()?;
    let indent = IndentLevel::from_node(statement.syntax());
    if !arg_list.syntax().text_range().contains_range(constant_token.syntax().text_range()) {
        return None;
    }
    if constant_token.to_string().chars().any(|it| !(it.is_uppercase() || it == '_')) {
        cov_mark::hit!(not_constant_name);
        return None;
    }
    if NameRefClass::classify(&ctx.sema, &constant_token).is_some() {
        cov_mark::hit!(already_defined);
        return None;
    }
    let target = statement.syntax().parent()?.text_range();
    let statement_syntax = statement.syntax().clone_for_update();
    acc.add(
        AssistId("generate_constant", AssistKind::QuickFix),
        "Generate constant",
        target,
        |builder| {
            builder.insert(
                statement.syntax().text_range.start(),
                format!(
                    "const {}: {} = $0;\n{}",
                    constant_token,
                    type_name,
                    indent
                ),
            );
        },
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::tests::{check_assist, check_assist_not_applicable};

    #[test]
    fn test_trivial() {
        check_assist(
            generate_constant,
            r#"struct S { i: usize }
impl S {
    pub fn new(n: usize) {}
}
fn main() {
    let v = S::new(CAPA$0CITY);
}"#,
            r#"struct S { i: usize }
impl S {
    pub fn new(n: usize) {}
}
fn main() {
    const CAPACITY: usize = $0;
    let v = S::new(CAPACITY);
}"#,
        );
    }
    #[test]
    fn test_wont_apply_when_defined() {
        cov_mark::check!(already_defined);
        check_assist_not_applicable(
            generate_constant,
            r#"struct S { i: usize }
impl S {
    pub fn new(n: usize) {}
}
fn main() {
    const CAPACITY: usize = 10;
    let v = S::new(CAPAC$0ITY);
}"#,
        );
    }
    #[test]
    fn test_wont_apply_when_maybe_not_constant() {
        cov_mark::check!(not_constant_name);
        check_assist_not_applicable(
            generate_constant,
            r#"struct S { i: usize }
impl S {
    pub fn new(n: usize) {}
}
fn main() {
    let v = S::new(capa$0city);
}"#,
        );
    }
}
<|endoftext|>


<commit_before>use super::plumbing::*;
use super::*;

use std::iter;

/// `Copied` is an iterator that copies the elements of an underlying iterator.
///
/// This struct is created by the [`copied()`] method on [`ParallelIterator`]
///
/// [`copied()`]: trait.ParallelIterator.html#method.copied
/// [`ParallelIterator`]: trait.ParallelIterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug, Clone)]
pub struct Copied {
    base: I,
}

impl Copied
where
    I: ParallelIterator,
{
    /// Create a new `Copied` iterator.
    pub(super) fn new(base: I) -> Self {
        Copied { base }
    }
}

impl<'a, T, I> ParallelIterator for Copied
where
    I: ParallelIterator<Item = &'a T>,
    T: 'a + Copy + Send + Sync,
{
    type Item = T;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
    where
        C: UnindexedConsumer<Self::Item>,
    {
        let consumer1 = CopiedConsumer::new(consumer);
        self.base.drive_unindexed(consumer1)
    }

    fn opt_len(&self) -> Option<usize> {
        self.base.opt_len()
    }
}

impl<'a, T, I> IndexedParallelIterator for Copied
where
    I: IndexedParallelIterator<Item = &'a T>,
    T: 'a + Copy + Send + Sync,
{
    fn drive<C>(self, consumer: C) -> C::Result
    where
        C: Consumer<Self::Item>,
    {
        let consumer1 = CopiedConsumer::new(consumer);
        self.base.drive(consumer1)
    }

    fn len(&self) -> usize {
        self.base.len()
    }

    fn with_producer<CB>(self, callback: CB) -> CB::Output
    where
        CB: ProducerCallback<Self::Item>,
    {
        return self.base.with_producer(Callback { callback });

        struct Callback<CB> {
            callback: CB,
        }

        impl<'a, T, CB> ProducerCallback<&'a T> for Callback<CB>
        where
            CB: ProducerCallback<T>,
            T: 'a + Copy + Send,
        {
            type Output = CB::Output;

            fn callback
(self, base: P) -> CB::Output
            where
                P: Producer<Item = &'a T>,
            {
                let producer = CopiedProducer { base };
                self.callback.callback(producer)
            }
        }
    }
}

/// ////////////////////////////////////////////////////////////////////////

struct CopiedProducer
 {
    base: P,
}

impl<'a, T, P> Producer for CopiedProducer

where
    P: Producer<Item = &'a T>,
    T: 'a + Copy,
{
    type Item = T;
    type IntoIter = iter::Map
 T>;

    fn into_iter(self) -> Self::IntoIter {
        // FIXME: use `Iterator::copied()` when Rust 1.36 is our minimum.
        self.base.into_iter().map(|&x| x)
    }

    fn min_len(&self) -> usize {
        self.base.min_len()
    }

    fn max_len(&self) -> usize {
        self.base.max_len()
    }

    fn split_at(self, index: usize) -> (Self, Self) {
        let (left, right) = self.base.split_at(index);
        (
            CopiedProducer { base: left },
            CopiedProducer { base: right },
        )
    }

    fn fold_with<F>(self, folder: F) -> F
    where
        F: Folder<Self::Item>,
    {
        self.base.fold_with(CopiedFolder { base: folder }).base
    }
}

/// ////////////////////////////////////////////////////////////////////////
/// Consumer implementation

struct CopiedConsumer<C> {
    base: C,
}

impl<C> CopiedConsumer<C> {
    fn new(base: C) -> Self {
        CopiedConsumer { base }
    }
}

impl<'a, T, C> Consumer<&'a T> for CopiedConsumer<C>
where
    C: Consumer<T>,
    T: 'a + Copy,
{
    type Folder = CopiedFolder<C::Folder>;
    type Reducer = C::Reducer;
    type Result = C::Result;

    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
        let (left, right, reducer) = self.base.split_at(index);
        (
            CopiedConsumer::new(left),
            CopiedConsumer::new(right),
            reducer,
        )
    }

    fn into_folder(self) -> Self::Folder {
        CopiedFolder {
            base: self.base.into_folder(),
        }
    }

    fn full(&self) -> bool {
        self.base.full()
    }
}

impl<'a, T, C> UnindexedConsumer<&'a T> for CopiedConsumer<C>
where
    C: UnindexedConsumer<T>,
    T: 'a + Copy,
{
    fn split_off_left(&self) -> Self {
        CopiedConsumer::new(self.base.split_off_left())
    }

    fn to_reducer(&self) -> Self::Reducer {
        self.base.to_reducer()
    }
}

struct CopiedFolder<F> {
    base: F,
}

impl<'a, T, F> Folder<&'a T> for CopiedFolder<F>
where
    F: Folder<T>,
    T: 'a + Copy,
{
    type Result = F::Result;

    fn consume(self, &item: &'a T) -> Self {
        CopiedFolder {
            base: self.base.consume(item),
        }
    }

    fn consume_iter(mut self, iter: I) -> Self
    where
        I: IntoIterator<Item = &'a T>,
    {
        // FIXME: use `Iterator::copied()` when Rust 1.36 is our minimum.
        self.base = self.base.consume_iter(iter.into_iter().map(|&x| x));
        self
    }

    fn complete(self) -> F::Result {
        self.base.complete()
    }

    fn full(&self) -> bool {
        self.base.full()
    }
}
<commit_msg>Avoid closures in the Copied implementation<commit_after>use super::plumbing::*;
use super::*;

use std::iter;

/// `Copied` is an iterator that copies the elements of an underlying iterator.
///
/// This struct is created by the [`copied()`] method on [`ParallelIterator`]
///
/// [`copied()`]: trait.ParallelIterator.html#method.copied
/// [`ParallelIterator`]: trait.ParallelIterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug, Clone)]
pub struct Copied {
    base: I,
}

impl Copied
where
    I: ParallelIterator,
{
    /// Create a new `Copied` iterator.
    pub(super) fn new(base: I) -> Self {
        Copied { base }
    }
}

impl<'a, T, I> ParallelIterator for Copied
where
    I: ParallelIterator<Item = &'a T>,
    T: 'a + Copy + Send + Sync,
{
    type Item = T;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
    where
        C: UnindexedConsumer<Self::Item>,
    {
        let consumer1 = CopiedConsumer::new(consumer);
        self.base.drive_unindexed(consumer1)
    }

    fn opt_len(&self) -> Option<usize> {
        self.base.opt_len()
    }
}

impl<'a, T, I> IndexedParallelIterator for Copied
where
    I: IndexedParallelIterator<Item = &'a T>,
    T: 'a + Copy + Send + Sync,
{
    fn drive<C>(self, consumer: C) -> C::Result
    where
        C: Consumer<Self::Item>,
    {
        let consumer1 = CopiedConsumer::new(consumer);
        self.base.drive(consumer1)
    }

    fn len(&self) -> usize {
        self.base.len()
    }

    fn with_producer<CB>(self, callback: CB) -> CB::Output
    where
        CB: ProducerCallback<Self::Item>,
    {
        return self.base.with_producer(Callback { callback });

        struct Callback<CB> {
            callback: CB,
        }

        impl<'a, T, CB> ProducerCallback<&'a T> for Callback<CB>
        where
            CB: ProducerCallback<T>,
            T: 'a + Copy + Send,
        {
            type Output = CB::Output;

            fn callback
(self, base: P) -> CB::Output
            where
                P: Producer<Item = &'a T>,
            {
                let producer = CopiedProducer { base };
                self.callback.callback(producer)
            }
        }
    }
}

/// ////////////////////////////////////////////////////////////////////////

struct CopiedProducer
 {
    base: P,
}

impl<'a, T, P> Producer for CopiedProducer

where
    P: Producer<Item = &'a T>,
    T: 'a + Copy,
{
    type Item = T;
    type IntoIter = iter::Cloned
;

    fn into_iter(self) -> Self::IntoIter {
        // FIXME: use `Iterator::copied()` when Rust 1.36 is our minimum.
        self.base.into_iter().cloned()
    }

    fn min_len(&self) -> usize {
        self.base.min_len()
    }

    fn max_len(&self) -> usize {
        self.base.max_len()
    }

    fn split_at(self, index: usize) -> (Self, Self) {
        let (left, right) = self.base.split_at(index);
        (
            CopiedProducer { base: left },
            CopiedProducer { base: right },
        )
    }

    fn fold_with<F>(self, folder: F) -> F
    where
        F: Folder<Self::Item>,
    {
        self.base.fold_with(CopiedFolder { base: folder }).base
    }
}

/// ////////////////////////////////////////////////////////////////////////
/// Consumer implementation

struct CopiedConsumer<C> {
    base: C,
}

impl<C> CopiedConsumer<C> {
    fn new(base: C) -> Self {
        CopiedConsumer { base }
    }
}

impl<'a, T, C> Consumer<&'a T> for CopiedConsumer<C>
where
    C: Consumer<T>,
    T: 'a + Copy,
{
    type Folder = CopiedFolder<C::Folder>;
    type Reducer = C::Reducer;
    type Result = C::Result;

    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
        let (left, right, reducer) = self.base.split_at(index);
        (
            CopiedConsumer::new(left),
            CopiedConsumer::new(right),
            reducer,
        )
    }

    fn into_folder(self) -> Self::Folder {
        CopiedFolder {
            base: self.base.into_folder(),
        }
    }

    fn full(&self) -> bool {
        self.base.full()
    }
}

impl<'a, T, C> UnindexedConsumer<&'a T> for CopiedConsumer<C>
where
    C: UnindexedConsumer<T>,
    T: 'a + Copy,
{
    fn split_off_left(&self) -> Self {
        CopiedConsumer::new(self.base.split_off_left())
    }

    fn to_reducer(&self) -> Self::Reducer {
        self.base.to_reducer()
    }
}

struct CopiedFolder<F> {
    base: F,
}

impl<'a, T, F> Folder<&'a T> for CopiedFolder<F>
where
    F: Folder<T>,
    T: 'a + Copy,
{
    type Result = F::Result;

    fn consume(self, &item: &'a T) -> Self {
        CopiedFolder {
            base: self.base.consume(item),
        }
    }

    fn consume_iter(mut self, iter: I) -> Self
    where
        I: IntoIterator<Item = &'a T>,
    {
        // FIXME: use `Iterator::copied()` when Rust 1.36 is our minimum.
        self.base = self.base.consume_iter(iter.into_iter().cloned());
        self
    }

    fn complete(self) -> F::Result {
        self.base.complete()
    }

    fn full(&self) -> bool {
        self.base.full()
    }
}
<|endoftext|>


<commit_before>// The elements of an array can be accessed by their indices
// arr[4]
#[test]
fn array_index() {
  let arr: [i32; 5] = [1, 2, 3, 4, 5];
  assert!(arr[__] == 1);
}

// A new fixed size array can be created by declaring the type of its elements
// along with its length
// [i32; 0] = []
#[test]
fn array_empty() {
  let arr: __;
  assert!(arr.len() == 0);
}

// Attempting to access an array at an index that is
// out of its bounds will cause an error. Let's cause
// that error in this example.
#[test]
#[should_panic]
fn out_of_index() {
  let arr: [&'static str; 5] = ["rust", "is", "mostly", "for", "nerds"];
  arr[__];
}

// Elements can be replaced in an array at a certain index.
// hint: Without the 'mut' keyword, you won't be able to change data.
#[test]
fn insert_at_index() {
  let mut arr: [u8; 5] = [0, 1, 2, 3, 4];
  __ = 0;
  assert!(arr == [0, 1, 2, 3, 0]);
}
<commit_msg>Add iterator koans to array.rs<commit_after>// The elements of an array can be accessed by their indices
// arr[4]
#[test]
fn array_index() {
  let arr: [i32; 5] = [1, 2, 3, 4, 5];
  assert!(arr[__] == 1);
}

// A new fixed size array can be created by declaring the type of its elements
// along with its length
// [i32; 0] = []
#[test]
fn array_empty() {
  let arr: __;
  assert!(arr.len() == 0);
}

// Attempting to access an array at an index that is
// out of its bounds will cause an error. Let's cause
// that error in this example.
#[test]
#[should_panic]
fn out_of_index() {
  let arr: [&'static str; 5] = ["rust", "is", "mostly", "for", "nerds"];
  arr[__];
}

// Elements can be replaced in an array at a certain index.
// hint: Without the 'mut' keyword, you won't be able to change data.
#[test]
fn insert_at_index() {
  let mut arr: [u8; 5] = [0, 1, 2, 3, 4];
  __ = 0;
  assert!(arr == [0, 1, 2, 3, 0]);
}

// Arrays can be iterated over.
#[test]
fn array_iteration() {
  let arr: [u8; 3] = [3, 2, 1];
  let mut iterator = arr.iter();
  assert!(iterator.next().unwrap() == &__);
  assert!(iterator.next().unwrap() == &__);
  assert!(iterator.next().unwrap() == &__);
}

// Arrays can also be mutated during iteration
#[test]
fn array_map() {
  let arr: [u32; 4] = [2, 5, 7, 4];
  let mut iterator = arr.iter().map(__);
  assert!(iterator.next() == Some(4));
  assert!(iterator.next() == Some(10));
  assert!(iterator.next() == Some(14));
  assert!(iterator.next() == Some(8));
}

// You can filter an array for results that match a given condition
#[test]
fn array_filter() {
  let arr: [u16; 5] = [1, 2, 3, 4, 5];
  let mut iterator = arr.iter().filter(__);
  assert!(iterator.next().unwrap() == &2);
  assert!(iterator.next().unwrap() == &4);
  assert!(iterator.next().is_none());
}

// Filter and map can be combined to do both at once
#[test]
fn array_filter_map() {
  let arr: [u8; 5] = [2, 1, 2, 1, 2];
  let mut iterator = arr.iter().filter_map(|&x|
    if x == 1 {Some(__)} else {None}
  );
  assert!(iterator.next() == Some(3));
  assert!(iterator.next() == Some(3));
  assert!(iterator.next().is_none());
}

// This can be used for more complex logic as well
#[test]
fn complex_array_filter_map() {
  let arr: [u64; 4] = [4, 8, 16, 32];
  let mut iterator = arr.iter().filter_map(|&x|
    if (x as f64).sqrt().floor() == (x as f64).sqrt() {Some((x as f64).sqrt() as u64)} else {None}
  );
  assert!(iterator.next().unwrap() == __);
  assert!(iterator.next().unwrap() == __);
  assert!(iterator.next().is_none());
}
<|endoftext|>