<commit_before>use std::cell::RefCell;
use std::mem;
use std::ptr;
use std::sync::atomic::{self, AtomicUsize, AtomicBool};
use std::sync::atomic::Ordering::{self, Relaxed, Acquire, Release, SeqCst};
use std::ops::{Deref, DerefMut};

use std::io::stderr;
use std::io::prelude::*;

use cache_padded::CachePadded;

mod garbage;

fn log(s: &str) {
    let _ = stderr().write(s.as_bytes());
    let _ = stderr().write("\n".as_bytes());
}

struct Participants {
    head: AtomicPtr<ParticipantNode>
}

//type ParticipantNode = CachePadded<Participant>;
struct ParticipantNode(Participant);

impl ParticipantNode {
    fn new(p: Participant) -> ParticipantNode {
        ParticipantNode(p)
    }
}

impl Deref for ParticipantNode {
    type Target = Participant;
    fn deref(&self) -> &Participant {
        &self.0
    }
}

impl DerefMut for ParticipantNode {
    fn deref_mut(&mut self) -> &mut Participant {
        &mut self.0
    }
}

struct Participant {
    epoch: AtomicUsize,
    in_critical: AtomicUsize,
    active: AtomicBool,
    garbage: RefCell<garbage::Local>,
    next: AtomicPtr<ParticipantNode>,
}

impl Participants {
    const fn new() -> Participants {
        Participants { head: AtomicPtr::new() }
    }

    fn enroll(&self) -> *const Participant {
        let mut participant = Owned::new(ParticipantNode::new(
            Participant {
                epoch: AtomicUsize::new(0),
                in_critical: AtomicUsize::new(0),
                active: AtomicBool::new(true),
                garbage: RefCell::new(garbage::Local::new()),
                next: AtomicPtr::new(),
            }
        ));
        let ret = &**participant as *const _;
        mem::forget(participant);
        return ret;

        let fake_guard = ();
        let g: &'static Guard = unsafe { mem::transmute(&fake_guard) };
        loop {
            let head = self.head.load(Relaxed, g);
            unsafe { participant.next.store_shared(head, Relaxed) };
            match self.head.cas_and_ref(head, participant, Release, g) {
                Ok(shared) => {
                    let shared: &Participant = &shared;
                    return shared;
                }
                Err(owned) => {
                    participant = owned;
                }
            }
        }
    }

    fn iter<'a>(&'a self, g: &'a Guard) -> Iter<'a> {
        Iter {
            guard: g,
            next: &self.head,
            needs_acq: true,
        }
    }
}

struct Iter<'a> {
    guard: &'a Guard,
    next: &'a AtomicPtr<ParticipantNode>,
    needs_acq: bool,
}

impl<'a> Iterator for Iter<'a> {
    type Item = &'a Participant;
    fn next(&mut self) -> Option<&'a Participant> {
        let mut cur = if self.needs_acq {
            self.needs_acq = false;
            self.next.load(Acquire, self.guard)
        } else {
            self.next.load(Relaxed, self.guard)
        };

        while let Some(n) = cur {
            if !n.active.load(Relaxed) {
                cur = n.next.load(Relaxed, self.guard);
                let unlinked = unsafe { self.next.cas_shared(Some(n), cur, Relaxed) };
                if unlinked { unsafe { self.guard.unlinked(n) } }
                self.next = &n.next;
            } else {
                self.next = &n.next;
                return Some(&n)
            }
        }

        None
    }
}

struct EpochState {
    epoch: CachePadded<AtomicUsize>,
    garbage: [CachePadded<garbage::ConcBag>; 3],
    participants: Participants,
}

unsafe impl Send for EpochState {}
unsafe impl Sync for EpochState {}

impl EpochState {
    const fn new() -> EpochState {
        EpochState {
            epoch: CachePadded::zeroed(),
            garbage: [CachePadded::zeroed(),
                      CachePadded::zeroed(),
                      CachePadded::zeroed()],
            participants: Participants::new(),
        }
    }
}

static EPOCH: EpochState = EpochState::new();

impl Participant {
    fn enter(&self) {
        self.in_critical.store(self.in_critical.load(Relaxed) + 1, Relaxed);
        atomic::fence(SeqCst);

        let epoch = EPOCH.epoch.load(Relaxed);
        let delta = epoch - self.epoch.load(Relaxed);
        if delta > 0 {
            self.epoch.store(epoch, Relaxed);

            unsafe {
                // Note: carefully designed to allow re-entrancy via drop, by
                // performing the drops *after* the borrow_mut() is relinquished

                let gen1 = self.garbage.borrow_mut().collect();
                if delta == 1 {
                    for g in gen1 {
                        mem::drop(g);
                    }
                } else {
                    let gen2 = self.garbage.borrow_mut().collect();

                    for g in gen1 {
                        mem::drop(g);
                    }
                    for g in gen2 {
                        mem::drop(g);
                    }
                }
            }
        }
    }

    fn exit(&self) {
        self.in_critical.store(self.in_critical.load(Relaxed) - 1, Release);
    }

    unsafe fn reclaim<T>(&self, data: *mut T) {
        self.garbage.borrow_mut().reclaim(data);
    }

    fn try_collect(&self) -> bool {
        let cur_epoch = EPOCH.epoch.load(SeqCst);

        let fake_guard = ();
        let g: &'static Guard = unsafe { mem::transmute(&fake_guard) };

        for p in EPOCH.participants.iter(g) {
            if p.in_critical.load(Relaxed) > 0 && p.epoch.load(Relaxed) != cur_epoch {
                return false
            }
        }

        let new_epoch = cur_epoch.wrapping_add(1);
        atomic::fence(Acquire);
        if EPOCH.epoch.compare_and_swap(cur_epoch, new_epoch, SeqCst) != cur_epoch {
            return false
        }

        unsafe {
            EPOCH.garbage[new_epoch.wrapping_add(1) % 3].collect();
            for g in self.garbage.borrow_mut().collect() {
                mem::drop(g);
            }
        }

        true
    }

    fn migrate_garbage(&self) {
        let cur_epoch = self.epoch.load(Relaxed);
        let local = mem::replace(&mut *self.garbage.borrow_mut(), garbage::Local::new());
        EPOCH.garbage[cur_epoch.wrapping_sub(1) % 3].insert(local.old);
        EPOCH.garbage[cur_epoch % 3].insert(local.cur);
    }
}

pub struct Owned<T> {
    data: Box<T>,
}

impl<T> Owned<T> {
    pub fn new(t: T) -> Owned<T> {
        Owned { data: Box::new(t) }
    }

    fn as_raw(&self) -> *mut T {
        self.deref() as *const _ as *mut _
    }
}

impl<T> Deref for Owned<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.data
    }
}

impl<T> DerefMut for Owned<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.data
    }
}

#[derive(PartialEq, Eq)]
pub struct Shared<'a, T: 'a> {
    data: &'a T,
}

impl<'a, T> Copy for Shared<'a, T> {}
impl<'a, T> Clone for Shared<'a, T> {
    fn clone(&self) -> Shared<'a, T> {
        Shared { data: self.data }
    }
}

impl<'a, T> Deref for Shared<'a, T> {
    type Target = &'a T;
    fn deref(&self) -> &&'a T {
        &self.data
    }
}

impl<'a, T> Shared<'a, T> {
    unsafe fn from_raw(raw: *mut T) -> Option<Shared<'a, T>> {
        if raw == ptr::null_mut() { None }
        else {
            Some(Shared {
                data: mem::transmute::<*mut T, &T>(raw)
            })
        }
    }

    unsafe fn from_ref(r: &T) -> Shared<'a, T> {
        Shared { data: mem::transmute(r) }
    }

    unsafe fn from_owned(owned: Owned<T>) -> Shared<'a, T> {
        let ret = Shared::from_ref(owned.deref());
        mem::forget(owned);
        ret
    }

    fn as_raw(&self) -> *mut T {
        self.data as *const _ as *mut _
    }
}

pub struct AtomicPtr<T> {
    ptr: atomic::AtomicPtr<T>,
}

impl<T> Default for AtomicPtr<T> {
    fn default() -> AtomicPtr<T> {
        AtomicPtr { ptr: atomic::AtomicPtr::new(ptr::null_mut()) }
    }
}

fn opt_shared_into_raw<T>(val: Option<Shared<T>>) -> *mut T {
    val.map(|p| p.as_raw()).unwrap_or(ptr::null_mut())
}

fn opt_owned_as_raw<T>(val: &Option<Owned<T>>) -> *mut T {
    val.as_ref().map(Owned::as_raw).unwrap_or(ptr::null_mut())
}

impl<T> AtomicPtr<T> {
    pub const fn new() -> AtomicPtr<T> {
        AtomicPtr { ptr: atomic::AtomicPtr::new(0 as *mut _) }
    }

    pub fn load<'a>(&self, ord: Ordering, _: &'a Guard) -> Option<Shared<'a, T>> {
        unsafe { Shared::from_raw(self.ptr.load(ord)) }
    }

    pub fn store(&self, val: Option<Owned<T>>, ord: Ordering) {
        self.ptr.store(opt_owned_as_raw(&val), ord)
    }

    pub fn store_and_ref<'a>(&self, val: Owned<T>, ord: Ordering, _: &'a Guard) -> Shared<'a, T> {
        unsafe {
            let shared = Shared::from_owned(val);
            self.store_shared(Some(shared), ord);
            shared
        }
    }

    pub unsafe fn store_shared(&self, val: Option<Shared<T>>, ord: Ordering) {
        self.ptr.store(opt_shared_into_raw(val), ord)
    }

    pub fn cas(&self, old: Option<Shared<T>>, new: Option<Owned<T>>, ord: Ordering)
               -> Result<(), Option<Owned<T>>>
    {
        if self.ptr.compare_and_swap(opt_shared_into_raw(old),
                                     opt_owned_as_raw(&new),
                                     ord) == opt_shared_into_raw(old)
        {
            Ok(())
        } else {
            Err(new)
        }
    }

    pub fn cas_and_ref<'a>(&self, old: Option<Shared<T>>, new: Owned<T>,
                           ord: Ordering, _: &'a Guard)
                           -> Result<Shared<'a, T>, Owned<T>>
    {
        if self.ptr.compare_and_swap(opt_shared_into_raw(old), new.as_raw(), ord)
            == opt_shared_into_raw(old)
        {
            Ok(unsafe { Shared::from_owned(new) })
        } else {
            Err(new)
        }
    }

    pub unsafe fn cas_shared(&self, old: Option<Shared<T>>, new: Option<Shared<T>>,
                             ord: Ordering)
                             -> bool
    {
        self.ptr.compare_and_swap(opt_shared_into_raw(old),
                                  opt_shared_into_raw(new),
                                  ord) == opt_shared_into_raw(old)
    }

    pub fn swap<'a>(&self, new: Option<Owned<T>>, ord: Ordering, _: &'a Guard)
                    -> Option<Shared<'a, T>> {
        unsafe { Shared::from_raw(self.ptr.swap(opt_owned_as_raw(&new), ord)) }
    }

    pub fn swap_shared<'a>(&self, new: Option<Shared<T>>, ord: Ordering, _: &'a Guard)
                           -> Option<Shared<'a, T>> {
        unsafe {
            Shared::from_raw(self.ptr.swap(opt_shared_into_raw(new), ord))
        }
    }
}

struct LocalEpoch {
    participant: *const Participant,
}

impl LocalEpoch {
    fn new() -> LocalEpoch {
        LocalEpoch { participant: EPOCH.participants.enroll() }
    }

    fn get(&self) -> &Participant {
        unsafe { &*self.participant }
    }
}

impl Drop for LocalEpoch {
    fn drop(&mut self) {
        let p = self.get();
        p.enter();
        p.try_collect();
        p.migrate_garbage();
        p.exit();
        p.active.store(false, Relaxed);
    }
}

thread_local!(static LOCAL_EPOCH: LocalEpoch = LocalEpoch::new() );

#[must_use]
pub struct Guard {
    _dummy: ()
}

static GC_THRESH: usize = 32;

fn with_participant<F, T>(f: F) -> T where F: FnOnce(&Participant) -> T {
    LOCAL_EPOCH.with(|e| f(e.get()))
}

pub fn garbage_size() -> usize {
    with_participant(|p| p.garbage.borrow().size())
}

pub fn pin() -> Guard {
    let needs_collect = with_participant(|p| {
        p.enter();
        p.garbage.borrow().size() > GC_THRESH
    });
    let g = Guard {
        _dummy: ()
    };

    if needs_collect {
        g.try_collect();
    }

    g
}

impl Guard {
    pub unsafe fn unlinked<T>(&self, val: Shared<T>) {
        with_participant(|p| p.reclaim(val.as_raw()))
    }

    pub fn try_collect(&self) -> bool {
        with_participant(|p| p.try_collect())
    }

    pub fn migrate_garbage(&self) {
        with_participant(|p| p.migrate_garbage())
    }
}

impl Drop for Guard {
    fn drop(&mut self) {
        with_participant(|p| p.exit());
    }
}

impl !Send for Guard {}
impl !Sync for Guard {}

#[cfg(test)]
mod test {
    use super::{Participants, EPOCH};
    use super::*;

    #[test]
    fn smoke_enroll() {
        Participants::new().enroll();
    }

    #[test]
    fn smoke_enroll_EPOCH() {
        EPOCH.participants.enroll();
    }

    #[test]
    fn smoke_guard() {
        let g = pin();
    }
}
<commit_msg>Remove temporary early return<commit_after>use std::cell::RefCell;
use std::mem;
use std::ptr;
use std::sync::atomic::{self, AtomicUsize, AtomicBool};
use std::sync::atomic::Ordering::{self, Relaxed, Acquire, Release, SeqCst};
use std::ops::{Deref, DerefMut};

use std::io::stderr;
use std::io::prelude::*;

use cache_padded::CachePadded;

mod garbage;

fn log(s: &str) {
    let _ = stderr().write(s.as_bytes());
    let _ = stderr().write("\n".as_bytes());
}

struct Participants {
    head: AtomicPtr<ParticipantNode>
}

//type ParticipantNode = CachePadded<Participant>;
struct ParticipantNode(Participant);

impl ParticipantNode {
    fn new(p: Participant) -> ParticipantNode {
        ParticipantNode(p)
    }
}

impl Deref for ParticipantNode {
    type Target = Participant;
    fn deref(&self) -> &Participant {
        &self.0
    }
}

impl DerefMut for ParticipantNode {
    fn deref_mut(&mut self) -> &mut Participant {
        &mut self.0
    }
}

struct Participant {
    epoch: AtomicUsize,
    in_critical: AtomicUsize,
    active: AtomicBool,
    garbage: RefCell<garbage::Local>,
    next: AtomicPtr<ParticipantNode>,
}

impl Participants {
    const fn new() -> Participants {
        Participants { head: AtomicPtr::new() }
    }

    fn enroll(&self) -> *const Participant {
        let mut participant = Owned::new(ParticipantNode::new(
            Participant {
                epoch: AtomicUsize::new(0),
                in_critical: AtomicUsize::new(0),
                active: AtomicBool::new(true),
                garbage: RefCell::new(garbage::Local::new()),
                next: AtomicPtr::new(),
            }
        ));
        let fake_guard = ();
        let g: &'static Guard = unsafe { mem::transmute(&fake_guard) };
        loop {
            let head = self.head.load(Relaxed, g);
            unsafe { participant.next.store_shared(head, Relaxed) };
            match self.head.cas_and_ref(head, participant, Release, g) {
                Ok(shared) => {
                    let shared: &Participant = &shared;
                    return shared;
                }
                Err(owned) => {
                    participant = owned;
                }
            }
        }
    }

    fn iter<'a>(&'a self, g: &'a Guard) -> Iter<'a> {
        Iter {
            guard: g,
            next: &self.head,
            needs_acq: true,
        }
    }
}

struct Iter<'a> {
    guard: &'a Guard,
    next: &'a AtomicPtr<ParticipantNode>,
    needs_acq: bool,
}

impl<'a> Iterator for Iter<'a> {
    type Item = &'a Participant;
    fn next(&mut self) -> Option<&'a Participant> {
        let mut cur = if self.needs_acq {
            self.needs_acq = false;
            self.next.load(Acquire, self.guard)
        } else {
            self.next.load(Relaxed, self.guard)
        };

        while let Some(n) = cur {
            if !n.active.load(Relaxed) {
                cur = n.next.load(Relaxed, self.guard);
                let unlinked = unsafe { self.next.cas_shared(Some(n), cur, Relaxed) };
                if unlinked { unsafe { self.guard.unlinked(n) } }
                self.next = &n.next;
            } else {
                self.next = &n.next;
                return Some(&n)
            }
        }

        None
    }
}

struct EpochState {
    epoch: CachePadded<AtomicUsize>,
    garbage: [CachePadded<garbage::ConcBag>; 3],
    participants: Participants,
}

unsafe impl Send for EpochState {}
unsafe impl Sync for EpochState {}

impl EpochState {
    const fn new() -> EpochState {
        EpochState {
            epoch: CachePadded::zeroed(),
            garbage: [CachePadded::zeroed(),
                      CachePadded::zeroed(),
                      CachePadded::zeroed()],
            participants: Participants::new(),
        }
    }
}

static EPOCH: EpochState = EpochState::new();

impl Participant {
    fn enter(&self) {
        self.in_critical.store(self.in_critical.load(Relaxed) + 1, Relaxed);
        atomic::fence(SeqCst);

        let epoch = EPOCH.epoch.load(Relaxed);
        let delta = epoch - self.epoch.load(Relaxed);
        if delta > 0 {
            self.epoch.store(epoch, Relaxed);

            unsafe {
                // Note: carefully designed to allow re-entrancy via drop, by
                // performing the drops *after* the borrow_mut() is relinquished

                let gen1 = self.garbage.borrow_mut().collect();
                if delta == 1 {
                    for g in gen1 {
                        mem::drop(g);
                    }
                } else {
                    let gen2 = self.garbage.borrow_mut().collect();

                    for g in gen1 {
                        mem::drop(g);
                    }
                    for g in gen2 {
                        mem::drop(g);
                    }
                }
            }
        }
    }

    fn exit(&self) {
        self.in_critical.store(self.in_critical.load(Relaxed) - 1, Release);
    }

    unsafe fn reclaim<T>(&self, data: *mut T) {
        self.garbage.borrow_mut().reclaim(data);
    }

    fn try_collect(&self) -> bool {
        let cur_epoch = EPOCH.epoch.load(SeqCst);

        let fake_guard = ();
        let g: &'static Guard = unsafe { mem::transmute(&fake_guard) };

        for p in EPOCH.participants.iter(g) {
            if p.in_critical.load(Relaxed) > 0 && p.epoch.load(Relaxed) != cur_epoch {
                return false
            }
        }

        let new_epoch = cur_epoch.wrapping_add(1);
        atomic::fence(Acquire);
        if EPOCH.epoch.compare_and_swap(cur_epoch, new_epoch, SeqCst) != cur_epoch {
            return false
        }

        unsafe {
            EPOCH.garbage[new_epoch.wrapping_add(1) % 3].collect();
            for g in self.garbage.borrow_mut().collect() {
                mem::drop(g);
            }
        }

        true
    }

    fn migrate_garbage(&self) {
        let cur_epoch = self.epoch.load(Relaxed);
        let local = mem::replace(&mut *self.garbage.borrow_mut(), garbage::Local::new());
        EPOCH.garbage[cur_epoch.wrapping_sub(1) % 3].insert(local.old);
        EPOCH.garbage[cur_epoch % 3].insert(local.cur);
    }
}

pub struct Owned<T> {
    data: Box<T>,
}

impl<T> Owned<T> {
    pub fn new(t: T) -> Owned<T> {
        Owned { data: Box::new(t) }
    }

    fn as_raw(&self) -> *mut T {
        self.deref() as *const _ as *mut _
    }
}

impl<T> Deref for Owned<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.data
    }
}

impl<T> DerefMut for Owned<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.data
    }
}

#[derive(PartialEq, Eq)]
pub struct Shared<'a, T: 'a> {
    data: &'a T,
}

impl<'a, T> Copy for Shared<'a, T> {}
impl<'a, T> Clone for Shared<'a, T> {
    fn clone(&self) -> Shared<'a, T> {
        Shared { data: self.data }
    }
}

impl<'a, T> Deref for Shared<'a, T> {
    type Target = &'a T;
    fn deref(&self) -> &&'a T {
        &self.data
    }
}

impl<'a, T> Shared<'a, T> {
    unsafe fn from_raw(raw: *mut T) -> Option<Shared<'a, T>> {
        if raw == ptr::null_mut() { None }
        else {
            Some(Shared {
                data: mem::transmute::<*mut T, &T>(raw)
            })
        }
    }

    unsafe fn from_ref(r: &T) -> Shared<'a, T> {
        Shared { data: mem::transmute(r) }
    }

    unsafe fn from_owned(owned: Owned<T>) -> Shared<'a, T> {
        let ret = Shared::from_ref(owned.deref());
        mem::forget(owned);
        ret
    }

    fn as_raw(&self) -> *mut T {
        self.data as *const _ as *mut _
    }
}

pub struct AtomicPtr<T> {
    ptr: atomic::AtomicPtr<T>,
}

impl<T> Default for AtomicPtr<T> {
    fn default() -> AtomicPtr<T> {
        AtomicPtr { ptr: atomic::AtomicPtr::new(ptr::null_mut()) }
    }
}

fn opt_shared_into_raw<T>(val: Option<Shared<T>>) -> *mut T {
    val.map(|p| p.as_raw()).unwrap_or(ptr::null_mut())
}

fn opt_owned_as_raw<T>(val: &Option<Owned<T>>) -> *mut T {
    val.as_ref().map(Owned::as_raw).unwrap_or(ptr::null_mut())
}

impl<T> AtomicPtr<T> {
    pub const fn new() -> AtomicPtr<T> {
        AtomicPtr { ptr: atomic::AtomicPtr::new(0 as *mut _) }
    }

    pub fn load<'a>(&self, ord: Ordering, _: &'a Guard) -> Option<Shared<'a, T>> {
        unsafe { Shared::from_raw(self.ptr.load(ord)) }
    }

    pub fn store(&self, val: Option<Owned<T>>, ord: Ordering) {
        self.ptr.store(opt_owned_as_raw(&val), ord)
    }

    pub fn store_and_ref<'a>(&self, val: Owned<T>, ord: Ordering, _: &'a Guard) -> Shared<'a, T> {
        unsafe {
            let shared = Shared::from_owned(val);
            self.store_shared(Some(shared), ord);
            shared
        }
    }

    pub unsafe fn store_shared(&self, val: Option<Shared<T>>, ord: Ordering) {
        self.ptr.store(opt_shared_into_raw(val), ord)
    }

    pub fn cas(&self, old: Option<Shared<T>>, new: Option<Owned<T>>, ord: Ordering)
               -> Result<(), Option<Owned<T>>>
    {
        if self.ptr.compare_and_swap(opt_shared_into_raw(old),
                                     opt_owned_as_raw(&new),
                                     ord) == opt_shared_into_raw(old)
        {
            Ok(())
        } else {
            Err(new)
        }
    }

    pub fn cas_and_ref<'a>(&self, old: Option<Shared<T>>, new: Owned<T>,
                           ord: Ordering, _: &'a Guard)
                           -> Result<Shared<'a, T>, Owned<T>>
    {
        if self.ptr.compare_and_swap(opt_shared_into_raw(old), new.as_raw(), ord)
            == opt_shared_into_raw(old)
        {
            Ok(unsafe { Shared::from_owned(new) })
        } else {
            Err(new)
        }
    }

    pub unsafe fn cas_shared(&self, old: Option<Shared<T>>, new: Option<Shared<T>>,
                             ord: Ordering)
                             -> bool
    {
        self.ptr.compare_and_swap(opt_shared_into_raw(old),
                                  opt_shared_into_raw(new),
                                  ord) == opt_shared_into_raw(old)
    }

    pub fn swap<'a>(&self, new: Option<Owned<T>>, ord: Ordering, _: &'a Guard)
                    -> Option<Shared<'a, T>> {
        unsafe { Shared::from_raw(self.ptr.swap(opt_owned_as_raw(&new), ord)) }
    }

    pub fn swap_shared<'a>(&self, new: Option<Shared<T>>, ord: Ordering, _: &'a Guard)
                           -> Option<Shared<'a, T>> {
        unsafe {
            Shared::from_raw(self.ptr.swap(opt_shared_into_raw(new), ord))
        }
    }
}

struct LocalEpoch {
    participant: *const Participant,
}

impl LocalEpoch {
    fn new() -> LocalEpoch {
        LocalEpoch { participant: EPOCH.participants.enroll() }
    }

    fn get(&self) -> &Participant {
        unsafe { &*self.participant }
    }
}

impl Drop for LocalEpoch {
    fn drop(&mut self) {
        let p = self.get();
        p.enter();
        p.try_collect();
        p.migrate_garbage();
        p.exit();
        p.active.store(false, Relaxed);
    }
}

thread_local!(static LOCAL_EPOCH: LocalEpoch = LocalEpoch::new() );

#[must_use]
pub struct Guard {
    _dummy: ()
}

static GC_THRESH: usize = 32;

fn with_participant<F, T>(f: F) -> T where F: FnOnce(&Participant) -> T {
    LOCAL_EPOCH.with(|e| f(e.get()))
}

pub fn garbage_size() -> usize {
    with_participant(|p| p.garbage.borrow().size())
}

pub fn pin() -> Guard {
    let needs_collect = with_participant(|p| {
        p.enter();
        p.garbage.borrow().size() > GC_THRESH
    });
    let g = Guard {
        _dummy: ()
    };

    if needs_collect {
        g.try_collect();
    }

    g
}

impl Guard {
    pub unsafe fn unlinked<T>(&self, val: Shared<T>) {
        with_participant(|p| p.reclaim(val.as_raw()))
    }

    pub fn try_collect(&self) -> bool {
        with_participant(|p| p.try_collect())
    }

    pub fn migrate_garbage(&self) {
        with_participant(|p| p.migrate_garbage())
    }
}

impl Drop for Guard {
    fn drop(&mut self) {
        with_participant(|p| p.exit());
    }
}

impl !Send for Guard {}
impl !Sync for Guard {}

#[cfg(test)]
mod test {
    use super::{Participants, EPOCH};
    use super::*;

    #[test]
    fn smoke_enroll() {
        Participants::new().enroll();
    }

    #[test]
    fn smoke_enroll_EPOCH() {
        EPOCH.participants.enroll();
    }

    #[test]
    fn smoke_guard() {
        let g = pin();
    }
}
<|endoftext|>


<commit_before>use std::sync::mpsc;

use platform::time::sleep_secs;
use platform::time::time_now;
use testlib::cmp::eq_f64;

use super::LiveTimers;
use super::MetricsRecorder;
use super::TimeSeries;
use super::Timer;
use super::Timing;

#[test]
#[should_panic]
fn test_live_timers_name_mismatch() {
    let mut lt = LiveTimers::new();

    lt.start("cmd");
    lt.stop("resp"); // panic expected
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_live_timers_ok() {
    let mut lt = LiveTimers::new();

    let t1 = time_now();
    let start_time = lt.start("cmd");
    // start_time is very close to *now*
    assert!(eq_f64(t1, start_time, 0.001));
    // "cmd" -> start_time was added to the map
    assert_eq!(&start_time, lt.get_timers().get("cmd").unwrap());

    sleep_secs(0.25);

    let timing = lt.stop("cmd");
    // the returned start_time matches what we saw before
    assert_eq!(start_time, timing.start_time);
    // the duration is almost exactly the time we slept
    assert!(eq_f64(0.25, timing.duration, 0.001));
    // "cmd" was removed from the map
    assert!(!lt.get_timers().contains_key("cmd"));
}

#[test]
fn test_time_series_updates() {
    let mut ts = TimeSeries::new();

    // add a timer
    ts.add_timing(&Timing::new("cmd", 1.1, 0.25));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("cmd", 1.9, 0.51));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("cmd", 2.3, 8.8));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
            2 => vec![8.8],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("resp", 4.1, 1.0));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
            2 => vec![8.8],
        },
        "resp".to_string() => hashmap!{
            4 => vec![1.0],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // empty the series
    ts.clear();
    // construct the expected value for comparison
    let expected = hashmap!{};
    // compare
    assert_eq!(&expected, ts.get_timers());
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_correct() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        let _t = Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.25, dur, 0.001));
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_wrong_binding() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        // this binding discards the value right away!
        let _ = Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.0, dur, 0.01));
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_no_binding() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        // no binding means Timer does not live past the first line
        Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.0, dur, 0.01));
}
<commit_msg>relax test because travis<commit_after>use std::sync::mpsc;

use platform::time::sleep_secs;
use platform::time::time_now;
use testlib::cmp::eq_f64;

use super::LiveTimers;
use super::MetricsRecorder;
use super::TimeSeries;
use super::Timer;
use super::Timing;

#[test]
#[should_panic]
fn test_live_timers_name_mismatch() {
    let mut lt = LiveTimers::new();

    lt.start("cmd");
    lt.stop("resp"); // panic expected
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_live_timers_ok() {
    let mut lt = LiveTimers::new();

    let t1 = time_now();
    let start_time = lt.start("cmd");
    // start_time is very close to *now*
    assert!(eq_f64(t1, start_time, 0.01));
    // "cmd" -> start_time was added to the map
    assert_eq!(&start_time, lt.get_timers().get("cmd").unwrap());

    sleep_secs(0.25);

    let timing = lt.stop("cmd");
    // the returned start_time matches what we saw before
    assert_eq!(start_time, timing.start_time);
    // the duration is almost exactly the time we slept
    assert!(eq_f64(0.25, timing.duration, 0.01));
    // "cmd" was removed from the map
    assert!(!lt.get_timers().contains_key("cmd"));
}

#[test]
fn test_time_series_updates() {
    let mut ts = TimeSeries::new();

    // add a timer
    ts.add_timing(&Timing::new("cmd", 1.1, 0.25));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("cmd", 1.9, 0.51));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("cmd", 2.3, 8.8));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
            2 => vec![8.8],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("resp", 4.1, 1.0));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
            2 => vec![8.8],
        },
        "resp".to_string() => hashmap!{
            4 => vec![1.0],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // empty the series
    ts.clear();
    // construct the expected value for comparison
    let expected = hashmap!{};
    // compare
    assert_eq!(&expected, ts.get_timers());
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_correct() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        let _t = Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.25, dur, 0.001));
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_wrong_binding() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        // this binding discards the value right away!
        let _ = Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.0, dur, 0.01));
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_no_binding() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        // no binding means Timer does not live past the first line
        Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.0, dur, 0.01));
}
<|endoftext|>


<commit_before>pub mod data_1_8_pre2;
pub mod biome;
pub mod block_state;
pub mod model;
pub mod nbt;
pub mod region;

pub use minecraft::data_1_8_pre2 as data;
use std::env;
use std::fs::{self, File};
use std::io;
use std::path::PathBuf;
use zip::ZipArchive;

fn var(key: &str) -> String {
    match env::var(key) {
        Ok(val) => val,
        Err(err) => panic!("couldn't find env var {}; err: {:?}", key, err)
    }
}

#[cfg(windows)]
pub fn vanilla_root_path() -> PathBuf {
    let appdata = var("appdata");
    let mut buf = PathBuf::from(&appdata);
    buf.push(".minecraft");
    buf
}
#[cfg(target_os = "linux")]
pub fn vanilla_root_path() -> PathBuf {
    let home = var("HOME");
    PathBuf::from(home);
    buf.push(".minecraft");
    buf
}
#[cfg(target_os = "macos")]
pub fn vanilla_root_path() -> PathBuf {
    let home = var("HOME");
    PathBuf::from(home);
    buf.push("Library");
    buf.push("Application Support");
    buf.push("minecraft");
    buf
}

pub fn fetch_assets(version: &str) {
    let mut buf = vanilla_root_path();
    buf.push("versions");
    buf.push(version);
    buf.push(format!("{}.jar", version));

    println!("Opening {:?}...", &buf);
    let file = File::open(&buf).unwrap();
    let mut archive = ZipArchive::new(file).unwrap();
    println!("File {:?} contains {} files.", &buf, archive.len());

    let mut count = 0;
    for i in 0..archive.len() {
        let mut file = archive.by_index(i).unwrap();
        // Won't work because file.name() borrows file 'a lifetime.
        // let path = &PathBuf::from(file.name().trim_right_matches('\0'));
        let path = sanitize_filename(file.name());
        if file.name().starts_with("assets/minecraft") {
            fs::create_dir_all(path.parent().unwrap()).unwrap();

            let mut outfile = File::create(&path).unwrap();
            io::copy(&mut file, &mut outfile).unwrap();
            count += 1
        }
    }

    println!("Extracted {} files.", count);
}

fn sanitize_filename(filename: &str) -> PathBuf {
    // PathBuf::from(filename.trim_right_matches('\0'))
    let no_null_filename = match filename.find('\0') {
        Some(index) => &filename[0..index],
        None => filename,
    };
    PathBuf::from(no_null_filename)
}
<commit_msg>Missing `mut buf` on vanila_root_path for linux and macos<commit_after>pub mod data_1_8_pre2;
pub mod biome;
pub mod block_state;
pub mod model;
pub mod nbt;
pub mod region;

pub use minecraft::data_1_8_pre2 as data;
use std::env;
use std::fs::{self, File};
use std::io;
use std::path::PathBuf;
use zip::ZipArchive;

fn var(key: &str) -> String {
    match env::var(key) {
        Ok(val) => val,
        Err(err) => panic!("couldn't find env var {}; err: {:?}", key, err)
    }
}

#[cfg(windows)]
pub fn vanilla_root_path() -> PathBuf {
    let appdata = var("appdata");
    let mut buf = PathBuf::from(&appdata);
    buf.push(".minecraft");
    buf
}
#[cfg(target_os = "linux")]
pub fn vanilla_root_path() -> PathBuf {
    let home = var("HOME");
    let mut buf = PathBuf::from(home);
    buf.push(".minecraft");
    buf
}
#[cfg(target_os = "macos")]
pub fn vanilla_root_path() -> PathBuf {
    let home = var("HOME");
    let mut buf = PathBuf::from(home);
    buf.push("Library");
    buf.push("Application Support");
    buf.push("minecraft");
    buf
}

pub fn fetch_assets(version: &str) {
    let mut buf = vanilla_root_path();
    buf.push("versions");
    buf.push(version);
    buf.push(format!("{}.jar", version));

    println!("Opening {:?}...", &buf);
    let file = File::open(&buf).unwrap();
    let mut archive = ZipArchive::new(file).unwrap();
    println!("File {:?} contains {} files.", &buf, archive.len());

    let mut count = 0;
    for i in 0..archive.len() {
        let mut file = archive.by_index(i).unwrap();
        // Won't work because file.name() borrows file 'a lifetime.
        // let path = &PathBuf::from(file.name().trim_right_matches('\0'));
        let path = sanitize_filename(file.name());
        if file.name().starts_with("assets/minecraft") {
            fs::create_dir_all(path.parent().unwrap()).unwrap();

            let mut outfile = File::create(&path).unwrap();
            io::copy(&mut file, &mut outfile).unwrap();
            count += 1
        }
    }

    println!("Extracted {} files.", count);
}

fn sanitize_filename(filename: &str) -> PathBuf {
    // PathBuf::from(filename.trim_right_matches('\0'))
    let no_null_filename = match filename.find('\0') {
        Some(index) => &filename[0..index],
        None => filename,
    };
    PathBuf::from(no_null_filename)
}
<|endoftext|>


<commit_before>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Item, ItemTrait};

#[test]
fn test_macro_variable_attr() {
    // mimics the token stream corresponding to `$attr fn f() {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { #[test] })),
        TokenTree::Ident(Ident::new("fn", Span::call_site())),
        TokenTree::Ident(Ident::new("f", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Fn {
        attrs: [
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "test",
                            arguments: None,
                        },
                    ],
                },
                tokens: TokenStream(``),
            },
        ],
        vis: Inherited,
        sig: Signature {
            ident: "f",
            generics: Generics,
            output: Default,
        },
        block: Block,
    }
    "###);
}

#[test]
fn test_negative_impl() {
    // Rustc parses all of the following.

    #[cfg(any())]
    impl ! {}
    let tokens = quote! {
        impl ! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Type::Never,
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !Trait {}
    let tokens = quote! {
        impl !Trait {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! Trait`),
    }
    "###);

    #[cfg(any())]
    impl !Trait for T {}
    let tokens = quote! {
        impl !Trait for T {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            Some,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "T",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !! {}
    let tokens = quote! {
        impl !! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! !`),
    }
    "###);
}

#[test]
fn test_macro_variable_impl() {
    // mimics the token stream corresponding to `impl $trait for $ty {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("impl", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Trait))),
        TokenTree::Ident(Ident::new("for", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Type))),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            None,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Group {
            elem: Type::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Type",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);
}

#[test]
fn test_supertraits() {
    // Rustc parses all of the following.

    #[rustfmt::skip]
    let tokens = quote!(trait Trait where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: Sized where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
        supertraits: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Sized",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: Sized + where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
        supertraits: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Sized",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);
}

#[test]
fn test_type_empty_bounds() {
    #[rustfmt::skip]
    let tokens = quote! {
        trait Foo {
            type Bar: ;
        }
    };

    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Foo",
        generics: Generics,
        items: [
            TraitItem::Type {
                ident: "Bar",
                generics: Generics,
                colon_token: Some,
            },
        ],
    }
    "###);
}
<commit_msg>Add impl visibility test<commit_after>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Item, ItemTrait};

#[test]
fn test_macro_variable_attr() {
    // mimics the token stream corresponding to `$attr fn f() {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { #[test] })),
        TokenTree::Ident(Ident::new("fn", Span::call_site())),
        TokenTree::Ident(Ident::new("f", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Fn {
        attrs: [
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "test",
                            arguments: None,
                        },
                    ],
                },
                tokens: TokenStream(``),
            },
        ],
        vis: Inherited,
        sig: Signature {
            ident: "f",
            generics: Generics,
            output: Default,
        },
        block: Block,
    }
    "###);
}

#[test]
fn test_negative_impl() {
    // Rustc parses all of the following.

    #[cfg(any())]
    impl ! {}
    let tokens = quote! {
        impl ! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Type::Never,
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !Trait {}
    let tokens = quote! {
        impl !Trait {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! Trait`),
    }
    "###);

    #[cfg(any())]
    impl !Trait for T {}
    let tokens = quote! {
        impl !Trait for T {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            Some,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "T",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !! {}
    let tokens = quote! {
        impl !! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! !`),
    }
    "###);
}

#[test]
fn test_macro_variable_impl() {
    // mimics the token stream corresponding to `impl $trait for $ty {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("impl", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Trait))),
        TokenTree::Ident(Ident::new("for", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Type))),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            None,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Group {
            elem: Type::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Type",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);
}

#[test]
fn test_supertraits() {
    // Rustc parses all of the following.

    #[rustfmt::skip]
    let tokens = quote!(trait Trait where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: Sized where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
        supertraits: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Sized",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: Sized + where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
        supertraits: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Sized",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);
}

#[test]
fn test_type_empty_bounds() {
    #[rustfmt::skip]
    let tokens = quote! {
        trait Foo {
            type Bar: ;
        }
    };

    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Foo",
        generics: Generics,
        items: [
            TraitItem::Type {
                ident: "Bar",
                generics: Generics,
                colon_token: Some,
            },
        ],
    }
    "###);
}

#[test]
fn test_impl_visibility() {
    let tokens = quote! {
        pub default unsafe impl union {}
    };

    snapshot!(tokens as Item, @"Verbatim(`pub default unsafe impl union { }`)");
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]

extern crate aster;
extern crate syntax;

use syntax::abi::Abi;
use syntax::ast;
use syntax::codemap::{DUMMY_SP, Spanned, respan};
use syntax::parse::token;
use syntax::ptr::P;

use aster::AstBuilder;
use aster::ident::ToIdent;

#[test]
fn test_fn() {
    let builder = AstBuilder::new();

    let block = builder.block()
        .stmt().let_id("x").isize(1)
        .stmt().let_id("y").isize(2)
        .expr().add().id("x").id("y");

    let fn_ = builder.item().fn_("foo")
        .return_().isize()
        .build(block.clone());

    assert_eq!(
        fn_,
        P(ast::Item {
            ident: builder.id("foo"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemFn(
                builder.fn_decl().return_().isize(),
                ast::Unsafety::Normal,
                Abi::Rust,
                builder.generics().build(),
                block
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_generic_fn() {
    let builder = AstBuilder::new();

    let block = builder.block()
        .stmt().let_id("x").isize(1)
        .stmt().let_id("y").isize(2)
        .expr().add().id("x").id("y");

    let fn_ = builder.item().fn_("foo")
        .return_().isize()
        .generics()
            .lifetime("'a").build()
            .lifetime("'b").bound("'a").build()
            .ty_param("T").build()
            .build()
        .build(block.clone());

    assert_eq!(
        fn_,
        P(ast::Item {
            ident: builder.id("foo"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemFn(
                builder.fn_decl().return_().isize(),
                ast::Unsafety::Normal,
                Abi::Rust,
                builder.generics()
                    .lifetime("'a").build()
                    .lifetime("'b").bound("'a").build()
                    .ty_param("T").build()
                    .build(),
                block
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_empty_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().struct_("Struct").build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                builder.struct_def().build(),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().struct_("Struct")
        .field("x").isize()
        .field("y").isize()
        .build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                builder.struct_def()
                    .field("x").isize()
                    .field("y").isize()
                    .build(),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_tuple_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().tuple_struct("Struct")
        .ty().isize()
        .ty().isize()
        .build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                P(ast::StructDef {
                    fields: vec![
                        Spanned {
                            span: DUMMY_SP,
                            node: ast::StructField_ {
                                kind: ast::UnnamedField(
                                    ast::Inherited,
                                ),
                                id: ast::DUMMY_NODE_ID,
                                ty: builder.ty().isize(),
                                attrs: vec![],
                            },
                        },
                        Spanned {
                            span: DUMMY_SP,
                            node: ast::StructField_ {
                                kind: ast::UnnamedField(
                                    ast::Inherited,
                                ),
                                id: ast::DUMMY_NODE_ID,
                                ty: builder.ty().isize(),
                                attrs: vec![],
                            },
                        },
                    ],
                    ctor_id: Some(ast::DUMMY_NODE_ID),
                }),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_empty_enum() {
    let builder = AstBuilder::new();
    let enum_= builder.item().enum_("Enum").build();

    assert_eq!(
        enum_,
        P(ast::Item {
            ident: builder.id("Enum"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemEnum(
                ast::EnumDef {
                    variants: vec![],
                },
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_enum() {
    let builder = AstBuilder::new();
    let enum_= builder.item().enum_("Enum")
        .id("A")
        .tuple("B").build()
        .tuple("C")
            .ty().isize()
            .build()
        .tuple("D")
            .ty().isize()
            .ty().isize()
            .build()
        .struct_("E")
            .field("a").isize()
            .build()
        .struct_("F")
            .field("a").isize()
            .field("b").isize()
            .build()
        .build();

    assert_eq!(
        enum_,
        P(ast::Item {
            ident: builder.id("Enum"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemEnum(
                ast::EnumDef {
                    variants: vec![
                        builder.variant("A").tuple().build(),
                        builder.variant("B").tuple().build(),
                        builder.variant("C").tuple()
                            .ty().isize()
                            .build(),
                        builder.variant("D").tuple()
                            .ty().isize()
                            .ty().isize()
                            .build(),
                        builder.variant("E").struct_()
                            .field("a").isize()
                            .build(),
                        builder.variant("F").struct_()
                            .field("a").isize()
                            .field("b").isize()
                            .build(),
                    ],
                },
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_use() {
    fn check(item: P<ast::Item>, view_path: ast::ViewPath_) {
        assert_eq!(
            item,
            P(ast::Item {
                ident: token::special_idents::invalid,
                attrs: vec![],
                id: ast::DUMMY_NODE_ID,
                node: ast::ItemUse(
                    P(respan(DUMMY_SP, view_path))
                ),
                vis: ast::Inherited,
                span: DUMMY_SP,
            })
        );
    }

    let builder = AstBuilder::new();

    let item = builder.item().use_()
        .ids(&["std", "vec", "Vec"]).build()
        .build();

    check(
        item,
        ast::ViewPathSimple(
            "Vec".to_ident(),
            builder.path().ids(&["std", "vec", "Vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec", "Vec"]).build()
        .as_("MyVec");

    check(
        item,
        ast::ViewPathSimple(
            "MyVec".to_ident(),
            builder.path().ids(&["std", "vec", "Vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .glob();

    check(
        item,
        ast::ViewPathGlob(
            builder.path().ids(&["std", "vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .list()
        .build();

    check(
        item,
        ast::ViewPathList(
            builder.path().ids(&["std", "vec"]).build(),
            vec![],
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .list()
        .self_()
        .id("Vec")
        .id("IntoIter")
        .build();

    check(
        item,
        ast::ViewPathList(
            builder.path().ids(&["std", "vec"]).build(),
            vec![
                respan(DUMMY_SP, ast::PathListMod {
                    id: ast::DUMMY_NODE_ID,
                }),
                respan(DUMMY_SP, ast::PathListIdent {
                    name: "Vec".to_ident(),
                    id: ast::DUMMY_NODE_ID,
                }),
                respan(DUMMY_SP, ast::PathListIdent {
                    name: "IntoIter".to_ident(),
                    id: ast::DUMMY_NODE_ID,
                }),
            ],
        )
    );
}
<commit_msg>Whitespace cleanup<commit_after>#![feature(rustc_private)]

extern crate aster;
extern crate syntax;

use syntax::abi::Abi;
use syntax::ast;
use syntax::codemap::{DUMMY_SP, Spanned, respan};
use syntax::parse::token;
use syntax::ptr::P;

use aster::AstBuilder;
use aster::ident::ToIdent;

#[test]
fn test_fn() {
    let builder = AstBuilder::new();

    let block = builder.block()
        .stmt().let_id("x").isize(1)
        .stmt().let_id("y").isize(2)
        .expr().add().id("x").id("y");

    let fn_ = builder.item().fn_("foo")
        .return_().isize()
        .build(block.clone());

    assert_eq!(
        fn_,
        P(ast::Item {
            ident: builder.id("foo"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemFn(
                builder.fn_decl().return_().isize(),
                ast::Unsafety::Normal,
                Abi::Rust,
                builder.generics().build(),
                block
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_generic_fn() {
    let builder = AstBuilder::new();

    let block = builder.block()
        .stmt().let_id("x").isize(1)
        .stmt().let_id("y").isize(2)
        .expr().add().id("x").id("y");

    let fn_ = builder.item().fn_("foo")
        .return_().isize()
        .generics()
            .lifetime("'a").build()
            .lifetime("'b").bound("'a").build()
            .ty_param("T").build()
            .build()
        .build(block.clone());

    assert_eq!(
        fn_,
        P(ast::Item {
            ident: builder.id("foo"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemFn(
                builder.fn_decl().return_().isize(),
                ast::Unsafety::Normal,
                Abi::Rust,
                builder.generics()
                    .lifetime("'a").build()
                    .lifetime("'b").bound("'a").build()
                    .ty_param("T").build()
                    .build(),
                block
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_empty_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().struct_("Struct").build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                builder.struct_def().build(),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().struct_("Struct")
        .field("x").isize()
        .field("y").isize()
        .build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                builder.struct_def()
                    .field("x").isize()
                    .field("y").isize()
                    .build(),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_tuple_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().tuple_struct("Struct")
        .ty().isize()
        .ty().isize()
        .build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                P(ast::StructDef {
                    fields: vec![
                        Spanned {
                            span: DUMMY_SP,
                            node: ast::StructField_ {
                                kind: ast::UnnamedField(
                                    ast::Inherited,
                                ),
                                id: ast::DUMMY_NODE_ID,
                                ty: builder.ty().isize(),
                                attrs: vec![],
                            },
                        },
                        Spanned {
                            span: DUMMY_SP,
                            node: ast::StructField_ {
                                kind: ast::UnnamedField(
                                    ast::Inherited,
                                ),
                                id: ast::DUMMY_NODE_ID,
                                ty: builder.ty().isize(),
                                attrs: vec![],
                            },
                        },
                    ],
                    ctor_id: Some(ast::DUMMY_NODE_ID),
                }),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_empty_enum() {
    let builder = AstBuilder::new();
    let enum_= builder.item().enum_("Enum").build();

    assert_eq!(
        enum_,
        P(ast::Item {
            ident: builder.id("Enum"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemEnum(
                ast::EnumDef {
                    variants: vec![],
                },
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_enum() {
    let builder = AstBuilder::new();
    let enum_= builder.item().enum_("Enum")
        .id("A")
        .tuple("B").build()
        .tuple("C")
            .ty().isize()
            .build()
        .tuple("D")
            .ty().isize()
            .ty().isize()
            .build()
        .struct_("E")
            .field("a").isize()
            .build()
        .struct_("F")
            .field("a").isize()
            .field("b").isize()
            .build()
        .build();

    assert_eq!(
        enum_,
        P(ast::Item {
            ident: builder.id("Enum"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemEnum(
                ast::EnumDef {
                    variants: vec![
                        builder.variant("A").tuple().build(),
                        builder.variant("B").tuple().build(),
                        builder.variant("C").tuple()
                            .ty().isize()
                            .build(),
                        builder.variant("D").tuple()
                            .ty().isize()
                            .ty().isize()
                            .build(),
                        builder.variant("E").struct_()
                            .field("a").isize()
                            .build(),
                        builder.variant("F").struct_()
                            .field("a").isize()
                            .field("b").isize()
                            .build(),
                    ],
                },
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_use() {
    fn check(item: P<ast::Item>, view_path: ast::ViewPath_) {
        assert_eq!(
            item,
            P(ast::Item {
                ident: token::special_idents::invalid,
                attrs: vec![],
                id: ast::DUMMY_NODE_ID,
                node: ast::ItemUse(
                    P(respan(DUMMY_SP, view_path))
                ),
                vis: ast::Inherited,
                span: DUMMY_SP,
            })
        );
    }

    let builder = AstBuilder::new();

    let item = builder.item().use_()
        .ids(&["std", "vec", "Vec"]).build()
        .build();

    check(
        item,
        ast::ViewPathSimple(
            "Vec".to_ident(),
            builder.path().ids(&["std", "vec", "Vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec", "Vec"]).build()
        .as_("MyVec");

    check(
        item,
        ast::ViewPathSimple(
            "MyVec".to_ident(),
            builder.path().ids(&["std", "vec", "Vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .glob();

    check(
        item,
        ast::ViewPathGlob(
            builder.path().ids(&["std", "vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .list()
        .build();

    check(
        item,
        ast::ViewPathList(
            builder.path().ids(&["std", "vec"]).build(),
            vec![],
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .list()
        .self_()
        .id("Vec")
        .id("IntoIter")
        .build();

    check(
        item,
        ast::ViewPathList(
            builder.path().ids(&["std", "vec"]).build(),
            vec![
                respan(DUMMY_SP, ast::PathListMod {
                    id: ast::DUMMY_NODE_ID,
                }),
                respan(DUMMY_SP, ast::PathListIdent {
                    name: "Vec".to_ident(),
                    id: ast::DUMMY_NODE_ID,
                }),
                respan(DUMMY_SP, ast::PathListIdent {
                    name: "IntoIter".to_ident(),
                    id: ast::DUMMY_NODE_ID,
                }),
            ],
        )
    );
}
<|endoftext|>


<commit_before>use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use clap::ArgMatches;

use runtime::Runtime;
use module::Module;

use storage::parser::FileHeaderParser;
use storage::parser::Parser;
use storage::json::parser::JsonHeaderParser;

pub struct BM<'a> {
    rt: &'a Runtime<'a>,
}

impl<'a> BM<'a> {

    pub fn new(rt: &'a Runtime<'a>) -> BM<'a> {
        BM {
            rt: rt,
        }
    }

    fn runtime(&self) -> &Runtime {
        &self.rt
    }

    fn command_add(&self, matches: &ArgMatches) -> bool {
        use self::header::build_header;

        let parser = Parser::new(JsonHeaderParser::new(None));

        let url    = matches.value_of("url").map(String::from).unwrap(); // clap ensures this is present
        let tags   = matches.value_of("tags").and_then(|s| {
            Some(s.split(",").map(String::from).collect())
        }).unwrap_or(vec![]);

        debug!("Building header with");
        debug!("    url  = '{:?}'", url);
        debug!("    tags = '{:?}'", tags);
        let header = build_header(url, tags);

        let fileid = self.rt.store().new_file_with_header(self, header);
        self.rt.store().load(&fileid).and_then(|file| {
            info!("Created file in memory: {}", fileid);
            Some(self.rt.store().persist(&parser, file))
        }).unwrap_or(false)
    }

    fn command_list(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_remove(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

}

impl<'a> Module<'a> for BM<'a> {

    fn exec(&self, matches: &ArgMatches) -> bool {
        match matches.subcommand_name() {
            Some("add") => {
                self.command_add(matches.subcommand_matches("add").unwrap())
            },

            Some("list") => {
                self.command_list(matches.subcommand_matches("list").unwrap())
            },

            Some("remove") => {
                self.command_remove(matches.subcommand_matches("remove").unwrap())
            },

            Some(_) | None => {
                info!("No command given, doing nothing");
                false
            },
        }
    }

    fn name(&self) -> &'static str {
        "bm"
    }
}

impl<'a> Debug for BM<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "BM");
        Ok(())
    }

}

<commit_msg>Fix: BM module name<commit_after>use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use clap::ArgMatches;

use runtime::Runtime;
use module::Module;

use storage::parser::FileHeaderParser;
use storage::parser::Parser;
use storage::json::parser::JsonHeaderParser;

pub struct BM<'a> {
    rt: &'a Runtime<'a>,
}

impl<'a> BM<'a> {

    pub fn new(rt: &'a Runtime<'a>) -> BM<'a> {
        BM {
            rt: rt,
        }
    }

    fn runtime(&self) -> &Runtime {
        &self.rt
    }

    fn command_add(&self, matches: &ArgMatches) -> bool {
        use self::header::build_header;

        let parser = Parser::new(JsonHeaderParser::new(None));

        let url    = matches.value_of("url").map(String::from).unwrap(); // clap ensures this is present
        let tags   = matches.value_of("tags").and_then(|s| {
            Some(s.split(",").map(String::from).collect())
        }).unwrap_or(vec![]);

        debug!("Building header with");
        debug!("    url  = '{:?}'", url);
        debug!("    tags = '{:?}'", tags);
        let header = build_header(url, tags);

        let fileid = self.rt.store().new_file_with_header(self, header);
        self.rt.store().load(&fileid).and_then(|file| {
            info!("Created file in memory: {}", fileid);
            Some(self.rt.store().persist(&parser, file))
        }).unwrap_or(false)
    }

    fn command_list(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_remove(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

}

impl<'a> Module<'a> for BM<'a> {

    fn exec(&self, matches: &ArgMatches) -> bool {
        match matches.subcommand_name() {
            Some("add") => {
                self.command_add(matches.subcommand_matches("add").unwrap())
            },

            Some("list") => {
                self.command_list(matches.subcommand_matches("list").unwrap())
            },

            Some("remove") => {
                self.command_remove(matches.subcommand_matches("remove").unwrap())
            },

            Some(_) | None => {
                info!("No command given, doing nothing");
                false
            },
        }
    }

    fn name(&self) -> &'static str {
        "bookmark"
    }
}

impl<'a> Debug for BM<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "BM");
        Ok(())
    }

}

<|endoftext|>


<commit_before>/*
 * Rust BareBones OS
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * main.rs
 * - Top-level file for kernel
 *
 * This code has been put into the public domain, there are no restrictions on
 * its use, and the author takes no liability.
 */
#![no_std]	//< Kernels can't use std
#![feature(lang_items)]	//< unwind needs to define lang items
#![feature(asm)]	//< As a kernel, we need inline assembly

use prelude::*;

// Load libcore (it's nice and freestanding)
// - We want the macros from libcore
#[macro_use]
extern crate core;

/// A dummy 'std' module to work around a set of issues in rustc
mod std {
	// #18491 - write!() expands to std::fmt::Arguments::new
	pub use core::fmt;
}

/// Macros, need to be loaded before everything else due to how rust parses
#[macro_use]
mod macros;

// Achitecture-specific modules
#[cfg(arch__amd64)] #[path="arch/amd64/mod.rs"]
pub mod arch;
#[cfg(arch__x86)] #[path="arch/x86/mod.rs"]
pub mod arch;

// Prelude
mod prelude;

/// Exception handling (panic)
pub mod unwind;

/// Logging code
mod logging;

// Kernel entrypoint
#[lang="start"]
#[no_mangle]
fn kmain()
{
	log!("Hello world!");
	loop {}
}

<commit_msg>Minor tweaks suggested by Tobba<commit_after>/*
 * Rust BareBones OS
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * main.rs
 * - Top-level file for kernel
 *
 * This code has been put into the public domain, there are no restrictions on
 * its use, and the author takes no liability.
 */
#![no_std]	//< Kernels can't use std
#![feature(lang_items)]	//< unwind needs to define lang items
#![feature(asm)]	//< As a kernel, we need inline assembly

use prelude::*;

// Load libcore (it's nice and freestanding)
// - We want the macros from libcore
#[macro_use]
extern crate core;

/// A dummy 'std' module to work around a set of issues in rustc
mod std {
	// #18491 - write!() expands to std::fmt::Arguments::new
	pub use core::fmt;
	// #16803 - #[derive] references std::cmp
	pub use core::cmp;
}

/// Macros, need to be loaded before everything else due to how rust parses
#[macro_use]
mod macros;

// Achitecture-specific modules
#[cfg(target_arch="x86_64")] #[path="arch/amd64/mod.rs"]
pub mod arch;
#[cfg(target_arch="x86")] #[path="arch/x86/mod.rs"]
pub mod arch;

// Prelude
mod prelude;

/// Exception handling (panic)
pub mod unwind;

/// Logging code
mod logging;

// Kernel entrypoint
#[lang="start"]
#[no_mangle]
fn kmain()
{
	log!("Hello world!");
	loop {}
}

<|endoftext|>


<commit_before>use std::{env, fs, io};
use std::path::Path;
use std::process::{Command, ExitStatus, exit};

#[derive(Debug, Clone)]
struct Metric<'a> {
    name: &'a str,
    prepare: &'a str,
    cmd: &'a str,
}

impl Metric<'_> {
    fn outfile(&self, project: &str) -> String {
        [self.name, "_", project, ".json"].join("")
    }
}

fn main() {
    // TODO args lib
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("please provide the target projects directory");
        exit(1);
    }
    let projects_directory = &args[1];

    // to add a new metric to the test suite, simply define it in this list:
    let metrics: Vec<Metric> = vec![
        Metric { name:"parse", prepare: "rm -rf target/", cmd: "dbt parse --no-version-check" },
    ];

    // list out all projects
    let path = Path::new(&projects_directory);
    let project_entries = fs::read_dir(path).unwrap();

    let results: Result<Vec<ExitStatus>, io::Error > = project_entries.map(|entry| {
        metrics.clone().into_iter().map(|metric| {
            let path = entry.as_ref().unwrap().path();
            let project_name = &path.file_name().and_then(|x| x.to_str()).unwrap();

            Command::new("hyperfine")
                .current_dir(&path)
                // warms filesystem caches by running the command first without counting it.
                // alternatively we could clear them before each run
                .arg("--warmup")
                .arg("1")
                .arg("--prepare")
                .arg(metric.prepare)
                .arg([metric.cmd, " --profiles-dir ", &projects_directory, "/../project_config/"].join(""))
                .arg("--export-json")
                .arg([&projects_directory, "/", &metric.outfile(project_name)].join(""))
                // this prevents capture dbt output. Noisy, but good for debugging when tests fail.
                .arg("--show-output")
                .status() // use spawn() here instead for more information
        }).collect::<Vec<Result<ExitStatus, io::Error>>>()
    }).flatten().collect();

    // only exit with status code 0 if everything ran as expected
    match results {
        // if dispatch of any of the commands failed, panic with that error
        Err(e) => panic!("{:?}", e),
        Ok(statuses) => {
            for status in statuses {
                match status.code() {
                    None => (),
                    Some(0) => (),
                    // if any child command exited with a non zero status code, exit with the same one here.
                    Some(nonzero) => exit(nonzero),
                }
            }
            // everything ran as expected
            exit(0);
        },
    }
}
<commit_msg>update profiles dir path<commit_after>use std::path::Path;
use std::process::{exit, Command, ExitStatus};
use std::{env, fs, io};

#[derive(Debug, Clone)]
struct Metric<'a> {
    name: &'a str,
    prepare: &'a str,
    cmd: &'a str,
}

impl Metric<'_> {
    fn outfile(&self, project: &str) -> String {
        [self.name, "_", project, ".json"].join("")
    }
}

fn main() {
    // TODO args lib
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("please provide the target projects directory");
        exit(1);
    }
    let projects_directory = &args[1];

    // to add a new metric to the test suite, simply define it in this list:
    let metrics: Vec<Metric> = vec![Metric {
        name: "parse",
        prepare: "rm -rf target/",
        cmd: "dbt parse --no-version-check",
    }];

    // list out all projects
    let path = Path::new(&projects_directory);
    let project_entries = fs::read_dir(path).unwrap();

    let results: Result<Vec<ExitStatus>, io::Error> = project_entries
        .map(|entry| {
            metrics
                .clone()
                .into_iter()
                .map(|metric| {
                    let path = entry.as_ref().unwrap().path();
                    let project_name = &path.file_name().and_then(|x| x.to_str()).unwrap();

                    Command::new("hyperfine")
                        .current_dir(&path)
                        // warms filesystem caches by running the command first without counting it.
                        // alternatively we could clear them before each run
                        .arg("--warmup")
                        .arg("1")
                        .arg("--prepare")
                        .arg(metric.prepare)
                        .arg([metric.cmd, " --profiles-dir ", "../../project_config/"].join(""))
                        .arg("--export-json")
                        .arg([&projects_directory, "/", &metric.outfile(project_name)].join(""))
                        // this prevents capture dbt output. Noisy, but good for debugging when tests fail.
                        .arg("--show-output")
                        .status() // use spawn() here instead for more information
                })
                .collect::<Vec<Result<ExitStatus, io::Error>>>()
        })
        .flatten()
        .collect();

    // only exit with status code 0 if everything ran as expected
    match results {
        // if dispatch of any of the commands failed, panic with that error
        Err(e) => panic!("{:?}", e),
        Ok(statuses) => {
            for status in statuses {
                match status.code() {
                    None => (),
                    Some(0) => (),
                    // if any child command exited with a non zero status code, exit with the same one here.
                    Some(nonzero) => exit(nonzero),
                }
            }
            // everything ran as expected
            exit(0);
        }
    }
}
<|endoftext|>


<commit_before>macro_rules! impl_integer_reductions {
    { $name:ident, $scalar:ty } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            Self: crate::LanesAtMost32
        {
            /// Horizontal wrapping add.  Computes the sum of the lanes of the vector, with wrapping addition.
            #[inline]
            pub fn wrapping_sum(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0) }
            }

            /// Horizontal wrapping multiply.  Computes the product of the lanes of the vector, with wrapping multiplication.
            #[inline]
            pub fn wrapping_product(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1) }
            }

            /// Horizontal bitwise "and".  Computes the cumulative bitwise "and" across the lanes of
            /// the vector.
            #[inline]
            pub fn horizontal_and(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_and(self) }
            }

            /// Horizontal bitwise "or".  Computes the cumulative bitwise "or" across the lanes of
            /// the vector.
            #[inline]
            pub fn horizontal_or(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_or(self) }
            }

            /// Horizontal bitwise "xor".  Computes the cumulative bitwise "xor" across the lanes of
            /// the vector.
            #[inline]
            pub fn horizontal_xor(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_xor(self) }
            }

            /// Horizontal maximum.  Computes the maximum lane in the vector.
            #[inline]
            pub fn horizontal_max(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_max(self) }
            }

            /// Horizontal minimum.  Computes the minimum lane in the vector.
            #[inline]
            pub fn horizontal_min(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_min(self) }
            }
        }
    }
}

macro_rules! impl_float_reductions {
    { $name:ident, $scalar:ty } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            Self: crate::LanesAtMost32
        {

            /// Horizontal add.  Computes the sum of the lanes of the vector.
            #[inline]
            pub fn sum(self) -> $scalar {
                // LLVM sum is inaccurate on i586
                if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
                    self.as_slice().iter().sum()
                } else {
                    unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0.) }
                }
            }

            /// Horizontal multiply.  Computes the sum of the lanes of the vector.
            #[inline]
            pub fn product(self) -> $scalar {
                // LLVM product is inaccurate on i586
                if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
                    self.as_slice().iter().product()
                } else {
                    unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1.) }
                }
            }

            /// Horizontal maximum.  Computes the maximum lane in the vector.
            ///
            /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
            /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
            #[inline]
            pub fn horizontal_max(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_max(self) }
            }

            /// Horizontal minimum.  Computes the minimum lane in the vector.
            ///
            /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
            /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
            #[inline]
            pub fn horizontal_min(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_min(self) }
            }
        }
    }
}

macro_rules! impl_full_mask_reductions {
    { $name:ident, $inner:ident } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            crate::$inner<LANES>: crate::LanesAtMost32
        {
            /// Returns true if any lane is set, or false otherwise.
            #[inline]
            pub fn any(self) -> bool {
                unsafe { crate::intrinsics::simd_reduce_any(self.to_int()) }
            }

            /// Returns true if all lanes are set, or false otherwise.
            #[inline]
            pub fn all(self) -> bool {
                unsafe { crate::intrinsics::simd_reduce_all(self.to_int()) }
            }
        }
    }
}

macro_rules! impl_opaque_mask_reductions {
    { $name:ident, $inner:ident, $bits_ty:ident } => {
        impl<const LANES: usize> $name<LANES>
        where
            $bits_ty<LANES>: crate::LanesAtMost32
        {
            /// Returns true if any lane is set, or false otherwise.
            #[inline]
            pub fn any(self) -> bool {
                self.0.any()
            }

            /// Returns true if all lanes are set, or false otherwise.
            #[inline]
            pub fn all(self) -> bool {
                self.0.all()
            }
        }
    }
}

impl<const LANES: usize> crate::BitMask<LANES>
where
    crate::BitMask<LANES>: crate::LanesAtMost32,
{
    /// Returns true if any lane is set, or false otherwise.
    #[inline]
    pub fn any(self) -> bool {
        self != Self::splat(false)
    }

    /// Returns true if all lanes are set, or false otherwise.
    #[inline]
    pub fn all(self) -> bool {
        self == Self::splat(true)
    }
}
<commit_msg>Update docs<commit_after>macro_rules! impl_integer_reductions {
    { $name:ident, $scalar:ty } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            Self: crate::LanesAtMost32
        {
            /// Horizontal wrapping add.  Returns the sum of the lanes of the vector, with wrapping addition.
            #[inline]
            pub fn wrapping_sum(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0) }
            }

            /// Horizontal wrapping multiply.  Returns the product of the lanes of the vector, with wrapping multiplication.
            #[inline]
            pub fn wrapping_product(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1) }
            }

            /// Horizontal bitwise "and".  Returns the cumulative bitwise "and" across the lanes of
            /// the vector.
            #[inline]
            pub fn horizontal_and(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_and(self) }
            }

            /// Horizontal bitwise "or".  Returns the cumulative bitwise "or" across the lanes of
            /// the vector.
            #[inline]
            pub fn horizontal_or(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_or(self) }
            }

            /// Horizontal bitwise "xor".  Returns the cumulative bitwise "xor" across the lanes of
            /// the vector.
            #[inline]
            pub fn horizontal_xor(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_xor(self) }
            }

            /// Horizontal maximum.  Returns the maximum lane in the vector.
            #[inline]
            pub fn horizontal_max(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_max(self) }
            }

            /// Horizontal minimum.  Returns the minimum lane in the vector.
            #[inline]
            pub fn horizontal_min(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_min(self) }
            }
        }
    }
}

macro_rules! impl_float_reductions {
    { $name:ident, $scalar:ty } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            Self: crate::LanesAtMost32
        {

            /// Horizontal add.  Returns the sum of the lanes of the vector.
            #[inline]
            pub fn sum(self) -> $scalar {
                // LLVM sum is inaccurate on i586
                if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
                    self.as_slice().iter().sum()
                } else {
                    unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0.) }
                }
            }

            /// Horizontal multiply.  Returns the product of the lanes of the vector.
            #[inline]
            pub fn product(self) -> $scalar {
                // LLVM product is inaccurate on i586
                if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
                    self.as_slice().iter().product()
                } else {
                    unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1.) }
                }
            }

            /// Horizontal maximum.  Returns the maximum lane in the vector.
            ///
            /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
            /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
            #[inline]
            pub fn horizontal_max(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_max(self) }
            }

            /// Horizontal minimum.  Returns the minimum lane in the vector.
            ///
            /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
            /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
            #[inline]
            pub fn horizontal_min(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_min(self) }
            }
        }
    }
}

macro_rules! impl_full_mask_reductions {
    { $name:ident, $inner:ident } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            crate::$inner<LANES>: crate::LanesAtMost32
        {
            /// Returns true if any lane is set, or false otherwise.
            #[inline]
            pub fn any(self) -> bool {
                unsafe { crate::intrinsics::simd_reduce_any(self.to_int()) }
            }

            /// Returns true if all lanes are set, or false otherwise.
            #[inline]
            pub fn all(self) -> bool {
                unsafe { crate::intrinsics::simd_reduce_all(self.to_int()) }
            }
        }
    }
}

macro_rules! impl_opaque_mask_reductions {
    { $name:ident, $inner:ident, $bits_ty:ident } => {
        impl<const LANES: usize> $name<LANES>
        where
            $bits_ty<LANES>: crate::LanesAtMost32
        {
            /// Returns true if any lane is set, or false otherwise.
            #[inline]
            pub fn any(self) -> bool {
                self.0.any()
            }

            /// Returns true if all lanes are set, or false otherwise.
            #[inline]
            pub fn all(self) -> bool {
                self.0.all()
            }
        }
    }
}

impl<const LANES: usize> crate::BitMask<LANES>
where
    crate::BitMask<LANES>: crate::LanesAtMost32,
{
    /// Returns true if any lane is set, or false otherwise.
    #[inline]
    pub fn any(self) -> bool {
        self != Self::splat(false)
    }

    /// Returns true if all lanes are set, or false otherwise.
    #[inline]
    pub fn all(self) -> bool {
        self == Self::splat(true)
    }
}
<|endoftext|>