<commit_before>use parking_lot::{Condvar, Mutex};
use std::cell::RefCell;
use std::convert::From;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;

use crate::gc::{tlab, Address, Region, K};
use crate::handle::HandleMemory;
use crate::stack::DoraToNativeInfo;
use crate::vm::{get_vm, VM};

pub const STACK_SIZE: usize = 500 * K;

thread_local! {
    pub static THREAD: RefCell<Arc<DoraThread>> = RefCell::new(DoraThread::main());
}

pub struct Threads {
    pub threads: Mutex<Vec<Arc<DoraThread>>>,
    pub cond_join: Condvar,

    pub next_id: AtomicUsize,
    pub safepoint: Mutex<(usize, usize)>,

    pub barrier: Barrier,
}

impl Threads {
    pub fn new() -> Threads {
        Threads {
            threads: Mutex::new(Vec::new()),
            cond_join: Condvar::new(),
            next_id: AtomicUsize::new(1),
            safepoint: Mutex::new((0, 1)),
            barrier: Barrier::new(),
        }
    }

    pub fn attach_current_thread(&self) {
        THREAD.with(|thread| {
            let mut threads = self.threads.lock();
            threads.push(thread.borrow().clone());
        });
    }

    pub fn attach_thread(&self, vm: &VM, thread: Arc<DoraThread>) {
        THREAD.with(|current_thread| {
            current_thread.borrow().park(vm);

            {
                let mut threads = self.threads.lock();
                threads.push(thread);
            }

            current_thread.borrow().unpark(vm);
        });
    }

    pub fn next_id(&self) -> usize {
        self.next_id.fetch_add(1, Ordering::SeqCst)
    }

    pub fn safepoint_id(&self) -> usize {
        let safepoint = self.safepoint.lock();
        safepoint.0
    }

    pub fn safepoint_requested(&self) -> bool {
        let safepoint = self.safepoint.lock();
        safepoint.0 != 0
    }

    pub fn request_safepoint(&self) -> usize {
        let mut safepoint = self.safepoint.lock();
        assert_eq!(safepoint.0, 0);
        safepoint.0 = safepoint.1;
        safepoint.1 += 1;

        safepoint.0
    }

    pub fn clear_safepoint_request(&self) {
        let mut safepoint = self.safepoint.lock();
        assert_ne!(safepoint.0, 0);
        safepoint.0 = 0;
    }

    pub fn detach_current_thread(&self) {
        let vm = get_vm();

        // Other threads might still be running and perform a GC.
        // Fill the TLAB for them.
        tlab::make_iterable_current(vm);

        THREAD.with(|thread| {
            thread.borrow().park(vm);
            let mut threads = self.threads.lock();
            threads.retain(|elem| !Arc::ptr_eq(elem, &*thread.borrow()));
            self.cond_join.notify_all();
        });
    }

    pub fn join_all(&self) {
        let mut threads = self.threads.lock();

        while threads.len() > 0 {
            self.cond_join.wait(&mut threads);
        }
    }

    pub fn each<F>(&self, mut f: F)
    where
        F: FnMut(&Arc<DoraThread>),
    {
        let threads = self.threads.lock();

        for thread in threads.iter() {
            f(thread)
        }
    }
}

pub struct DoraThread {
    pub id: AtomicUsize,
    pub handles: HandleMemory,
    pub tld: ThreadLocalData,
    pub saved_pc: AtomicUsize,
    pub saved_fp: AtomicUsize,
    pub state: StateManager,
    pub atomic_state: AtomicUsize,
}

unsafe impl Sync for DoraThread {}
unsafe impl Send for DoraThread {}

impl DoraThread {
    pub fn new(vm: &VM) -> Arc<DoraThread> {
        DoraThread::with_id(vm.threads.next_id(), ThreadState::Parked)
    }

    pub fn main() -> Arc<DoraThread> {
        DoraThread::with_id(0, ThreadState::Running)
    }

    fn with_id(id: usize, initial_state: ThreadState) -> Arc<DoraThread> {
        Arc::new(DoraThread {
            id: AtomicUsize::new(id),
            handles: HandleMemory::new(),
            tld: ThreadLocalData::new(),
            saved_pc: AtomicUsize::new(0),
            saved_fp: AtomicUsize::new(0),
            state: StateManager::new(initial_state),
            atomic_state: AtomicUsize::new(initial_state as usize),
        })
    }

    pub fn id(&self) -> usize {
        self.id.load(Ordering::Relaxed)
    }

    pub fn dtn(&self) -> *const DoraToNativeInfo {
        self.tld.dtn.load(Ordering::Relaxed) as *const _
    }

    pub fn set_dtn(&self, ptr: *const DoraToNativeInfo) {
        self.tld.dtn.store(ptr as usize, Ordering::Relaxed);
    }

    pub fn use_dtn<F, R>(&self, dtn: &mut DoraToNativeInfo, fct: F) -> R
    where
        F: FnOnce() -> R,
    {
        dtn.last = self.dtn();

        self.set_dtn(dtn as *const _);

        let ret = fct();

        self.set_dtn(dtn.last);

        ret
    }

    pub fn push_dtn(&self, dtn: &mut DoraToNativeInfo) {
        dtn.last = self.dtn();
        self.set_dtn(dtn as *const _);
    }

    pub fn pop_dtn(&self) {
        let current_dtn = self.dtn();
        assert!(!current_dtn.is_null());
        let dtn = unsafe { &*current_dtn };
        self.set_dtn(dtn.last);
    }

    pub fn state(&self) -> ThreadState {
        self.state.state()
    }

    pub fn state_relaxed(&self) -> ThreadState {
        self.atomic_state.load(Ordering::Relaxed).into()
    }

    pub fn park(&self, vm: &VM) {
        if self
            .atomic_state
            .compare_exchange(
                ThreadState::Running as usize,
                ThreadState::Parked as usize,
                Ordering::SeqCst,
                Ordering::SeqCst,
            )
            .is_err()
        {
            self.park_slow(vm);
        }
    }

    pub fn park_slow(&self, vm: &VM) {
        assert!(self
            .atomic_state
            .compare_exchange(
                ThreadState::RequestedSafepoint as usize,
                ThreadState::ParkedSafepoint as usize,
                Ordering::SeqCst,
                Ordering::SeqCst,
            )
            .is_ok());
        vm.threads.barrier.notify_park();
    }

    pub fn unpark(&self, vm: &VM) {
        if self
            .atomic_state
            .compare_exchange(
                ThreadState::Parked as usize,
                ThreadState::Running as usize,
                Ordering::SeqCst,
                Ordering::SeqCst,
            )
            .is_err()
        {
            self.unpark_slow(vm);
        }
    }

    pub fn unpark_slow(&self, vm: &VM) {
        loop {
            match self.atomic_state.compare_exchange(
                ThreadState::Parked as usize,
                ThreadState::Running as usize,
                Ordering::SeqCst,
                Ordering::SeqCst,
            ) {
                Ok(_) => break,
                Err(state) => {
                    assert_eq!(state, ThreadState::ParkedSafepoint as usize);
                    vm.threads.barrier.wait_in_unpark();
                }
            }
        }
    }
}

pub struct StateManager {
    mtx: Mutex<(ThreadState, usize)>,
}

impl StateManager {
    fn new(initial_state: ThreadState) -> StateManager {
        StateManager {
            mtx: Mutex::new((initial_state, 0)),
        }
    }

    fn state(&self) -> ThreadState {
        let mtx = self.mtx.lock();
        mtx.0
    }

    fn park(&self, _vm: &VM) {
        let mut mtx = self.mtx.lock();
        assert!(mtx.0.is_running());
        mtx.0 = ThreadState::Parked;
    }

    fn unpark(&self, _vm: &VM) {
        let mut mtx = self.mtx.lock();
        assert!(mtx.0.is_parked());
        mtx.0 = ThreadState::Running;
    }

    fn block(&self, safepoint_id: usize) {
        let mut mtx = self.mtx.lock();
        assert!(mtx.0.is_running());
        mtx.0 = ThreadState::Blocked;
        mtx.1 = safepoint_id;
    }

    fn unblock(&self) {
        let mut mtx = self.mtx.lock();
        assert!(mtx.0.is_blocked());
        mtx.0 = ThreadState::Running;
        mtx.1 = 0;
    }

    fn in_safepoint(&self, safepoint_id: usize) -> bool {
        assert_ne!(safepoint_id, 0);
        let mtx = self.mtx.lock();

        match mtx.0 {
            ThreadState::Running => false,
            ThreadState::Blocked => mtx.1 == safepoint_id,
            ThreadState::Parked => true,
            ThreadState::RequestedSafepoint
            | ThreadState::ParkedSafepoint
            | ThreadState::Safepoint => unreachable!(),
        }
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ThreadState {
    Running = 0,
    Parked = 1,
    Blocked = 2,
    RequestedSafepoint = 3,
    ParkedSafepoint = 4,
    Safepoint = 5,
}

impl From<usize> for ThreadState {
    fn from(value: usize) -> ThreadState {
        match value {
            0 => ThreadState::Running,
            1 => ThreadState::Parked,
            2 => ThreadState::Blocked,
            3 => ThreadState::RequestedSafepoint,
            4 => ThreadState::ParkedSafepoint,
            5 => ThreadState::Safepoint,
            _ => unreachable!(),
        }
    }
}

impl ThreadState {
    pub fn is_running(&self) -> bool {
        match *self {
            ThreadState::Running => true,
            _ => false,
        }
    }

    pub fn is_parked(&self) -> bool {
        match *self {
            ThreadState::Parked => true,
            _ => false,
        }
    }

    pub fn is_blocked(&self) -> bool {
        match *self {
            ThreadState::Blocked => true,
            _ => false,
        }
    }

    pub fn to_usize(&self) -> usize {
        *self as usize
    }
}

impl Default for ThreadState {
    fn default() -> ThreadState {
        ThreadState::Running
    }
}

pub struct ThreadLocalData {
    tlab_top: AtomicUsize,
    tlab_end: AtomicUsize,
    concurrent_marking: AtomicBool,
    stack_limit: AtomicUsize,
    safepoint_requested: AtomicBool,
    dtn: AtomicUsize,
}

impl ThreadLocalData {
    pub fn new() -> ThreadLocalData {
        ThreadLocalData {
            tlab_top: AtomicUsize::new(0),
            tlab_end: AtomicUsize::new(0),
            concurrent_marking: AtomicBool::new(false),
            stack_limit: AtomicUsize::new(0),
            safepoint_requested: AtomicBool::new(false),
            dtn: AtomicUsize::new(0),
        }
    }

    pub fn tlab_initialize(&self, start: Address, end: Address) {
        assert!(start <= end);

        self.tlab_top.store(start.to_usize(), Ordering::Relaxed);
        self.tlab_end.store(end.to_usize(), Ordering::Relaxed);
    }

    pub fn tlab_rest(&self) -> usize {
        let tlab_top = self.tlab_top.load(Ordering::Relaxed);
        let tlab_end = self.tlab_end.load(Ordering::Relaxed);

        tlab_end - tlab_top
    }

    pub fn tlab_region(&self) -> Region {
        let tlab_top = self.tlab_top.load(Ordering::Relaxed);
        let tlab_end = self.tlab_end.load(Ordering::Relaxed);

        Region::new(tlab_top.into(), tlab_end.into())
    }

    pub fn set_stack_limit(&self, stack_limit: Address) {
        self.stack_limit
            .store(stack_limit.to_usize(), Ordering::Relaxed);
    }

    pub fn tlab_top_offset() -> i32 {
        offset_of!(ThreadLocalData, tlab_top) as i32
    }

    pub fn tlab_end_offset() -> i32 {
        offset_of!(ThreadLocalData, tlab_end) as i32
    }

    pub fn concurrent_marking_offset() -> i32 {
        offset_of!(ThreadLocalData, concurrent_marking) as i32
    }

    pub fn safepoint_requested_offset() -> i32 {
        offset_of!(ThreadLocalData, safepoint_requested) as i32
    }

    pub fn stack_limit(&self) -> Address {
        Address::from(self.stack_limit.load(Ordering::Relaxed))
    }

    pub fn stack_limit_offset() -> i32 {
        offset_of!(ThreadLocalData, stack_limit) as i32
    }

    pub fn dtn_offset() -> i32 {
        offset_of!(ThreadLocalData, dtn) as i32
    }

    pub fn set_safepoint_requested(&self) {
        self.safepoint_requested.store(true, Ordering::Relaxed);
    }

    pub fn clear_safepoint_requested(&self) {
        self.safepoint_requested.store(false, Ordering::Relaxed);
    }
}

pub struct Barrier {
    data: Mutex<BarrierData>,
    cv_wakeup: Condvar,
    cv_notify: Condvar,
}

impl Barrier {
    pub fn new() -> Barrier {
        Barrier {
            data: Mutex::new(BarrierData::new()),
            cv_wakeup: Condvar::new(),
            cv_notify: Condvar::new(),
        }
    }

    pub fn arm(&self) {
        let mut data = self.data.lock();
        assert!(!data.is_armed());
        data.arm();
    }

    pub fn disarm(&self) {
        let mut data = self.data.lock();
        assert!(data.is_armed());
        data.disarm();
        self.cv_wakeup.notify_all();
    }

    pub fn notify_park(&self) {
        let mut data = self.data.lock();
        assert!(data.is_armed());
        data.stopped += 1;
        self.cv_notify.notify_one();
    }

    pub fn wait_in_safepoint(&self) {
        let mut data = self.data.lock();
        assert!(data.is_armed());
        data.stopped += 1;
        self.cv_notify.notify_one();
        let safepoint = data.armed;

        while data.armed == safepoint {
            self.cv_wakeup.wait(&mut data);
        }
    }

    pub fn wait_in_unpark(&self) {
        let mut data = self.data.lock();
        assert!(data.is_armed());

        while data.is_armed() {
            self.cv_wakeup.wait(&mut data);
        }
    }

    pub fn wait_until_threads_stopped(&self, threads: usize) {
        let mut data = self.data.lock();
        assert!(data.is_armed());
        while data.stopped < threads {
            self.cv_notify.wait(&mut data);
        }
        assert_eq!(data.stopped, threads);
    }
}

struct BarrierData {
    armed: usize,
    next: usize,
    stopped: usize,
}

impl BarrierData {
    pub fn new() -> BarrierData {
        BarrierData {
            armed: 0,
            next: 1,
            stopped: 0,
        }
    }

    pub fn is_armed(&self) -> bool {
        self.armed != 0
    }

    pub fn arm(&mut self) {
        self.stopped = 0;
        self.armed = self.next;

        if self.next == usize::max_value() {
            self.next = 1;
        } else {
            self.next += 1;
        }
    }

    pub fn disarm(&mut self) {
        self.armed = 0;
    }
}
<commit_msg>safepointing: wait_in_unpark might not be armed<commit_after>use parking_lot::{Condvar, Mutex};
use std::cell::RefCell;
use std::convert::From;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;

use crate::gc::{tlab, Address, Region, K};
use crate::handle::HandleMemory;
use crate::stack::DoraToNativeInfo;
use crate::vm::{get_vm, VM};

pub const STACK_SIZE: usize = 500 * K;

thread_local! {
    pub static THREAD: RefCell<Arc<DoraThread>> = RefCell::new(DoraThread::main());
}

pub struct Threads {
    pub threads: Mutex<Vec<Arc<DoraThread>>>,
    pub cond_join: Condvar,

    pub next_id: AtomicUsize,
    pub safepoint: Mutex<(usize, usize)>,

    pub barrier: Barrier,
}

impl Threads {
    pub fn new() -> Threads {
        Threads {
            threads: Mutex::new(Vec::new()),
            cond_join: Condvar::new(),
            next_id: AtomicUsize::new(1),
            safepoint: Mutex::new((0, 1)),
            barrier: Barrier::new(),
        }
    }

    pub fn attach_current_thread(&self) {
        THREAD.with(|thread| {
            let mut threads = self.threads.lock();
            threads.push(thread.borrow().clone());
        });
    }

    pub fn attach_thread(&self, vm: &VM, thread: Arc<DoraThread>) {
        THREAD.with(|current_thread| {
            current_thread.borrow().park(vm);

            {
                let mut threads = self.threads.lock();
                threads.push(thread);
            }

            current_thread.borrow().unpark(vm);
        });
    }

    pub fn next_id(&self) -> usize {
        self.next_id.fetch_add(1, Ordering::SeqCst)
    }

    pub fn safepoint_id(&self) -> usize {
        let safepoint = self.safepoint.lock();
        safepoint.0
    }

    pub fn safepoint_requested(&self) -> bool {
        let safepoint = self.safepoint.lock();
        safepoint.0 != 0
    }

    pub fn request_safepoint(&self) -> usize {
        let mut safepoint = self.safepoint.lock();
        assert_eq!(safepoint.0, 0);
        safepoint.0 = safepoint.1;
        safepoint.1 += 1;

        safepoint.0
    }

    pub fn clear_safepoint_request(&self) {
        let mut safepoint = self.safepoint.lock();
        assert_ne!(safepoint.0, 0);
        safepoint.0 = 0;
    }

    pub fn detach_current_thread(&self) {
        let vm = get_vm();

        // Other threads might still be running and perform a GC.
        // Fill the TLAB for them.
        tlab::make_iterable_current(vm);

        THREAD.with(|thread| {
            thread.borrow().park(vm);
            let mut threads = self.threads.lock();
            threads.retain(|elem| !Arc::ptr_eq(elem, &*thread.borrow()));
            self.cond_join.notify_all();
        });
    }

    pub fn join_all(&self) {
        let mut threads = self.threads.lock();

        while threads.len() > 0 {
            self.cond_join.wait(&mut threads);
        }
    }

    pub fn each<F>(&self, mut f: F)
    where
        F: FnMut(&Arc<DoraThread>),
    {
        let threads = self.threads.lock();

        for thread in threads.iter() {
            f(thread)
        }
    }
}

pub struct DoraThread {
    pub id: AtomicUsize,
    pub handles: HandleMemory,
    pub tld: ThreadLocalData,
    pub saved_pc: AtomicUsize,
    pub saved_fp: AtomicUsize,
    pub state: StateManager,
    pub atomic_state: AtomicUsize,
}

unsafe impl Sync for DoraThread {}
unsafe impl Send for DoraThread {}

impl DoraThread {
    pub fn new(vm: &VM) -> Arc<DoraThread> {
        DoraThread::with_id(vm.threads.next_id(), ThreadState::Parked)
    }

    pub fn main() -> Arc<DoraThread> {
        DoraThread::with_id(0, ThreadState::Running)
    }

    fn with_id(id: usize, initial_state: ThreadState) -> Arc<DoraThread> {
        Arc::new(DoraThread {
            id: AtomicUsize::new(id),
            handles: HandleMemory::new(),
            tld: ThreadLocalData::new(),
            saved_pc: AtomicUsize::new(0),
            saved_fp: AtomicUsize::new(0),
            state: StateManager::new(initial_state),
            atomic_state: AtomicUsize::new(initial_state as usize),
        })
    }

    pub fn id(&self) -> usize {
        self.id.load(Ordering::Relaxed)
    }

    pub fn dtn(&self) -> *const DoraToNativeInfo {
        self.tld.dtn.load(Ordering::Relaxed) as *const _
    }

    pub fn set_dtn(&self, ptr: *const DoraToNativeInfo) {
        self.tld.dtn.store(ptr as usize, Ordering::Relaxed);
    }

    pub fn use_dtn<F, R>(&self, dtn: &mut DoraToNativeInfo, fct: F) -> R
    where
        F: FnOnce() -> R,
    {
        dtn.last = self.dtn();

        self.set_dtn(dtn as *const _);

        let ret = fct();

        self.set_dtn(dtn.last);

        ret
    }

    pub fn push_dtn(&self, dtn: &mut DoraToNativeInfo) {
        dtn.last = self.dtn();
        self.set_dtn(dtn as *const _);
    }

    pub fn pop_dtn(&self) {
        let current_dtn = self.dtn();
        assert!(!current_dtn.is_null());
        let dtn = unsafe { &*current_dtn };
        self.set_dtn(dtn.last);
    }

    pub fn state(&self) -> ThreadState {
        self.state.state()
    }

    pub fn state_relaxed(&self) -> ThreadState {
        self.atomic_state.load(Ordering::Relaxed).into()
    }

    pub fn park(&self, vm: &VM) {
        if self
            .atomic_state
            .compare_exchange(
                ThreadState::Running as usize,
                ThreadState::Parked as usize,
                Ordering::SeqCst,
                Ordering::SeqCst,
            )
            .is_err()
        {
            self.park_slow(vm);
        }
    }

    pub fn park_slow(&self, vm: &VM) {
        assert!(self
            .atomic_state
            .compare_exchange(
                ThreadState::RequestedSafepoint as usize,
                ThreadState::ParkedSafepoint as usize,
                Ordering::SeqCst,
                Ordering::SeqCst,
            )
            .is_ok());
        vm.threads.barrier.notify_park();
    }

    pub fn unpark(&self, vm: &VM) {
        if self
            .atomic_state
            .compare_exchange(
                ThreadState::Parked as usize,
                ThreadState::Running as usize,
                Ordering::SeqCst,
                Ordering::SeqCst,
            )
            .is_err()
        {
            self.unpark_slow(vm);
        }
    }

    pub fn unpark_slow(&self, vm: &VM) {
        loop {
            match self.atomic_state.compare_exchange(
                ThreadState::Parked as usize,
                ThreadState::Running as usize,
                Ordering::SeqCst,
                Ordering::SeqCst,
            ) {
                Ok(_) => break,
                Err(state) => {
                    assert_eq!(state, ThreadState::ParkedSafepoint as usize);
                    vm.threads.barrier.wait_in_unpark();
                }
            }
        }
    }
}

pub struct StateManager {
    mtx: Mutex<(ThreadState, usize)>,
}

impl StateManager {
    fn new(initial_state: ThreadState) -> StateManager {
        StateManager {
            mtx: Mutex::new((initial_state, 0)),
        }
    }

    fn state(&self) -> ThreadState {
        let mtx = self.mtx.lock();
        mtx.0
    }

    fn park(&self, _vm: &VM) {
        let mut mtx = self.mtx.lock();
        assert!(mtx.0.is_running());
        mtx.0 = ThreadState::Parked;
    }

    fn unpark(&self, _vm: &VM) {
        let mut mtx = self.mtx.lock();
        assert!(mtx.0.is_parked());
        mtx.0 = ThreadState::Running;
    }

    fn block(&self, safepoint_id: usize) {
        let mut mtx = self.mtx.lock();
        assert!(mtx.0.is_running());
        mtx.0 = ThreadState::Blocked;
        mtx.1 = safepoint_id;
    }

    fn unblock(&self) {
        let mut mtx = self.mtx.lock();
        assert!(mtx.0.is_blocked());
        mtx.0 = ThreadState::Running;
        mtx.1 = 0;
    }

    fn in_safepoint(&self, safepoint_id: usize) -> bool {
        assert_ne!(safepoint_id, 0);
        let mtx = self.mtx.lock();

        match mtx.0 {
            ThreadState::Running => false,
            ThreadState::Blocked => mtx.1 == safepoint_id,
            ThreadState::Parked => true,
            ThreadState::RequestedSafepoint
            | ThreadState::ParkedSafepoint
            | ThreadState::Safepoint => unreachable!(),
        }
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ThreadState {
    Running = 0,
    Parked = 1,
    Blocked = 2,
    RequestedSafepoint = 3,
    ParkedSafepoint = 4,
    Safepoint = 5,
}

impl From<usize> for ThreadState {
    fn from(value: usize) -> ThreadState {
        match value {
            0 => ThreadState::Running,
            1 => ThreadState::Parked,
            2 => ThreadState::Blocked,
            3 => ThreadState::RequestedSafepoint,
            4 => ThreadState::ParkedSafepoint,
            5 => ThreadState::Safepoint,
            _ => unreachable!(),
        }
    }
}

impl ThreadState {
    pub fn is_running(&self) -> bool {
        match *self {
            ThreadState::Running => true,
            _ => false,
        }
    }

    pub fn is_parked(&self) -> bool {
        match *self {
            ThreadState::Parked => true,
            _ => false,
        }
    }

    pub fn is_blocked(&self) -> bool {
        match *self {
            ThreadState::Blocked => true,
            _ => false,
        }
    }

    pub fn to_usize(&self) -> usize {
        *self as usize
    }
}

impl Default for ThreadState {
    fn default() -> ThreadState {
        ThreadState::Running
    }
}

pub struct ThreadLocalData {
    tlab_top: AtomicUsize,
    tlab_end: AtomicUsize,
    concurrent_marking: AtomicBool,
    stack_limit: AtomicUsize,
    safepoint_requested: AtomicBool,
    dtn: AtomicUsize,
}

impl ThreadLocalData {
    pub fn new() -> ThreadLocalData {
        ThreadLocalData {
            tlab_top: AtomicUsize::new(0),
            tlab_end: AtomicUsize::new(0),
            concurrent_marking: AtomicBool::new(false),
            stack_limit: AtomicUsize::new(0),
            safepoint_requested: AtomicBool::new(false),
            dtn: AtomicUsize::new(0),
        }
    }

    pub fn tlab_initialize(&self, start: Address, end: Address) {
        assert!(start <= end);

        self.tlab_top.store(start.to_usize(), Ordering::Relaxed);
        self.tlab_end.store(end.to_usize(), Ordering::Relaxed);
    }

    pub fn tlab_rest(&self) -> usize {
        let tlab_top = self.tlab_top.load(Ordering::Relaxed);
        let tlab_end = self.tlab_end.load(Ordering::Relaxed);

        tlab_end - tlab_top
    }

    pub fn tlab_region(&self) -> Region {
        let tlab_top = self.tlab_top.load(Ordering::Relaxed);
        let tlab_end = self.tlab_end.load(Ordering::Relaxed);

        Region::new(tlab_top.into(), tlab_end.into())
    }

    pub fn set_stack_limit(&self, stack_limit: Address) {
        self.stack_limit
            .store(stack_limit.to_usize(), Ordering::Relaxed);
    }

    pub fn tlab_top_offset() -> i32 {
        offset_of!(ThreadLocalData, tlab_top) as i32
    }

    pub fn tlab_end_offset() -> i32 {
        offset_of!(ThreadLocalData, tlab_end) as i32
    }

    pub fn concurrent_marking_offset() -> i32 {
        offset_of!(ThreadLocalData, concurrent_marking) as i32
    }

    pub fn safepoint_requested_offset() -> i32 {
        offset_of!(ThreadLocalData, safepoint_requested) as i32
    }

    pub fn stack_limit(&self) -> Address {
        Address::from(self.stack_limit.load(Ordering::Relaxed))
    }

    pub fn stack_limit_offset() -> i32 {
        offset_of!(ThreadLocalData, stack_limit) as i32
    }

    pub fn dtn_offset() -> i32 {
        offset_of!(ThreadLocalData, dtn) as i32
    }

    pub fn set_safepoint_requested(&self) {
        self.safepoint_requested.store(true, Ordering::Relaxed);
    }

    pub fn clear_safepoint_requested(&self) {
        self.safepoint_requested.store(false, Ordering::Relaxed);
    }
}

pub struct Barrier {
    data: Mutex<BarrierData>,
    cv_wakeup: Condvar,
    cv_notify: Condvar,
}

impl Barrier {
    pub fn new() -> Barrier {
        Barrier {
            data: Mutex::new(BarrierData::new()),
            cv_wakeup: Condvar::new(),
            cv_notify: Condvar::new(),
        }
    }

    pub fn arm(&self) {
        let mut data = self.data.lock();
        assert!(!data.is_armed());
        data.arm();
    }

    pub fn disarm(&self) {
        let mut data = self.data.lock();
        assert!(data.is_armed());
        data.disarm();
        self.cv_wakeup.notify_all();
    }

    pub fn notify_park(&self) {
        let mut data = self.data.lock();
        assert!(data.is_armed());
        data.stopped += 1;
        self.cv_notify.notify_one();
    }

    pub fn wait_in_safepoint(&self) {
        let mut data = self.data.lock();
        assert!(data.is_armed());
        data.stopped += 1;
        self.cv_notify.notify_one();
        let safepoint = data.armed;

        while data.armed == safepoint {
            self.cv_wakeup.wait(&mut data);
        }
    }

    pub fn wait_in_unpark(&self) {
        let mut data = self.data.lock();

        while data.is_armed() {
            self.cv_wakeup.wait(&mut data);
        }
    }

    pub fn wait_until_threads_stopped(&self, threads: usize) {
        let mut data = self.data.lock();
        assert!(data.is_armed());
        while data.stopped < threads {
            self.cv_notify.wait(&mut data);
        }
        assert_eq!(data.stopped, threads);
    }
}

struct BarrierData {
    armed: usize,
    next: usize,
    stopped: usize,
}

impl BarrierData {
    pub fn new() -> BarrierData {
        BarrierData {
            armed: 0,
            next: 1,
            stopped: 0,
        }
    }

    pub fn is_armed(&self) -> bool {
        self.armed != 0
    }

    pub fn arm(&mut self) {
        self.stopped = 0;
        self.armed = self.next;

        if self.next == usize::max_value() {
            self.next = 1;
        } else {
            self.next += 1;
        }
    }

    pub fn disarm(&mut self) {
        self.armed = 0;
    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub, Mul};

macro_rules! wrapping_impl {
    ($trait_name:ident, $method:ident, $t:ty) => {
        impl $trait_name for $t {
            #[inline]
            fn $method(&self, v: &Self) -> Self {
                <$t>::$method(*self, *v)
            }
        }
    };
    ($trait_name:ident, $method:ident, $t:ty, $rhs:ty) => {
        impl $trait_name<$rhs> for $t {
            #[inline]
            fn $method(&self, v: &$rhs) -> Self {
                <$t>::$method(*self, *v)
            }
        }
    }
}

/// Performs addition that wraps around on overflow.
pub trait WrappingAdd: Sized + Add<Self, Output=Self> {
    /// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of
    /// the type.
    fn wrapping_add(&self, v: &Self) -> Self;
}

wrapping_impl!(WrappingAdd, wrapping_add, u8);
wrapping_impl!(WrappingAdd, wrapping_add, u16);
wrapping_impl!(WrappingAdd, wrapping_add, u32);
wrapping_impl!(WrappingAdd, wrapping_add, u64);
wrapping_impl!(WrappingAdd, wrapping_add, usize);

wrapping_impl!(WrappingAdd, wrapping_add, i8);
wrapping_impl!(WrappingAdd, wrapping_add, i16);
wrapping_impl!(WrappingAdd, wrapping_add, i32);
wrapping_impl!(WrappingAdd, wrapping_add, i64);
wrapping_impl!(WrappingAdd, wrapping_add, isize);

/// Performs subtraction that wraps around on overflow.
pub trait WrappingSub: Sized + Sub<Self, Output=Self> {
    /// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary
    /// of the type.
    fn wrapping_sub(&self, v: &Self) -> Self;
}

wrapping_impl!(WrappingSub, wrapping_sub, u8);
wrapping_impl!(WrappingSub, wrapping_sub, u16);
wrapping_impl!(WrappingSub, wrapping_sub, u32);
wrapping_impl!(WrappingSub, wrapping_sub, u64);
wrapping_impl!(WrappingSub, wrapping_sub, usize);

wrapping_impl!(WrappingSub, wrapping_sub, i8);
wrapping_impl!(WrappingSub, wrapping_sub, i16);
wrapping_impl!(WrappingSub, wrapping_sub, i32);
wrapping_impl!(WrappingSub, wrapping_sub, i64);
wrapping_impl!(WrappingSub, wrapping_sub, isize);

/// Performs multiplication that wraps around on overflow.
pub trait WrappingMul: Sized + Mul<Self, Output=Self> {
    /// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary
    /// of the type.
    fn wrapping_mul(&self, v: &Self) -> Self;
}

wrapping_impl!(WrappingMul, wrapping_mul, u8);
wrapping_impl!(WrappingMul, wrapping_mul, u16);
wrapping_impl!(WrappingMul, wrapping_mul, u32);
wrapping_impl!(WrappingMul, wrapping_mul, u64);
wrapping_impl!(WrappingMul, wrapping_mul, usize);

wrapping_impl!(WrappingMul, wrapping_mul, i8);
wrapping_impl!(WrappingMul, wrapping_mul, i16);
wrapping_impl!(WrappingMul, wrapping_mul, i32);
wrapping_impl!(WrappingMul, wrapping_mul, i64);
wrapping_impl!(WrappingMul, wrapping_mul, isize);
<commit_msg>Added tests.<commit_after>use std::ops::{Add, Sub, Mul};

macro_rules! wrapping_impl {
    ($trait_name:ident, $method:ident, $t:ty) => {
        impl $trait_name for $t {
            #[inline]
            fn $method(&self, v: &Self) -> Self {
                <$t>::$method(*self, *v)
            }
        }
    };
    ($trait_name:ident, $method:ident, $t:ty, $rhs:ty) => {
        impl $trait_name<$rhs> for $t {
            #[inline]
            fn $method(&self, v: &$rhs) -> Self {
                <$t>::$method(*self, *v)
            }
        }
    }
}

/// Performs addition that wraps around on overflow.
pub trait WrappingAdd: Sized + Add<Self, Output=Self> {
    /// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of
    /// the type.
    fn wrapping_add(&self, v: &Self) -> Self;
}

wrapping_impl!(WrappingAdd, wrapping_add, u8);
wrapping_impl!(WrappingAdd, wrapping_add, u16);
wrapping_impl!(WrappingAdd, wrapping_add, u32);
wrapping_impl!(WrappingAdd, wrapping_add, u64);
wrapping_impl!(WrappingAdd, wrapping_add, usize);

wrapping_impl!(WrappingAdd, wrapping_add, i8);
wrapping_impl!(WrappingAdd, wrapping_add, i16);
wrapping_impl!(WrappingAdd, wrapping_add, i32);
wrapping_impl!(WrappingAdd, wrapping_add, i64);
wrapping_impl!(WrappingAdd, wrapping_add, isize);

/// Performs subtraction that wraps around on overflow.
pub trait WrappingSub: Sized + Sub<Self, Output=Self> {
    /// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary
    /// of the type.
    fn wrapping_sub(&self, v: &Self) -> Self;
}

wrapping_impl!(WrappingSub, wrapping_sub, u8);
wrapping_impl!(WrappingSub, wrapping_sub, u16);
wrapping_impl!(WrappingSub, wrapping_sub, u32);
wrapping_impl!(WrappingSub, wrapping_sub, u64);
wrapping_impl!(WrappingSub, wrapping_sub, usize);

wrapping_impl!(WrappingSub, wrapping_sub, i8);
wrapping_impl!(WrappingSub, wrapping_sub, i16);
wrapping_impl!(WrappingSub, wrapping_sub, i32);
wrapping_impl!(WrappingSub, wrapping_sub, i64);
wrapping_impl!(WrappingSub, wrapping_sub, isize);

/// Performs multiplication that wraps around on overflow.
pub trait WrappingMul: Sized + Mul<Self, Output=Self> {
    /// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary
    /// of the type.
    fn wrapping_mul(&self, v: &Self) -> Self;
}

wrapping_impl!(WrappingMul, wrapping_mul, u8);
wrapping_impl!(WrappingMul, wrapping_mul, u16);
wrapping_impl!(WrappingMul, wrapping_mul, u32);
wrapping_impl!(WrappingMul, wrapping_mul, u64);
wrapping_impl!(WrappingMul, wrapping_mul, usize);

wrapping_impl!(WrappingMul, wrapping_mul, i8);
wrapping_impl!(WrappingMul, wrapping_mul, i16);
wrapping_impl!(WrappingMul, wrapping_mul, i32);
wrapping_impl!(WrappingMul, wrapping_mul, i64);
wrapping_impl!(WrappingMul, wrapping_mul, isize);

#[test]
fn test_wrapping_traits() {
    fn wrapping_add<T: WrappingAdd>(a: T, b: T) -> T { a.wrapping_add(&b) }
    fn wrapping_sub<T: WrappingSub>(a: T, b: T) -> T { a.wrapping_sub(&b) }
    fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T { a.wrapping_mul(&b) }
    assert_eq!(wrapping_add(255, 1), 0u8);
    assert_eq!(wrapping_sub(0, 1), 255u8);
    assert_eq!(wrapping_mul(255, 2), 254u8);
}
<|endoftext|>


<commit_before>extern crate sdl2;

fn main() -> Result<(), String> {
    let sdl_context = sdl2::init()?;
    let game_controller_subsystem = sdl_context.game_controller()?;

    let available = game_controller_subsystem
        .num_joysticks()
        .map_err(|e| format!("can't enumerate joysticks: {}", e))?;

    println!("{} joysticks available", available);

    // Iterate over all available joysticks and look for game controllers.
    let mut controller = (0..available)
        .find_map(|id| {
            if !game_controller_subsystem.is_game_controller(id) {
                println!("{} is not a game controller", id);
                return None;
            }

            println!("Attempting to open controller {}", id);

            match game_controller_subsystem.open(id) {
                Ok(c) => {
                    // We managed to find and open a game controller,
                    // exit the loop
                    println!("Success: opened \"{}\"", c.name());
                    Some(c)
                }
                Err(e) => {
                    println!("failed: {:?}", e);
                    None
                }
            }
        })
        .expect("Couldn't open any controller");

    println!("Controller mapping: {}", controller.mapping());

    let (mut lo_freq, mut hi_freq) = (0, 0);

    for event in sdl_context.event_pump()?.wait_iter() {
        use sdl2::controller::Axis;
        use sdl2::event::Event;

        match event {
            Event::ControllerAxisMotion {
                axis: Axis::TriggerLeft,
                value: val,
                ..
            } => {
                // Trigger axes go from 0 to 32767, so this should be okay
                lo_freq = (val as u16) * 2;
                match controller.set_rumble(lo_freq, hi_freq, 15000) {
                    Ok(()) => println!("Set rumble to ({}, {})", lo_freq, hi_freq),
                    Err(e) => println!(
                        "Error setting rumble to ({}, {}): {:?}",
                        lo_freq, hi_freq, e
                    ),
                }
            }
            Event::ControllerAxisMotion {
                axis: Axis::TriggerRight,
                value: val,
                ..
            } => {
                // Trigger axes go from 0 to 32767, so this should be okay
                hi_freq = (val as u16) * 2;
                match controller.set_rumble(lo_freq, hi_freq, 15000) {
                    Ok(()) => println!("Set rumble to ({}, {})", lo_freq, hi_freq),
                    Err(e) => println!(
                        "Error setting rumble to ({}, {}): {:?}",
                        lo_freq, hi_freq, e
                    ),
                }
            }
            Event::ControllerAxisMotion {
                axis, value: val, ..
            } => {
                // Axis motion is an absolute value in the range
                // [-32768, 32767]. Let's simulate a very rough dead
                // zone to ignore spurious events.
                let dead_zone = 10_000;
                if val > dead_zone || val < -dead_zone {
                    println!("Axis {:?} moved to {}", axis, val);
                }
            }
            Event::ControllerButtonDown { button, .. } => println!("Button {:?} down", button),
            Event::ControllerButtonUp { button, .. } => println!("Button {:?} up", button),
            Event::ControllerTouchpadDown { touchpad, finger, x, y, ..} => println!("Touchpad {touchpad} down finger:{finger} x:{x} y:{y}"),
            Event::ControllerTouchpadMotion { touchpad, finger, x, y, ..} => println!("Touchpad {touchpad} move finger:{finger} x:{x} y:{y}"),
            Event::ControllerTouchpadUp { touchpad, finger, x, y, ..} => println!("Touchpad {touchpad} up   finger:{finger} x:{x} y:{y}"),
            Event::Quit { .. } => break,
            _ => (),
        }
    }

    Ok(())
}
<commit_msg>fix formatting<commit_after>extern crate sdl2;

fn main() -> Result<(), String> {
    let sdl_context = sdl2::init()?;
    let game_controller_subsystem = sdl_context.game_controller()?;

    let available = game_controller_subsystem
        .num_joysticks()
        .map_err(|e| format!("can't enumerate joysticks: {}", e))?;

    println!("{} joysticks available", available);

    // Iterate over all available joysticks and look for game controllers.
    let mut controller = (0..available)
        .find_map(|id| {
            if !game_controller_subsystem.is_game_controller(id) {
                println!("{} is not a game controller", id);
                return None;
            }

            println!("Attempting to open controller {}", id);

            match game_controller_subsystem.open(id) {
                Ok(c) => {
                    // We managed to find and open a game controller,
                    // exit the loop
                    println!("Success: opened \"{}\"", c.name());
                    Some(c)
                }
                Err(e) => {
                    println!("failed: {:?}", e);
                    None
                }
            }
        })
        .expect("Couldn't open any controller");

    println!("Controller mapping: {}", controller.mapping());

    let (mut lo_freq, mut hi_freq) = (0, 0);

    for event in sdl_context.event_pump()?.wait_iter() {
        use sdl2::controller::Axis;
        use sdl2::event::Event;

        match event {
            Event::ControllerAxisMotion {
                axis: Axis::TriggerLeft,
                value: val,
                ..
            } => {
                // Trigger axes go from 0 to 32767, so this should be okay
                lo_freq = (val as u16) * 2;
                match controller.set_rumble(lo_freq, hi_freq, 15000) {
                    Ok(()) => println!("Set rumble to ({}, {})", lo_freq, hi_freq),
                    Err(e) => println!(
                        "Error setting rumble to ({}, {}): {:?}",
                        lo_freq, hi_freq, e
                    ),
                }
            }
            Event::ControllerAxisMotion {
                axis: Axis::TriggerRight,
                value: val,
                ..
            } => {
                // Trigger axes go from 0 to 32767, so this should be okay
                hi_freq = (val as u16) * 2;
                match controller.set_rumble(lo_freq, hi_freq, 15000) {
                    Ok(()) => println!("Set rumble to ({}, {})", lo_freq, hi_freq),
                    Err(e) => println!(
                        "Error setting rumble to ({}, {}): {:?}",
                        lo_freq, hi_freq, e
                    ),
                }
            }
            Event::ControllerAxisMotion {
                axis, value: val, ..
            } => {
                // Axis motion is an absolute value in the range
                // [-32768, 32767]. Let's simulate a very rough dead
                // zone to ignore spurious events.
                let dead_zone = 10_000;
                if val > dead_zone || val < -dead_zone {
                    println!("Axis {:?} moved to {}", axis, val);
                }
            }
            Event::ControllerButtonDown { button, .. } => println!("Button {:?} down", button),
            Event::ControllerButtonUp { button, .. } => println!("Button {:?} up", button),
            Event::ControllerTouchpadDown {
                touchpad,
                finger,
                x,
                y,
                ..
            } => println!("Touchpad {touchpad} down finger:{finger} x:{x} y:{y}"),
            Event::ControllerTouchpadMotion {
                touchpad,
                finger,
                x,
                y,
                ..
            } => println!("Touchpad {touchpad} move finger:{finger} x:{x} y:{y}"),
            Event::ControllerTouchpadUp {
                touchpad,
                finger,
                x,
                y,
                ..
            } => println!("Touchpad {touchpad} up   finger:{finger} x:{x} y:{y}"),
            Event::Quit { .. } => break,
            _ => (),
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>#![feature(async_await)]
use futures::{FutureExt, StreamExt, TryFutureExt};

use tg_botapi::types::{ParseMode, Message, UpdateType, InputFile};
use tg_botapi::Bot;

use std::env;
use tg_botapi::methods::SendPhoto;

fn main() {
    let token = env::var("TOKEN")
        .expect("No bot token provided, please set the environment variable TOKEN");

    tokio::run(run_bot(token).boxed().unit_error().compat());
}

async fn run_bot(token: impl Into<String>) {
    let bot = Bot::new(token);

    let mut updates = bot.start_polling();

    while let Some(update) = updates.next().await {
        match update.update_type {
            UpdateType::Message(message) => {
                tokio::spawn(
                    handle_message(bot.clone(), message)
                        .boxed()
                        .unit_error()
                        .compat(),
                );
            }

            _ => {}
        }
    }
}

async fn handle_message(bot: Bot, msg: Message) {
    if let Some(ref img) = msg.photo {
        let smallest_photo = &img.iter().min_by_key(|ps| ps.height).unwrap().file_id;
        let req = msg.reply_photo(InputFile::FileId(smallest_photo.into()));

        bot.send(&req).await.unwrap();
    } else if let Some(text) = msg.get_text() {
        if text == "/img" {
            let file_path = "./image.jpg";
            let req = msg.reply_photo(InputFile::file(file_path.into()));

            bot.send(&req).await.unwrap();
        } else {
            let mut req = msg.reply(text);
            req.parse_mode = ParseMode::Markdown;

            bot.send(&req).await.unwrap();
        }
    }
}
<commit_msg>Fix echo example<commit_after>#![feature(async_await)]
use futures::{FutureExt, StreamExt, TryFutureExt};

use tg_botapi::types::{ParseMode, Message, UpdateType, InputFile};
use tg_botapi::Bot;

use std::env;

fn main() {
    let token = env::var("TOKEN")
        .expect("No bot token provided, please set the environment variable TOKEN");

    tokio::run(run_bot(token).boxed().unit_error().compat());
}

async fn run_bot(token: impl Into<String>) {
    let bot = Bot::new(token);

    let mut updates = bot.start_polling();

    while let Some(update) = updates.next().await {
        match update.update_type {
            UpdateType::Message(message) => {
                tokio::spawn(
                    handle_message(bot.clone(), message)
                        .boxed()
                        .unit_error()
                        .compat(),
                );
            }

            _ => {}
        }
    }
}

async fn handle_message(bot: Bot, msg: Message) {
    if let Some(ref img) = msg.photo {
        let smallest_photo = &img.iter().min_by_key(|ps| ps.height).unwrap().file_id;
        let req = msg.reply_photo(InputFile::FileId(smallest_photo.into()));

        bot.send(&req).await.unwrap();
    } else if let Some(text) = msg.get_text() {
        if text == "/img" {
            let file_path = "./image.jpg";
            let req = msg.reply_photo(InputFile::file(file_path));

            bot.send(&req).await.unwrap();
        } else {
            let mut req = msg.reply(text);
            req.parse_mode = ParseMode::Markdown;

            bot.send(&req).await.unwrap();
        }
    }
}
<|endoftext|>


<commit_before>extern crate ruroonga;
use ruroonga::*;
use std::ffi::CStr;
use std::str;

fn main() {
    unsafe {
        let ctx = groonga_init();
        println!("Hello in Ruroonga with Groonga: {}", get_groonga_version());
        let _ = groonga_fin(ctx);
    }
}
<commit_msg>Convert Rust string type to C char type with unstable feature.... :<<commit_after>#![feature(libc)]
#![feature(collections)]
#![feature(convert)]
extern crate ruroonga;
extern crate libc;
use ruroonga::*;
use std::ffi::CStr;
use std::ffi::CString;
use std::str;
use std::string::String;

fn main() {
    unsafe {
        let ctx = groonga_init();
        let mut string = "test.db".to_string();
        let bytes = string.into_bytes();
        let mut x : Vec<libc::c_char> = bytes.map_in_place(|w| w as libc::c_char);;
        let slice = x.as_mut_slice();
        let dbpath = slice.as_mut_ptr();
        let db_ctx = grn_db_create(ctx, dbpath, None);
        println!("Hello in Ruroonga with Groonga: {}", get_groonga_version());
        let _ = groonga_fin(ctx);
    }
}
<|endoftext|>


<commit_before>//HACK: This is how we're splitting the maze example into multiple files since
// cargo doesn't properly support examples with multiple files yet
#[path = "maze/wall.rs"]
mod wall;
#[path = "maze/cell.rs"]
mod cell;
#[path = "maze/maze.rs"]
mod maze;
#[path = "maze/grid.rs"]
mod grid;

extern crate turtle;

use turtle::Turtle;

pub use maze::Maze;
use grid::{GridCellIter};
use cell::Cell;

// Dimensions of the maze in turtle steps (pixels)
const WIDTH: f64 = 600.0; // px
const HEIGHT: f64 = 600.0; // px

fn main() {
    let maze = Maze::generate();

    let mut turtle = Turtle::new();
    turtle.set_speed(10);
    turtle.set_background_color("#A5D6A7");
    turtle.set_pen_color("#03A9F4");
    turtle.set_pen_size(2.0);

    // Get to the top left corner
    turtle.pen_up();
    turtle.forward(HEIGHT / 2.0);
    turtle.right(90.0);
    turtle.backward(WIDTH / 2.0);
    turtle.pen_down();

    let cell_width = WIDTH/(maze.row_size() as f64);
    let cell_height = HEIGHT/(maze.col_size() as f64);

    // Draw rows
    draw_rows(
        &mut turtle,
        cell_width,
        cell_height,
        maze.first_row().map(|cell| cell.north.is_closed()),
        maze.rows(),
        |row| row.map(|cell| cell.south.is_closed()),
        false,
    );

    // Draw columns
    turtle.left(90.0);
    draw_rows(
        &mut turtle,
        cell_height,
        cell_width,
        maze.last_col().rev().map(|cell| cell.east.is_closed()),
        maze.cols().rev(),
        |col| col.map(|cell| cell.west.is_closed()).rev(),
        true,
    );
}

fn draw_rows<
    'a,
    R: Iterator<Item=bool>,
    G: Iterator<Item=GridCellIter<'a>>,
    F: Fn(GridCellIter<'a>) -> X,
    X: Iterator<Item=bool> + DoubleEndedIterator
>(
    turtle: &mut Turtle,
    // size of each cell in the row
    cell_size: f64,
    // gap between rows
    cell_gap: f64,
    first_row: R,
    rows: G,
    row_walls: F,
    rotate_left: bool,
) {
    draw_row(turtle, cell_size, first_row);

    // Direction of rotation for all turns
    let rotation = if rotate_left { -1.0 } else { 1.0 };
    for (i, row) in rows.enumerate() {
        turtle.pen_up();

        // Direction of rotation for these turns
        let direction = rotation * if i % 2 == 0 { 1.0 } else { -1.0 };
        turtle.right(direction * 90.0);
        turtle.forward(cell_gap);
        turtle.right(direction * 90.0);
        turtle.pen_down();

        let walls = row_walls(row);

        // Every second row needs to be reversed so the turtle can zig-zag back and
        // forth instead of wasting too much time moving all the way to the left of
        // each row
        if i % 2 == 0 {
            draw_row(turtle, cell_size, walls.rev());
        }
        else {
            draw_row(turtle, cell_size, walls);
        }
    }
}

fn draw_row<I: Iterator<Item=bool>>(turtle: &mut Turtle, wall_size: f64, walls: I) {
    for should_draw in walls {
        if !should_draw {
            turtle.pen_up();
        }
        turtle.forward(wall_size);
        turtle.pen_down();
    }
}
<commit_msg>Removing unused import<commit_after>//HACK: This is how we're splitting the maze example into multiple files since
// cargo doesn't properly support examples with multiple files yet
#[path = "maze/wall.rs"]
mod wall;
#[path = "maze/cell.rs"]
mod cell;
#[path = "maze/maze.rs"]
mod maze;
#[path = "maze/grid.rs"]
mod grid;

extern crate turtle;

use turtle::Turtle;

pub use maze::Maze;
use grid::{GridCellIter};

// Dimensions of the maze in turtle steps (pixels)
const WIDTH: f64 = 600.0; // px
const HEIGHT: f64 = 600.0; // px

fn main() {
    let maze = Maze::generate();

    let mut turtle = Turtle::new();
    turtle.set_speed(10);
    turtle.set_background_color("#A5D6A7");
    turtle.set_pen_color("#03A9F4");
    turtle.set_pen_size(2.0);

    // Get to the top left corner
    turtle.pen_up();
    turtle.forward(HEIGHT / 2.0);
    turtle.right(90.0);
    turtle.backward(WIDTH / 2.0);
    turtle.pen_down();

    let cell_width = WIDTH/(maze.row_size() as f64);
    let cell_height = HEIGHT/(maze.col_size() as f64);

    // Draw rows
    draw_rows(
        &mut turtle,
        cell_width,
        cell_height,
        maze.first_row().map(|cell| cell.north.is_closed()),
        maze.rows(),
        |row| row.map(|cell| cell.south.is_closed()),
        false,
    );

    // Draw columns
    turtle.left(90.0);
    draw_rows(
        &mut turtle,
        cell_height,
        cell_width,
        maze.last_col().rev().map(|cell| cell.east.is_closed()),
        maze.cols().rev(),
        |col| col.map(|cell| cell.west.is_closed()).rev(),
        true,
    );
}

fn draw_rows<
    'a,
    R: Iterator<Item=bool>,
    G: Iterator<Item=GridCellIter<'a>>,
    F: Fn(GridCellIter<'a>) -> X,
    X: Iterator<Item=bool> + DoubleEndedIterator
>(
    turtle: &mut Turtle,
    // size of each cell in the row
    cell_size: f64,
    // gap between rows
    cell_gap: f64,
    first_row: R,
    rows: G,
    row_walls: F,
    rotate_left: bool,
) {
    draw_row(turtle, cell_size, first_row);

    // Direction of rotation for all turns
    let rotation = if rotate_left { -1.0 } else { 1.0 };
    for (i, row) in rows.enumerate() {
        turtle.pen_up();

        // Direction of rotation for these turns
        let direction = rotation * if i % 2 == 0 { 1.0 } else { -1.0 };
        turtle.right(direction * 90.0);
        turtle.forward(cell_gap);
        turtle.right(direction * 90.0);
        turtle.pen_down();

        let walls = row_walls(row);

        // Every second row needs to be reversed so the turtle can zig-zag back and
        // forth instead of wasting too much time moving all the way to the left of
        // each row
        if i % 2 == 0 {
            draw_row(turtle, cell_size, walls.rev());
        }
        else {
            draw_row(turtle, cell_size, walls);
        }
    }
}

fn draw_row<I: Iterator<Item=bool>>(turtle: &mut Turtle, wall_size: f64, walls: I) {
    for should_draw in walls {
        if !should_draw {
            turtle.pen_up();
        }
        turtle.forward(wall_size);
        turtle.pen_down();
    }
}
<|endoftext|>


<commit_before>extern crate libterm;

use libterm::ReadExt;
use std::io::{Write, stdout, stdin};

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let stdin = stdin();
    let mut stdin = stdin.lock();

    stdout.write(b"password: ").unwrap();
    stdout.flush().unwrap();

    let pass = stdin.read_passwd(&mut stdout);

    if let Ok(Some(pass)) = pass {
        stdout.write(pass.as_bytes()).unwrap();
        stdout.write(b"\n").unwrap();
    } else {
        stdout.write(b"Error\n").unwrap();
    }
}
<commit_msg>Fix read example<commit_after>extern crate libterm;

use libterm::TermRead;
use std::io::{Write, stdout, stdin};

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let stdin = stdin();
    let mut stdin = stdin.lock();

    stdout.write(b"password: ").unwrap();
    stdout.flush().unwrap();

    let pass = stdin.read_passwd(&mut stdout);

    if let Ok(Some(pass)) = pass {
        stdout.write(pass.as_bytes()).unwrap();
        stdout.write(b"\n").unwrap();
    } else {
        stdout.write(b"Error\n").unwrap();
    }
}
<|endoftext|>


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

//! Controls the state machine of the system
//!
//! It supports following states, and transitions, as shown in the
//! below diagram:
//!
//! ```text
//!   .---------------.
//!   |               v
//! Idle -> Poll -> Probe -> Download -> Install -> Reboot
//!   ^      ^        '          '          '
//!   '      '        '          '          '
//!   '      `--------'          '          '
//!   `---------------'          '          '
//!   `--------------------------'          '
//!   `-------------------------------------'
//! ```

use failure::Error;
use firmware::Metadata;
use runtime_settings::RuntimeSettings;
use settings::Settings;

#[macro_use]
mod macros;

mod idle;
use self::idle::Idle;

mod poll;
use self::poll::Poll;

mod probe;
use self::probe::Probe;

mod download;
use self::download::Download;

mod install;
use self::install::Install;

pub trait StateChangeImpl {
    fn to_next_state(self) -> Result<StateMachine, Error>;
}

/// Holds the `State` type and common data, which is available for
/// every state transition.
#[derive(Debug, PartialEq)]
pub struct State<S>
where
    State<S>: StateChangeImpl,
{
    /// System settings.
    settings: Settings,

    /// Runtime settings.
    runtime_settings: RuntimeSettings,

    /// Firmware metadata.
    firmware: Metadata,

    /// Package UID applied
    applied_package_uid: Option<String>,

    /// State type with specific data and methods.
    state: S,
}

/// The struct representing the state machine.
#[derive(Debug, PartialEq)]
pub enum StateMachine {
    /// Idle state
    Idle(State<Idle>),

    /// Poll state
    Poll(State<Poll>),

    /// Probe state
    Probe(State<Probe>),

    /// Download state
    Download(State<Download>),

    /// Install state
    Install(State<Install>),
}

impl StateMachine {
    pub fn new(settings: Settings, runtime_settings: RuntimeSettings, firmware: Metadata) -> Self {
        StateMachine::Idle(State {
            settings,
            runtime_settings,
            firmware,
            applied_package_uid: None,
            state: Idle {},
        })
    }

    pub fn start(self) {
        // FIXME: Handle errors
        self.step().unwrap();
    }

    fn step(self) -> Result<StateMachine, Error> {
        match self {
            StateMachine::Idle(s) => Ok(s.to_next_state()?),
            StateMachine::Poll(s) => Ok(s.to_next_state()?),
            StateMachine::Probe(s) => Ok(s.to_next_state()?),
            StateMachine::Download(s) => Ok(s.to_next_state()?),
            StateMachine::Install(s) => Ok(s.to_next_state()?),
        }
    }
}
<commit_msg>states: Update diagram<commit_after>// Copyright (C) 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: MPL-2.0
//

//! Controls the state machine of the system
//!
//! It supports following states, and transitions, as shown in the
//! below diagram:
//!
//! ```text
//!   .--------------.   .---------.----> Error ------------.
//!   |              v  /         /         ^               '
//! Idle -> Poll -> Probe -> Download -> Install -> Reboot  |
//!   ^      ^        '          '          '               |
//!   '      '        '          '          '               |
//!   '      `--------'          '          '               |
//!   `---------------'          '          '               |
//!   `--------------------------'          '               |
//!   `-------------------------------------'               |
//!   `-----------------------------------------------------'
//! ```

use failure::Error;
use firmware::Metadata;
use runtime_settings::RuntimeSettings;
use settings::Settings;

#[macro_use]
mod macros;

mod idle;
use self::idle::Idle;

mod poll;
use self::poll::Poll;

mod probe;
use self::probe::Probe;

mod download;
use self::download::Download;

mod install;
use self::install::Install;

pub trait StateChangeImpl {
    fn to_next_state(self) -> Result<StateMachine, Error>;
}

/// Holds the `State` type and common data, which is available for
/// every state transition.
#[derive(Debug, PartialEq)]
pub struct State<S>
where
    State<S>: StateChangeImpl,
{
    /// System settings.
    settings: Settings,

    /// Runtime settings.
    runtime_settings: RuntimeSettings,

    /// Firmware metadata.
    firmware: Metadata,

    /// Package UID applied
    applied_package_uid: Option<String>,

    /// State type with specific data and methods.
    state: S,
}

/// The struct representing the state machine.
#[derive(Debug, PartialEq)]
pub enum StateMachine {
    /// Idle state
    Idle(State<Idle>),

    /// Poll state
    Poll(State<Poll>),

    /// Probe state
    Probe(State<Probe>),

    /// Download state
    Download(State<Download>),

    /// Install state
    Install(State<Install>),
}

impl StateMachine {
    pub fn new(settings: Settings, runtime_settings: RuntimeSettings, firmware: Metadata) -> Self {
        StateMachine::Idle(State {
            settings,
            runtime_settings,
            firmware,
            applied_package_uid: None,
            state: Idle {},
        })
    }

    pub fn start(self) {
        // FIXME: Handle errors
        self.step().unwrap();
    }

    fn step(self) -> Result<StateMachine, Error> {
        match self {
            StateMachine::Idle(s) => Ok(s.to_next_state()?),
            StateMachine::Poll(s) => Ok(s.to_next_state()?),
            StateMachine::Probe(s) => Ok(s.to_next_state()?),
            StateMachine::Download(s) => Ok(s.to_next_state()?),
            StateMachine::Install(s) => Ok(s.to_next_state()?),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::collections::HashMap;

use clap::{App, AppSettings, Arg};

struct Help {
    short: &'static str,
    long: &'static str,
}

macro_rules! doc {
    ($map:expr, $name:expr, $short:expr) => {
        doc!($map, $name, $short, $short)
    };
    ($map:expr, $name:expr, $short:expr, $long:expr) => {
        $map.insert($name, Help {
            short: $short,
            long: concat!($long, "\n ")
        });
    };
}

pub fn build_app() -> App<'static, 'static> {
    let helps = usage();
    let arg = |name| {
        Arg::with_name(name).help(helps[name].short).long_help(
            helps[name].long,
        )
    };

    App::new("fd")
        .version(crate_version!())
        .usage("fd [FLAGS/OPTIONS] [<pattern>] [<path>]")
        .setting(AppSettings::ColoredHelp)
        .setting(AppSettings::DeriveDisplayOrder)
        .arg(arg("hidden").long("hidden").short("H"))
        .arg(arg("no-ignore").long("no-ignore").short("I"))
        .arg(
            arg("rg-alias-hidden-ignore")
                .short("u")
                .multiple(true)
                .hidden(true),
        )
        .arg(
            arg("case-sensitive")
                .long("case-sensitive")
                .short("s")
                .overrides_with("ignore-case"),
        )
        .arg(
            arg("ignore-case")
                .long("ignore-case")
                .short("i")
                .overrides_with("case-sensitive"),
        )
        .arg(arg("absolute-path").long("absolute-path").short("a"))
        .arg(arg("follow").long("follow").short("L").alias("dereference"))
        .arg(arg("full-path").long("full-path").short("p"))
        .arg(arg("null_separator").long("print0").short("0"))
        .arg(arg("depth").long("max-depth").short("d").takes_value(true))
        .arg(
            arg("file-type")
                .long("type")
                .short("t")
                .takes_value(true)
                .value_name("filetype")
                .possible_values(&["f", "file", "d", "directory", "l", "symlink"])
                .hide_possible_values(true),
        )
        .arg(
            arg("extension")
                .long("extension")
                .short("e")
                .takes_value(true)
                .value_name("ext"),
        )
        .arg(
            arg("color")
                .long("color")
                .short("c")
                .takes_value(true)
                .value_name("when")
                .possible_values(&["never", "auto", "always"])
                .hide_possible_values(true),
        )
        .arg(
            arg("threads")
                .long("threads")
                .short("j")
                .takes_value(true)
                .value_name("num"),
        )
        .arg(
            arg("max-buffer-time")
                .long("max-buffer-time")
                .takes_value(true)
                .hidden(true),
        )
        .arg(
            arg("exec")
                .long("exec")
                .short("x")
                .takes_value(true)
                .value_name("cmd"),
        )
        .arg(arg("pattern"))
        .arg(arg("path"))
}

#[cfg_attr(rustfmt, rustfmt_skip)]
fn usage() -> HashMap<&'static str, Help> {
    let mut h = HashMap::new();
    doc!(h, "hidden"
        , "Search hidden files and directories"
        , "Include hidden directories and files in the search results (default: hidden files \
           and directories are skipped).");
    doc!(h, "no-ignore"
        , "Do not respect .(git)ignore files"
        , "Show search results from files and directories that would otherwise be ignored by \
            '.*ignore' files.");
    doc!(h, "case-sensitive"
        , "Case-sensitive search (default: smart case)"
        , "Perform a case-sensitive search. By default, fd uses case-insensitive searches, \
           unless the pattern contains an uppercase character (smart case).");
    doc!(h, "ignore-case"
        , "Case-insensitive search (default: smart case)"
        , "Perform a case-insensitive search. By default, fd uses case-insensitive searches, \
           unless the pattern contains an uppercase character (smart case).");
    doc!(h, "absolute-path"
        , "Show absolute instead of relative paths"
        , "Shows the full path starting from the root as opposed to relative paths.");
    doc!(h, "follow"
        , "Follow symbolic links"
        , "By default, fd does not descent into symlinked directories. Using this flag, symbolic \
           links are also traversed.");
    doc!(h, "full-path"
        , "Search full path (default: file-/dirname only)"
        , "By default, the search pattern is only matched against the filename (or directory \
           name). Using this flag, the pattern is matched against the full path.");
    doc!(h, "null_separator"
        , "Separate results by the null character"
        , "Separate search results by the null character (instead of newlines). Useful for \
           piping results to 'xargs'.");
    doc!(h, "depth"
        , "Set maximum search depth (default: none)"
        , "Limit the directory traversal to a given depth. By default, there is no limit \
           on the search depth.");
    doc!(h, "file-type"
        , "Filter by type: f(ile), d(irectory), (sym)l(ink)"
        , "Filter the search by type:\n  \
             'f' or 'file':         regular files\n  \
             'd' or 'directory':    directories\n  \
             'l' or 'symlink':      symbolic links");
    doc!(h, "exec"
        , "Execute the given command for each search result"
        , "Execute the given command for each search result.\n\
           The following are valid tokens that can be used within the expression for generating \
           commands:\n \
             '{}':   places the input in the location of this token\n \
             '{.}':  removes the extension from the input\n \
             '{/}':  places the basename of the input\n \
             '{//}': places the parent of the input\n \
             '{/.}': places the basename of the input, without the extension\n");
    doc!(h, "extension"
        , "Filter by file extension"
        , "(Additionally) filter search results by their file extension.");
    doc!(h, "color"
        , "When to use colors: never, *auto*, always"
        , "Declare when to use color for the pattern match output:\n  \
             'auto':      show colors if the output goes to an interactive console (default)\n  \
             'never':     do not use colorized output\n  \
             'always':    always use colorized output");
    doc!(h, "threads"
        , "Set number of threads to use for searching & executing"
        , "Set number of threads to use for searching & executing (default: number of available \
           CPU cores)");
    doc!(h, "max-buffer-time"
        , "the time (in ms) to buffer, before streaming to the console"
        , "Amount of time in milliseconds to buffer, before streaming the search results to\
           the console.");
    doc!(h, "pattern"
        , "the search pattern, a regular expression (optional)");
    doc!(h, "path"
        , "the root directory for the filesystem search (optional)"
        , "The directory where the filesystem search is rooted (optional). \
           If omitted, search the current working directory.");
    doc!(h, "rg-alias-hidden-ignore"
        , "Alias for no-ignore and/or hidden"
        , "Alias for no-ignore ('u') and no-ignore and hidden ('uu')");

    h
}
<commit_msg>Typo fix: Change 'descent' to 'descend'<commit_after>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::collections::HashMap;

use clap::{App, AppSettings, Arg};

struct Help {
    short: &'static str,
    long: &'static str,
}

macro_rules! doc {
    ($map:expr, $name:expr, $short:expr) => {
        doc!($map, $name, $short, $short)
    };
    ($map:expr, $name:expr, $short:expr, $long:expr) => {
        $map.insert($name, Help {
            short: $short,
            long: concat!($long, "\n ")
        });
    };
}

pub fn build_app() -> App<'static, 'static> {
    let helps = usage();
    let arg = |name| {
        Arg::with_name(name).help(helps[name].short).long_help(
            helps[name].long,
        )
    };

    App::new("fd")
        .version(crate_version!())
        .usage("fd [FLAGS/OPTIONS] [<pattern>] [<path>]")
        .setting(AppSettings::ColoredHelp)
        .setting(AppSettings::DeriveDisplayOrder)
        .arg(arg("hidden").long("hidden").short("H"))
        .arg(arg("no-ignore").long("no-ignore").short("I"))
        .arg(
            arg("rg-alias-hidden-ignore")
                .short("u")
                .multiple(true)
                .hidden(true),
        )
        .arg(
            arg("case-sensitive")
                .long("case-sensitive")
                .short("s")
                .overrides_with("ignore-case"),
        )
        .arg(
            arg("ignore-case")
                .long("ignore-case")
                .short("i")
                .overrides_with("case-sensitive"),
        )
        .arg(arg("absolute-path").long("absolute-path").short("a"))
        .arg(arg("follow").long("follow").short("L").alias("dereference"))
        .arg(arg("full-path").long("full-path").short("p"))
        .arg(arg("null_separator").long("print0").short("0"))
        .arg(arg("depth").long("max-depth").short("d").takes_value(true))
        .arg(
            arg("file-type")
                .long("type")
                .short("t")
                .takes_value(true)
                .value_name("filetype")
                .possible_values(&["f", "file", "d", "directory", "l", "symlink"])
                .hide_possible_values(true),
        )
        .arg(
            arg("extension")
                .long("extension")
                .short("e")
                .takes_value(true)
                .value_name("ext"),
        )
        .arg(
            arg("color")
                .long("color")
                .short("c")
                .takes_value(true)
                .value_name("when")
                .possible_values(&["never", "auto", "always"])
                .hide_possible_values(true),
        )
        .arg(
            arg("threads")
                .long("threads")
                .short("j")
                .takes_value(true)
                .value_name("num"),
        )
        .arg(
            arg("max-buffer-time")
                .long("max-buffer-time")
                .takes_value(true)
                .hidden(true),
        )
        .arg(
            arg("exec")
                .long("exec")
                .short("x")
                .takes_value(true)
                .value_name("cmd"),
        )
        .arg(arg("pattern"))
        .arg(arg("path"))
}

#[cfg_attr(rustfmt, rustfmt_skip)]
fn usage() -> HashMap<&'static str, Help> {
    let mut h = HashMap::new();
    doc!(h, "hidden"
        , "Search hidden files and directories"
        , "Include hidden directories and files in the search results (default: hidden files \
           and directories are skipped).");
    doc!(h, "no-ignore"
        , "Do not respect .(git)ignore files"
        , "Show search results from files and directories that would otherwise be ignored by \
            '.*ignore' files.");
    doc!(h, "case-sensitive"
        , "Case-sensitive search (default: smart case)"
        , "Perform a case-sensitive search. By default, fd uses case-insensitive searches, \
           unless the pattern contains an uppercase character (smart case).");
    doc!(h, "ignore-case"
        , "Case-insensitive search (default: smart case)"
        , "Perform a case-insensitive search. By default, fd uses case-insensitive searches, \
           unless the pattern contains an uppercase character (smart case).");
    doc!(h, "absolute-path"
        , "Show absolute instead of relative paths"
        , "Shows the full path starting from the root as opposed to relative paths.");
    doc!(h, "follow"
        , "Follow symbolic links"
        , "By default, fd does not descend into symlinked directories. Using this flag, symbolic \
           links are also traversed.");
    doc!(h, "full-path"
        , "Search full path (default: file-/dirname only)"
        , "By default, the search pattern is only matched against the filename (or directory \
           name). Using this flag, the pattern is matched against the full path.");
    doc!(h, "null_separator"
        , "Separate results by the null character"
        , "Separate search results by the null character (instead of newlines). Useful for \
           piping results to 'xargs'.");
    doc!(h, "depth"
        , "Set maximum search depth (default: none)"
        , "Limit the directory traversal to a given depth. By default, there is no limit \
           on the search depth.");
    doc!(h, "file-type"
        , "Filter by type: f(ile), d(irectory), (sym)l(ink)"
        , "Filter the search by type:\n  \
             'f' or 'file':         regular files\n  \
             'd' or 'directory':    directories\n  \
             'l' or 'symlink':      symbolic links");
    doc!(h, "exec"
        , "Execute the given command for each search result"
        , "Execute the given command for each search result.\n\
           The following are valid tokens that can be used within the expression for generating \
           commands:\n \
             '{}':   places the input in the location of this token\n \
             '{.}':  removes the extension from the input\n \
             '{/}':  places the basename of the input\n \
             '{//}': places the parent of the input\n \
             '{/.}': places the basename of the input, without the extension\n");
    doc!(h, "extension"
        , "Filter by file extension"
        , "(Additionally) filter search results by their file extension.");
    doc!(h, "color"
        , "When to use colors: never, *auto*, always"
        , "Declare when to use color for the pattern match output:\n  \
             'auto':      show colors if the output goes to an interactive console (default)\n  \
             'never':     do not use colorized output\n  \
             'always':    always use colorized output");
    doc!(h, "threads"
        , "Set number of threads to use for searching & executing"
        , "Set number of threads to use for searching & executing (default: number of available \
           CPU cores)");
    doc!(h, "max-buffer-time"
        , "the time (in ms) to buffer, before streaming to the console"
        , "Amount of time in milliseconds to buffer, before streaming the search results to\
           the console.");
    doc!(h, "pattern"
        , "the search pattern, a regular expression (optional)");
    doc!(h, "path"
        , "the root directory for the filesystem search (optional)"
        , "The directory where the filesystem search is rooted (optional). \
           If omitted, search the current working directory.");
    doc!(h, "rg-alias-hidden-ignore"
        , "Alias for no-ignore and/or hidden"
        , "Alias for no-ignore ('u') and no-ignore and hidden ('uu')");

    h
}
<|endoftext|>


<commit_before>mod macros;

const NUM_BYTES: usize = 4096;
const NUM_REGISTERS: usize = 16;
const STACK_SIZE: usize = 48;

const VALUE_MASK: u16 = 0b0000_0000_1111_1111;
const REGISTER_ADDRESS_MASK: u16 = 0b0000_1111_0000_0000;

const TYPE_MASK: u16 = 0b0000_0000_0000_1111;
const LEFT_MASK: u16 = 0b0000_1111_0000_0000;
const RIGHT_MASK: u16 = 0b0000_0000_1111_0000;

#[allow(dead_code)]
pub struct System {
    memory: [u8; NUM_BYTES],
    registers: [u8; NUM_REGISTERS],
    pc: u16,
    index: u16,
    stack: [u8; STACK_SIZE],
    sp: u8
}

#[allow(dead_code)]
impl System{
    pub fn new() -> Self {
        System {
            memory: [0; NUM_BYTES],
            registers: [0; NUM_REGISTERS],
            pc: 0,
            index: 0,
            stack: [0; STACK_SIZE],
            sp: 0
        }
    }

    /** Index into system memory at address and return word located there. */
    pub fn read_word(&self, address: usize) -> u16 {
        let left = self.memory[address] as u16;
        let right = self.memory[address + 1] as u16;
        (left << 8) | right
    }

    /** Execute the instruction. */
    pub fn execute(&mut self, opcode: u16) {
        match opcode {
            0x6000...0x7000 => {    // 0x6XNN : VX = NN
                let register = ((opcode & REGISTER_ADDRESS_MASK) >> 8) as usize;
                let value = (opcode & VALUE_MASK) as u8;
                self.registers[register] = value;
            },
            0x7000...0x8000 => {    // 0x7XNN : VX = VX + NN
                let register = ((opcode & REGISTER_ADDRESS_MASK) >> 8) as usize;
                let value = (opcode & VALUE_MASK) as u8;
                self.registers[register] = self.registers[register].wrapping_add(value);
            },
            0x8000...0x9000 => {
                let left = ((opcode & LEFT_MASK) >> 8) as usize;
                let right = ((opcode & RIGHT_MASK) >> 4) as usize;
                match opcode & TYPE_MASK {
                    0x0 => {    // 0x8XY0 : VX = VY
                        self.registers[left] = self.registers[right];
                    },
                    0x1 => {    // 0x8XY1 : VX = VX | VY
                        self.registers[left] |= self.registers[right];
                    },
                    0x2 => {    // 0x8XY2 : VX = VX & VY
                        self.registers[left] &= self.registers[right];
                    },
                    0x3 => {    // 0x8XY2 : VX = VX ^ VY
                        self.registers[left] ^= self.registers[right];
                    },
                    _ => {
                        eprintln!("Unrecognized instruction!");
                    }
                }
            }
            _ => {
                eprintln!("Unrecognized instruction!");
            }
        }
    }
}

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

    /** Load some test data into the system memory for the purposes of testing. */
    fn load_test_data(system: &mut System) {
        system.memory[0] = 0xAF;
        system.memory[1] = 0x7F;
        system.memory[NUM_BYTES / 2] = 0x77;
        system.memory[NUM_BYTES / 2 + 1] = 0x88;
        system.memory[NUM_BYTES - 2] = 0x3A;
        system.memory[NUM_BYTES - 1] = 0x01;
    }

    /** Set some registers for the purposes of testing. */
    fn set_registers_for_test(system: &mut System) {
        system.execute(0x6064);
        system.execute(0x6127);
        system.execute(0x6212);
        system.execute(0x63AE);
        system.execute(0x64FF);
        system.execute(0x65B4);
        system.execute(0x6642);
        system.execute(0x6F25);
    }

    /** Read a word (two bytes) from the system memory. */
    #[test]
    fn read_word() {
        let mut system = System::new();
        load_test_data(&mut system);
        assert_eq!(0xAF7F, system.read_word(0));
        assert_eq!(0x7788, system.read_word(NUM_BYTES / 2));
        assert_eq!(0x3A01, system.read_word(NUM_BYTES - 2));
    }

    /** The opcode 0x6XNN should store the constant NN into register VX. */
    #[test]
    fn load_constant() {
        let mut system = System::new();

        system.execute(0x6015);
        assert_eq!(0x15, system.registers[0x0]);

        system.execute(0x6120);
        assert_eq!(0x20, system.registers[0x1]);

        system.execute(0x6225);
        assert_eq!(0x25, system.registers[0x2]);

        system.execute(0x6330);
        assert_eq!(0x30, system.registers[0x3]);

        system.execute(0x6435);
        assert_eq!(0x35, system.registers[0x4]);

        system.execute(0x6540);
        assert_eq!(0x40, system.registers[0x5]);

        system.execute(0x6645);
        assert_eq!(0x45, system.registers[0x6]);

        system.execute(0x6750);
        assert_eq!(0x50, system.registers[0x7]);

        system.execute(0x6855);
        assert_eq!(0x55, system.registers[0x8]);

        system.execute(0x6960);
        assert_eq!(0x60, system.registers[0x9]);

        system.execute(0x6A65);
        assert_eq!(0x65, system.registers[0xA]);

        system.execute(0x6B70);
        assert_eq!(0x70, system.registers[0xB]);

        system.execute(0x6C75);
        assert_eq!(0x75, system.registers[0xC]);

        system.execute(0x6D80);
        assert_eq!(0x80, system.registers[0xD]);

        system.execute(0x6E85);
        assert_eq!(0x85, system.registers[0xE]);

        system.execute(0x6F90);
        assert_eq!(0x90, system.registers[0xF]);
    }

    /** The opcode 0x7XNN should add the constant NN into register VX. */
    #[test]
    fn add_constant() {
        let mut system = System::new();

        system.execute(0x6015);
        system.execute(0x7015);
        assert_eq!(0x2A, system.registers[0x0]);

        system.execute(0x6A42);
        system.execute(0x7A42);
        assert_eq!(0x84, system.registers[0xA]);

        system.execute(0x6EFF);
        system.execute(0x7E01);
        // registers should overlow appropriately
        assert_eq!(0x00, system.registers[0xE]);
    }

    /** The opcode 0x8XY0 should copy the value from register VY into register VX. */
    #[test]
    fn copy_register() {
        let mut system = System::new();

        system.execute(0x6A42);
        system.execute(0x8EA0);
        assert_eq!(0x42, system.registers[0xA]);
        assert_eq!(0x42, system.registers[0xE]);

        system.execute(0x67DE);
        system.execute(0x8F70);
        assert_eq!(0xDE, system.registers[0x7]);
        assert_eq!(0xDE, system.registers[0xF]);
    }

    /** The opcode 0x8XY1 should set register VX to the value (VX OR VY). */
    #[test]
    fn oring_register() {
        let mut system = System::new();
        set_registers_for_test(&mut system);

        system.execute(0x8011);
        assert_eq!(0x67, system.registers[0x0]);
        assert_eq!(0x27, system.registers[0x1]);

        system.execute(0x8231);
        assert_eq!(0xBE, system.registers[0x2]);
        assert_eq!(0xAE, system.registers[0x3]);

        system.execute(0x8FE1);
        assert_eq!(0x25, system.registers[0xF]);
        assert_eq!(0x00, system.registers[0xE]);
    }

    /** The opcode 0x8XY2 should set register VX to the value (VX AND VY). */
    #[test]
    fn anding_register() {
        let mut system = System::new();
        set_registers_for_test(&mut system);

        system.execute(0x8012);
        assert_eq!(0x24, system.registers[0x0]);
        assert_eq!(0x27, system.registers[0x1]);

        system.execute(0x8232);
        assert_eq!(0x02, system.registers[0x2]);
        assert_eq!(0xAE, system.registers[0x3]);

        system.execute(0x8FE2);
        assert_eq!(0x00, system.registers[0xF]);
        assert_eq!(0x00, system.registers[0xE]);
    }

    /** The opcode 0x8XY3 should set register VX to the value (VX XOR VY). */
    #[test]
    fn xoring_register() {
        let mut system = System::new();
        set_registers_for_test(&mut system);

        system.execute(0x8013);
        assert_eq!(0x43, system.registers[0x0]);
        assert_eq!(0x27, system.registers[0x1]);

        system.execute(0x8233);
        assert_eq!(0xBC, system.registers[0x2]);
        assert_eq!(0xAE, system.registers[0x3]);

        system.execute(0x8FE3);
        assert_eq!(0x25, system.registers[0xF]);
        assert_eq!(0x00, system.registers[0xE]);
    }
}
<commit_msg>add and sub with overflow<commit_after>mod macros;

const NUM_BYTES: usize = 4096;
const NUM_REGISTERS: usize = 16;
const STACK_SIZE: usize = 48;

const VALUE_MASK: u16 = 0b0000_0000_1111_1111;
const REGISTER_ADDRESS_MASK: u16 = 0b0000_1111_0000_0000;

const TYPE_MASK: u16 = 0b0000_0000_0000_1111;
const LEFT_MASK: u16 = 0b0000_1111_0000_0000;
const RIGHT_MASK: u16 = 0b0000_0000_1111_0000;

#[allow(dead_code)]
pub struct System {
    memory: [u8; NUM_BYTES],
    registers: [u8; NUM_REGISTERS],
    pc: u16,
    index: u16,
    stack: [u8; STACK_SIZE],
    sp: u8
}

#[allow(dead_code)]
impl System{
    pub fn new() -> Self {
        System {
            memory: [0; NUM_BYTES],
            registers: [0; NUM_REGISTERS],
            pc: 0,
            index: 0,
            stack: [0; STACK_SIZE],
            sp: 0
        }
    }

    /** Index into system memory at address and return word located there. */
    pub fn read_word(&self, address: usize) -> u16 {
        let left = self.memory[address] as u16;
        let right = self.memory[address + 1] as u16;
        (left << 8) | right
    }

    /** Execute the instruction. */
    pub fn execute(&mut self, opcode: u16) {
        match opcode {

            0x6000...0x7000 => {    // 0x6XNN : VX = NN
                let register = ((opcode & REGISTER_ADDRESS_MASK) >> 8) as usize;
                let value = (opcode & VALUE_MASK) as u8;
                self.registers[register] = value;
            },

            0x7000...0x8000 => {    // 0x7XNN : VX = VX + NN
                let register = ((opcode & REGISTER_ADDRESS_MASK) >> 8) as usize;
                let value = (opcode & VALUE_MASK) as u8;
                self.registers[register] = self.registers[register].wrapping_add(value);
            },

            0x8000...0x9000 => {
                let left = ((opcode & LEFT_MASK) >> 8) as usize;
                let right = ((opcode & RIGHT_MASK) >> 4) as usize;
                match opcode & TYPE_MASK {

                    0x0 => {    // 0x8XY0 : VX = VY
                        self.registers[left] = self.registers[right];
                    },

                    0x1 => {    // 0x8XY1 : VX = VX | VY
                        self.registers[left] |= self.registers[right];
                    },

                    0x2 => {    // 0x8XY2 : VX = VX & VY
                        self.registers[left] &= self.registers[right];
                    },

                    0x3 => {    // 0x8XY3 : VX = VX ^ VY
                        self.registers[left] ^= self.registers[right];
                    },

                    0x4 => {    // 0x8XY4 : VX = VX + VY
                        let (value, overflow) =
                            self.registers[left].overflowing_add(self.registers[right]);
                        self.registers[left] = value;
                        if overflow {
                            self.registers[0xF] = 0x1;
                        }
                    },

                    0x5 => {    // 0x8XY5 : VX = VX - VY
                        let (value, overflow) =
                            self.registers[left].overflowing_sub(self.registers[right]);
                        self.registers[left] = value;
                        if overflow {
                            self.registers[0xF] = 0x1;
                        }
                    },

                    0x7 => {    // 0x8XY7 : VY = VY - VX
                        let (value, overflow) =
                            self.registers[right].overflowing_sub(self.registers[left]);
                        self.registers[right] = value;
                        if overflow {
                            self.registers[0xF] = 0x1;
                        }
                    },

                    _ => {
                        eprintln!("Unrecognized instruction!");
                    }
                }
            }

            _ => {
                eprintln!("Unrecognized instruction!");
            }
        }
    }
}

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

    /** Load some test data into the system memory for the purposes of testing. */
    fn load_test_data(system: &mut System) {
        system.memory[0] = 0xAF;
        system.memory[1] = 0x7F;
        system.memory[NUM_BYTES / 2] = 0x77;
        system.memory[NUM_BYTES / 2 + 1] = 0x88;
        system.memory[NUM_BYTES - 2] = 0x3A;
        system.memory[NUM_BYTES - 1] = 0x01;
    }

    /** Set some registers for the purposes of testing. */
    fn set_registers_for_test(system: &mut System) {
        system.execute(0x6064);
        system.execute(0x6127);
        system.execute(0x6212);
        system.execute(0x63AE);
        system.execute(0x64FF);
        system.execute(0x65B4);
        system.execute(0x6642);
        system.execute(0x6F25);
    }

    /** Read a word (two bytes) from the system memory. */
    #[test]
    fn read_word() {
        let mut system = System::new();
        load_test_data(&mut system);
        assert_eq!(0xAF7F, system.read_word(0));
        assert_eq!(0x7788, system.read_word(NUM_BYTES / 2));
        assert_eq!(0x3A01, system.read_word(NUM_BYTES - 2));
    }

    /** The opcode 0x6XNN should store the constant NN into register VX. */
    #[test]
    fn load_constant() {
        let mut system = System::new();

        system.execute(0x6015);
        assert_eq!(0x15, system.registers[0x0]);

        system.execute(0x6120);
        assert_eq!(0x20, system.registers[0x1]);

        system.execute(0x6225);
        assert_eq!(0x25, system.registers[0x2]);

        system.execute(0x6330);
        assert_eq!(0x30, system.registers[0x3]);

        system.execute(0x6435);
        assert_eq!(0x35, system.registers[0x4]);

        system.execute(0x6540);
        assert_eq!(0x40, system.registers[0x5]);

        system.execute(0x6645);
        assert_eq!(0x45, system.registers[0x6]);

        system.execute(0x6750);
        assert_eq!(0x50, system.registers[0x7]);

        system.execute(0x6855);
        assert_eq!(0x55, system.registers[0x8]);

        system.execute(0x6960);
        assert_eq!(0x60, system.registers[0x9]);

        system.execute(0x6A65);
        assert_eq!(0x65, system.registers[0xA]);

        system.execute(0x6B70);
        assert_eq!(0x70, system.registers[0xB]);

        system.execute(0x6C75);
        assert_eq!(0x75, system.registers[0xC]);

        system.execute(0x6D80);
        assert_eq!(0x80, system.registers[0xD]);

        system.execute(0x6E85);
        assert_eq!(0x85, system.registers[0xE]);

        system.execute(0x6F90);
        assert_eq!(0x90, system.registers[0xF]);
    }

    /** The opcode 0x7XNN should add the constant NN into register VX. */
    #[test]
    fn add_constant() {
        let mut system = System::new();

        system.execute(0x6015);
        system.execute(0x7015);
        assert_eq!(0x2A, system.registers[0x0]);

        system.execute(0x6A42);
        system.execute(0x7A42);
        assert_eq!(0x84, system.registers[0xA]);

        system.execute(0x6EFF);
        system.execute(0x7E01);
        // registers should overlow appropriately
        assert_eq!(0x00, system.registers[0xE]);
    }

    /** The opcode 0x8XY0 should copy the value from register VY into register VX. */
    #[test]
    fn copy_register() {
        let mut system = System::new();

        system.execute(0x6A42);
        system.execute(0x8EA0);
        assert_eq!(0x42, system.registers[0xA]);
        assert_eq!(0x42, system.registers[0xE]);

        system.execute(0x67DE);
        system.execute(0x8F70);
        assert_eq!(0xDE, system.registers[0x7]);
        assert_eq!(0xDE, system.registers[0xF]);
    }

    /** The opcode 0x8XY1 should set register VX to the value (VX OR VY). */
    #[test]
    fn oring_register() {
        let mut system = System::new();
        set_registers_for_test(&mut system);

        system.execute(0x8011);
        assert_eq!(0x67, system.registers[0x0]);
        assert_eq!(0x27, system.registers[0x1]);

        system.execute(0x8231);
        assert_eq!(0xBE, system.registers[0x2]);
        assert_eq!(0xAE, system.registers[0x3]);

        system.execute(0x8FE1);
        assert_eq!(0x25, system.registers[0xF]);
        assert_eq!(0x00, system.registers[0xE]);
    }

    /** The opcode 0x8XY2 should set register VX to the value (VX AND VY). */
    #[test]
    fn anding_register() {
        let mut system = System::new();
        set_registers_for_test(&mut system);

        system.execute(0x8012);
        assert_eq!(0x24, system.registers[0x0]);
        assert_eq!(0x27, system.registers[0x1]);

        system.execute(0x8232);
        assert_eq!(0x02, system.registers[0x2]);
        assert_eq!(0xAE, system.registers[0x3]);

        system.execute(0x8FE2);
        assert_eq!(0x00, system.registers[0xF]);
        assert_eq!(0x00, system.registers[0xE]);
    }

    /** The opcode 0x8XY3 should set register VX to the value (VX XOR VY). */
    #[test]
    fn xoring_register() {
        let mut system = System::new();
        set_registers_for_test(&mut system);

        system.execute(0x8013);
        assert_eq!(0x43, system.registers[0x0]);
        assert_eq!(0x27, system.registers[0x1]);

        system.execute(0x8233);
        assert_eq!(0xBC, system.registers[0x2]);
        assert_eq!(0xAE, system.registers[0x3]);

        system.execute(0x8FE3);
        assert_eq!(0x25, system.registers[0xF]);
        assert_eq!(0x00, system.registers[0xE]);
    }

    /** The opcode 0x8XY4 should add register VY to register VX
      * If a carry occurs, set register VF to 01. */
    #[test]
    fn add_register_with_carry() {
        let mut system = System::new();
        set_registers_for_test(&mut system);
        system.execute(0x6F00);

        system.execute(0x8014);
        assert_eq!(0x8B, system.registers[0x0]);
        assert_eq!(0x00, system.registers[0xF]);

        system.execute(0x8234);
        assert_eq!(0xC0, system.registers[0x2]);
        assert_eq!(0x00, system.registers[0xF]);

        system.execute(0x6502);
        system.execute(0x8454);
        assert_eq!(0x01, system.registers[0x4]);
        // overflow has occured - register VF should be set to 0x01
        assert_eq!(0x01, system.registers[0xF]);
    }

    /** The opcode 0x8XY5 should subtract register VY from register VX
      * If a borrow occurs, set register VF to 01. */
    #[test]
    fn sub_register_with_borrow_right_subtrahend() {
        let mut system = System::new();
        set_registers_for_test(&mut system);
        system.execute(0x6F00);

        system.execute(0x8125);
        assert_eq!(0x15, system.registers[0x1]);
        assert_eq!(0x00, system.registers[0xF]);

        system.execute(0x8455);
        assert_eq!(0x4B, system.registers[0x4]);
        assert_eq!(0x00, system.registers[0xF]);

        system.execute(0x6501);
        system.execute(0x8B55);
        assert_eq!(0xFF, system.registers[0xB]);
        // note - a borrow occurs here because subtrahend > minuend,
            // therefore register VF should be set to 0x01
        assert_eq!(0x01, system.registers[0xF]);
    }

    /** The opcode 0x8XY7 should subtract register VX from register VY
      * If a borrow occurs, set register VF to 01. */
    #[test]
    fn sub_register_with_borrow_left_subtrahend() {
        let mut system = System::new();
        set_registers_for_test(&mut system);
        system.execute(0x6F00);

        system.execute(0x8217);
        assert_eq!(0x15, system.registers[0x1]);
        assert_eq!(0x00, system.registers[0xF]);

        system.execute(0x8547);
        assert_eq!(0x4B, system.registers[0x4]);
        assert_eq!(0x00, system.registers[0xF]);

        system.execute(0x6501);
        system.execute(0x85B7);
        assert_eq!(0xFF, system.registers[0xB]);
        // note - a borrow occurs here because subtrahend > minuend,
            // therefore register VF should be set to 0x01
        assert_eq!(0x01, system.registers[0xF]);
    }
}
<|endoftext|>


<commit_before><commit_msg>Refactor some of the index repository logic<commit_after><|endoftext|>