<commit_before>use crate::syntax::{
    Array, ExternFn, Impl, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
};
use std::hash::{Hash, Hasher};
use std::mem;
use std::ops::{Deref, DerefMut};

impl PartialEq for Include {
    fn eq(&self, other: &Include) -> bool {
        let Include {
            path,
            kind,
            begin_span: _,
            end_span: _,
        } = self;
        let Include {
            path: path2,
            kind: kind2,
            begin_span: _,
            end_span: _,
        } = other;
        path == path2 && kind == kind2
    }
}

impl Deref for ExternFn {
    type Target = Signature;

    fn deref(&self) -> &Self::Target {
        &self.sig
    }
}

impl DerefMut for ExternFn {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.sig
    }
}

impl Hash for Type {
    fn hash<H: Hasher>(&self, state: &mut H) {
        mem::discriminant(self).hash(state);
        match self {
            Type::Ident(t) => t.hash(state),
            Type::RustBox(t) => t.hash(state),
            Type::UniquePtr(t) => t.hash(state),
            Type::SharedPtr(t) => t.hash(state),
            Type::WeakPtr(t) => t.hash(state),
            Type::Ref(t) => t.hash(state),
            Type::Str(t) => t.hash(state),
            Type::RustVec(t) => t.hash(state),
            Type::CxxVector(t) => t.hash(state),
            Type::Fn(t) => t.hash(state),
            Type::SliceRef(t) => t.hash(state),
            Type::Array(t) => t.hash(state),
            Type::Void(_) => {}
        }
    }
}

impl Eq for Type {}

impl PartialEq for Type {
    fn eq(&self, other: &Type) -> bool {
        match (self, other) {
            (Type::Ident(lhs), Type::Ident(rhs)) => lhs == rhs,
            (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
            (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
            (Type::SharedPtr(lhs), Type::SharedPtr(rhs)) => lhs == rhs,
            (Type::WeakPtr(lhs), Type::WeakPtr(rhs)) => lhs == rhs,
            (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
            (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
            (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
            (Type::CxxVector(lhs), Type::CxxVector(rhs)) => lhs == rhs,
            (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
            (Type::SliceRef(lhs), Type::SliceRef(rhs)) => lhs == rhs,
            (Type::Void(_), Type::Void(_)) => true,
            (_, _) => false,
        }
    }
}

impl Eq for Lifetimes {}

impl PartialEq for Lifetimes {
    fn eq(&self, other: &Lifetimes) -> bool {
        let Lifetimes {
            lt_token: _,
            lifetimes,
            gt_token: _,
        } = self;
        let Lifetimes {
            lt_token: _,
            lifetimes: lifetimes2,
            gt_token: _,
        } = other;
        lifetimes.iter().eq(lifetimes2)
    }
}

impl Hash for Lifetimes {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Lifetimes {
            lt_token: _,
            lifetimes,
            gt_token: _,
        } = self;
        lifetimes.len().hash(state);
        for lifetime in lifetimes {
            lifetime.hash(state);
        }
    }
}

impl Eq for Ty1 {}

impl PartialEq for Ty1 {
    fn eq(&self, other: &Ty1) -> bool {
        let Ty1 {
            name,
            langle: _,
            inner,
            rangle: _,
        } = self;
        let Ty1 {
            name: name2,
            langle: _,
            inner: inner2,
            rangle: _,
        } = other;
        name == name2 && inner == inner2
    }
}

impl Hash for Ty1 {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Ty1 {
            name,
            langle: _,
            inner,
            rangle: _,
        } = self;
        name.hash(state);
        inner.hash(state);
    }
}

impl Eq for Ref {}

impl PartialEq for Ref {
    fn eq(&self, other: &Ref) -> bool {
        let Ref {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            inner,
            pin_tokens: _,
            mutability: _,
        } = self;
        let Ref {
            pinned: pinned2,
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            inner: inner2,
            pin_tokens: _,
            mutability: _,
        } = other;
        pinned == pinned2 && lifetime == lifetime2 && mutable == mutable2 && inner == inner2
    }
}

impl Hash for Ref {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Ref {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            inner,
            pin_tokens: _,
            mutability: _,
        } = self;
        pinned.hash(state);
        lifetime.hash(state);
        mutable.hash(state);
        inner.hash(state);
    }
}

impl Eq for SliceRef {}

impl PartialEq for SliceRef {
    fn eq(&self, other: &SliceRef) -> bool {
        let SliceRef {
            ampersand: _,
            lifetime,
            mutable,
            bracket: _,
            inner,
            mutability: _,
        } = self;
        let SliceRef {
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            bracket: _,
            inner: inner2,
            mutability: _,
        } = other;
        lifetime == lifetime2 && mutable == mutable2 && inner == inner2
    }
}

impl Hash for SliceRef {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let SliceRef {
            ampersand: _,
            lifetime,
            mutable,
            bracket: _,
            inner,
            mutability: _,
        } = self;
        lifetime.hash(state);
        mutable.hash(state);
        inner.hash(state);
    }
}

impl Eq for Array {}

impl PartialEq for Array {
    fn eq(&self, other: &Array) -> bool {
        let Array {
            bracket: _,
            inner,
            semi_token: _,
            len,
            len_token: _,
        } = self;
        let Array {
            bracket: _,
            inner: inner2,
            semi_token: _,
            len: len2,
            len_token: _,
        } = other;
        inner == inner2 && len == len2
    }
}

impl Hash for Array {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Array {
            bracket: _,
            inner,
            semi_token: _,
            len,
            len_token: _,
        } = self;
        inner.hash(state);
        len.hash(state);
    }
}

impl Eq for Signature {}

impl PartialEq for Signature {
    fn eq(&self, other: &Signature) -> bool {
        let Signature {
            unsafety,
            fn_token: _,
            generics: _,
            receiver,
            args,
            ret,
            throws,
            paren_token: _,
            throws_tokens: _,
        } = self;
        let Signature {
            unsafety: unsafety2,
            fn_token: _,
            generics: _,
            receiver: receiver2,
            args: args2,
            ret: ret2,
            throws: throws2,
            paren_token: _,
            throws_tokens: _,
        } = other;
        unsafety.is_some() == unsafety2.is_some()
            && receiver == receiver2
            && ret == ret2
            && throws == throws2
            && args.len() == args2.len()
            && args.iter().zip(args2).all(|(arg, arg2)| arg == arg2)
    }
}

impl Hash for Signature {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Signature {
            unsafety,
            fn_token: _,
            generics: _,
            receiver,
            args,
            ret,
            throws,
            paren_token: _,
            throws_tokens: _,
        } = self;
        unsafety.is_some().hash(state);
        receiver.hash(state);
        for arg in args {
            arg.hash(state);
        }
        ret.hash(state);
        throws.hash(state);
    }
}

impl Eq for Var {}

impl PartialEq for Var {
    fn eq(&self, other: &Var) -> bool {
        let Var {
            doc: _,
            attrs: _,
            visibility: _,
            ident,
            ty,
        } = self;
        let Var {
            doc: _,
            attrs: _,
            visibility: _,
            ident: ident2,
            ty: ty2,
        } = other;
        ident == ident2 && ty == ty2
    }
}

impl Hash for Var {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Var {
            doc: _,
            attrs: _,
            visibility: _,
            ident,
            ty,
        } = self;
        ident.hash(state);
        ty.hash(state);
    }
}

impl Eq for Receiver {}

impl PartialEq for Receiver {
    fn eq(&self, other: &Receiver) -> bool {
        let Receiver {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            var: _,
            ty,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = self;
        let Receiver {
            pinned: pinned2,
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            var: _,
            ty: ty2,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = other;
        pinned == pinned2 && lifetime == lifetime2 && mutable == mutable2 && ty == ty2
    }
}

impl Hash for Receiver {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Receiver {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            var: _,
            ty,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = self;
        pinned.hash(state);
        lifetime.hash(state);
        mutable.hash(state);
        ty.hash(state);
    }
}

impl Hash for Impl {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Impl {
            impl_token: _,
            generics,
            negative,
            ty,
            brace_token: _,
            negative_token: _,
        } = self;
        generics.hash(state);
        if *negative {
            negative.hash(state);
        }
        ty.hash(state);
    }
}

impl Eq for Impl {}

impl PartialEq for Impl {
    fn eq(&self, other: &Impl) -> bool {
        let Impl {
            impl_token: _,
            generics,
            negative,
            ty,
            brace_token: _,
            negative_token: _,
        } = self;
        let Impl {
            impl_token: _,
            generics: generics2,
            negative: negative2,
            ty: ty2,
            brace_token: _,
            negative_token: _,
        } = other;
        generics == generics2 && negative == negative2 && ty == ty2
    }
}
<commit_msg>Avoid hashing arg names in hash of function signature<commit_after>use crate::syntax::{
    Array, ExternFn, Impl, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
};
use std::hash::{Hash, Hasher};
use std::mem;
use std::ops::{Deref, DerefMut};

impl PartialEq for Include {
    fn eq(&self, other: &Include) -> bool {
        let Include {
            path,
            kind,
            begin_span: _,
            end_span: _,
        } = self;
        let Include {
            path: path2,
            kind: kind2,
            begin_span: _,
            end_span: _,
        } = other;
        path == path2 && kind == kind2
    }
}

impl Deref for ExternFn {
    type Target = Signature;

    fn deref(&self) -> &Self::Target {
        &self.sig
    }
}

impl DerefMut for ExternFn {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.sig
    }
}

impl Hash for Type {
    fn hash<H: Hasher>(&self, state: &mut H) {
        mem::discriminant(self).hash(state);
        match self {
            Type::Ident(t) => t.hash(state),
            Type::RustBox(t) => t.hash(state),
            Type::UniquePtr(t) => t.hash(state),
            Type::SharedPtr(t) => t.hash(state),
            Type::WeakPtr(t) => t.hash(state),
            Type::Ref(t) => t.hash(state),
            Type::Str(t) => t.hash(state),
            Type::RustVec(t) => t.hash(state),
            Type::CxxVector(t) => t.hash(state),
            Type::Fn(t) => t.hash(state),
            Type::SliceRef(t) => t.hash(state),
            Type::Array(t) => t.hash(state),
            Type::Void(_) => {}
        }
    }
}

impl Eq for Type {}

impl PartialEq for Type {
    fn eq(&self, other: &Type) -> bool {
        match (self, other) {
            (Type::Ident(lhs), Type::Ident(rhs)) => lhs == rhs,
            (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
            (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
            (Type::SharedPtr(lhs), Type::SharedPtr(rhs)) => lhs == rhs,
            (Type::WeakPtr(lhs), Type::WeakPtr(rhs)) => lhs == rhs,
            (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
            (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
            (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
            (Type::CxxVector(lhs), Type::CxxVector(rhs)) => lhs == rhs,
            (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
            (Type::SliceRef(lhs), Type::SliceRef(rhs)) => lhs == rhs,
            (Type::Void(_), Type::Void(_)) => true,
            (_, _) => false,
        }
    }
}

impl Eq for Lifetimes {}

impl PartialEq for Lifetimes {
    fn eq(&self, other: &Lifetimes) -> bool {
        let Lifetimes {
            lt_token: _,
            lifetimes,
            gt_token: _,
        } = self;
        let Lifetimes {
            lt_token: _,
            lifetimes: lifetimes2,
            gt_token: _,
        } = other;
        lifetimes.iter().eq(lifetimes2)
    }
}

impl Hash for Lifetimes {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Lifetimes {
            lt_token: _,
            lifetimes,
            gt_token: _,
        } = self;
        lifetimes.len().hash(state);
        for lifetime in lifetimes {
            lifetime.hash(state);
        }
    }
}

impl Eq for Ty1 {}

impl PartialEq for Ty1 {
    fn eq(&self, other: &Ty1) -> bool {
        let Ty1 {
            name,
            langle: _,
            inner,
            rangle: _,
        } = self;
        let Ty1 {
            name: name2,
            langle: _,
            inner: inner2,
            rangle: _,
        } = other;
        name == name2 && inner == inner2
    }
}

impl Hash for Ty1 {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Ty1 {
            name,
            langle: _,
            inner,
            rangle: _,
        } = self;
        name.hash(state);
        inner.hash(state);
    }
}

impl Eq for Ref {}

impl PartialEq for Ref {
    fn eq(&self, other: &Ref) -> bool {
        let Ref {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            inner,
            pin_tokens: _,
            mutability: _,
        } = self;
        let Ref {
            pinned: pinned2,
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            inner: inner2,
            pin_tokens: _,
            mutability: _,
        } = other;
        pinned == pinned2 && lifetime == lifetime2 && mutable == mutable2 && inner == inner2
    }
}

impl Hash for Ref {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Ref {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            inner,
            pin_tokens: _,
            mutability: _,
        } = self;
        pinned.hash(state);
        lifetime.hash(state);
        mutable.hash(state);
        inner.hash(state);
    }
}

impl Eq for SliceRef {}

impl PartialEq for SliceRef {
    fn eq(&self, other: &SliceRef) -> bool {
        let SliceRef {
            ampersand: _,
            lifetime,
            mutable,
            bracket: _,
            inner,
            mutability: _,
        } = self;
        let SliceRef {
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            bracket: _,
            inner: inner2,
            mutability: _,
        } = other;
        lifetime == lifetime2 && mutable == mutable2 && inner == inner2
    }
}

impl Hash for SliceRef {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let SliceRef {
            ampersand: _,
            lifetime,
            mutable,
            bracket: _,
            inner,
            mutability: _,
        } = self;
        lifetime.hash(state);
        mutable.hash(state);
        inner.hash(state);
    }
}

impl Eq for Array {}

impl PartialEq for Array {
    fn eq(&self, other: &Array) -> bool {
        let Array {
            bracket: _,
            inner,
            semi_token: _,
            len,
            len_token: _,
        } = self;
        let Array {
            bracket: _,
            inner: inner2,
            semi_token: _,
            len: len2,
            len_token: _,
        } = other;
        inner == inner2 && len == len2
    }
}

impl Hash for Array {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Array {
            bracket: _,
            inner,
            semi_token: _,
            len,
            len_token: _,
        } = self;
        inner.hash(state);
        len.hash(state);
    }
}

impl Eq for Signature {}

impl PartialEq for Signature {
    fn eq(&self, other: &Signature) -> bool {
        let Signature {
            unsafety,
            fn_token: _,
            generics: _,
            receiver,
            args,
            ret,
            throws,
            paren_token: _,
            throws_tokens: _,
        } = self;
        let Signature {
            unsafety: unsafety2,
            fn_token: _,
            generics: _,
            receiver: receiver2,
            args: args2,
            ret: ret2,
            throws: throws2,
            paren_token: _,
            throws_tokens: _,
        } = other;
        unsafety.is_some() == unsafety2.is_some()
            && receiver == receiver2
            && ret == ret2
            && throws == throws2
            && args.len() == args2.len()
            && args.iter().zip(args2).all(|(arg, arg2)| {
                let Var {
                    doc: _,
                    attrs: _,
                    visibility: _,
                    ident: _,
                    ty,
                } = arg;
                let Var {
                    doc: _,
                    attrs: _,
                    visibility: _,
                    ident: _,
                    ty: ty2,
                } = arg2;
                ty == ty2
            })
    }
}

impl Hash for Signature {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Signature {
            unsafety,
            fn_token: _,
            generics: _,
            receiver,
            args,
            ret,
            throws,
            paren_token: _,
            throws_tokens: _,
        } = self;
        unsafety.is_some().hash(state);
        receiver.hash(state);
        for arg in args {
            let Var {
                doc: _,
                attrs: _,
                visibility: _,
                ident: _,
                ty,
            } = arg;
            ty.hash(state);
        }
        ret.hash(state);
        throws.hash(state);
    }
}

impl Eq for Receiver {}

impl PartialEq for Receiver {
    fn eq(&self, other: &Receiver) -> bool {
        let Receiver {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            var: _,
            ty,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = self;
        let Receiver {
            pinned: pinned2,
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            var: _,
            ty: ty2,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = other;
        pinned == pinned2 && lifetime == lifetime2 && mutable == mutable2 && ty == ty2
    }
}

impl Hash for Receiver {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Receiver {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            var: _,
            ty,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = self;
        pinned.hash(state);
        lifetime.hash(state);
        mutable.hash(state);
        ty.hash(state);
    }
}

impl Hash for Impl {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Impl {
            impl_token: _,
            generics,
            negative,
            ty,
            brace_token: _,
            negative_token: _,
        } = self;
        generics.hash(state);
        if *negative {
            negative.hash(state);
        }
        ty.hash(state);
    }
}

impl Eq for Impl {}

impl PartialEq for Impl {
    fn eq(&self, other: &Impl) -> bool {
        let Impl {
            impl_token: _,
            generics,
            negative,
            ty,
            brace_token: _,
            negative_token: _,
        } = self;
        let Impl {
            impl_token: _,
            generics: generics2,
            negative: negative2,
            ty: ty2,
            brace_token: _,
            negative_token: _,
        } = other;
        generics == generics2 && negative == negative2 && ty == ty2
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

//! A bounded tokio [`Handle`]. Only a bounded number of tasks can run
//! concurrently when spawned through this executor, defined by the initial
//! `capacity`.

use futures::future::{Future, FutureExt};
use std::sync::Arc;
use tokio::{
    runtime::Handle,
    sync::{OwnedSemaphorePermit, Semaphore},
    task::JoinHandle,
};

#[derive(Clone, Debug)]
pub struct BoundedExecutor {
    semaphore: Arc<Semaphore>,
    executor: Handle,
}

impl BoundedExecutor {
    /// Create a new `BoundedExecutor` from an existing tokio [`Handle`]
    /// with a maximum concurrent task capacity of `capacity`.
    pub fn new(capacity: usize, executor: Handle) -> Self {
        let semaphore = Arc::new(Semaphore::new(capacity));
        Self {
            semaphore,
            executor,
        }
    }

    /// Spawn a [`Future`] on the `BoundedExecutor`. This function is async and
    /// will block if the executor is at capacity until one of the other spawned
    /// futures completes. This function returns a [`JoinHandle`] that the caller
    /// can `.await` on for the results of the [`Future`].
    pub async fn spawn<F>(&self, f: F) -> JoinHandle<F::Output>
    where
        F: Future + Send + 'static,
        F::Output: Send + 'static,
    {
        let permit = self.semaphore.clone().acquire_owned().await.unwrap();
        self.spawn_with_permit(f, permit)
    }

    /// Try to spawn a [`Future`] on the `BoundedExecutor`. If the `BoundedExecutor`
    /// is at capacity, this will return an `Err(F)`, passing back the future the
    /// caller attempted to spawn. Otherwise, this will spawn the future on the
    /// executor and send back a [`JoinHandle`] that the caller can `.await` on
    /// for the results of the [`Future`].
    pub fn try_spawn<F>(&self, f: F) -> Result<JoinHandle<F::Output>, F>
    where
        F: Future + Send + 'static,
        F::Output: Send + 'static,
    {
        match self.semaphore.clone().try_acquire_owned().ok() {
            Some(permit) => Ok(self.spawn_with_permit(f, permit)),
            None => Err(f),
        }
    }

    fn spawn_with_permit<F>(
        &self,
        f: F,
        spawn_permit: OwnedSemaphorePermit,
    ) -> JoinHandle<F::Output>
    where
        F: Future + Send + 'static,
        F::Output: Send + 'static,
    {
        // Release the permit back to the semaphore when this task completes.
        let f = f.map(move |ret| {
            drop(spawn_permit);
            ret
        });
        self.executor.spawn(f)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use futures::{channel::oneshot, executor::block_on, future::Future};
    use std::{
        sync::atomic::{AtomicU32, Ordering},
        time::Duration,
    };
    use tokio::{runtime::Runtime, time::sleep};

    #[test]
    fn try_spawn() {
        let rt = Runtime::new().unwrap();
        let executor = rt.handle().clone();
        let executor = BoundedExecutor::new(1, executor);

        let (tx1, rx1) = oneshot::channel();
        let (tx2, rx2) = oneshot::channel();

        // executor has a free slot, spawn should succeed

        let f1 = executor.try_spawn(rx1).unwrap();

        // executor is full, try_spawn should return err and give back the task
        // we attempted to spawn

        let rx2 = executor.try_spawn(rx2).unwrap_err();

        // complete f1 future, should open a free slot in executor

        tx1.send(()).unwrap();
        block_on(f1).unwrap().unwrap();

        // should successfully spawn a new task now that the first is complete

        let f2 = executor.try_spawn(rx2).unwrap();

        // cleanup

        tx2.send(()).unwrap();
        block_on(f2).unwrap().unwrap();
    }

    fn yield_task() -> impl Future<Output = ()> {
        sleep(Duration::from_millis(1)).map(|_| ())
    }

    // spawn NUM_TASKS futures on a BoundedExecutor, ensuring that no more than
    // MAX_WORKERS ever enter the critical section.
    #[test]
    fn concurrent_bounded_executor() {
        const MAX_WORKERS: u32 = 20;
        const NUM_TASKS: u32 = 1000;
        static WORKERS: AtomicU32 = AtomicU32::new(0);
        static COMPLETED_TASKS: AtomicU32 = AtomicU32::new(0);

        let rt = Runtime::new().unwrap();
        let executor = rt.handle().clone();
        let executor = BoundedExecutor::new(MAX_WORKERS as usize, executor);

        for _ in 0..NUM_TASKS {
            block_on(executor.spawn(async move {
                // acquired permit, there should only ever be MAX_WORKERS in this
                // critical section

                let prev_workers = WORKERS.fetch_add(1, Ordering::SeqCst);
                assert!(prev_workers < MAX_WORKERS);

                // yield back to the tokio scheduler
                yield_task().await;

                let prev_workers = WORKERS.fetch_sub(1, Ordering::SeqCst);
                assert!(prev_workers > 0 && prev_workers <= MAX_WORKERS);

                COMPLETED_TASKS.fetch_add(1, Ordering::Relaxed);
            }));
        }

        // spin until completed
        loop {
            let completed = COMPLETED_TASKS.load(Ordering::Relaxed);
            if completed == NUM_TASKS {
                break;
            } else {
                std::hint::spin_loop()
            }
        }
    }
}
<commit_msg>[bounded-executor] add spawn_blocking and try_spawn_blocking<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

//! A bounded tokio [`Handle`]. Only a bounded number of tasks can run
//! concurrently when spawned through this executor, defined by the initial
//! `capacity`.

use futures::future::{Future, FutureExt};
use std::sync::Arc;
use tokio::{
    runtime::Handle,
    sync::{OwnedSemaphorePermit, Semaphore},
    task::JoinHandle,
};

#[derive(Clone, Debug)]
pub struct BoundedExecutor {
    semaphore: Arc<Semaphore>,
    executor: Handle,
}

impl BoundedExecutor {
    /// Create a new `BoundedExecutor` from an existing tokio [`Handle`]
    /// with a maximum concurrent task capacity of `capacity`.
    pub fn new(capacity: usize, executor: Handle) -> Self {
        let semaphore = Arc::new(Semaphore::new(capacity));
        Self {
            semaphore,
            executor,
        }
    }

    async fn acquire_permit(&self) -> OwnedSemaphorePermit {
        self.semaphore.clone().acquire_owned().await.unwrap()
    }

    fn try_acquire_permit(&self) -> Option<OwnedSemaphorePermit> {
        self.semaphore.clone().try_acquire_owned().ok()
    }

    /// Spawn a [`Future`] on the `BoundedExecutor`. This function is async and
    /// will block if the executor is at capacity until one of the other spawned
    /// futures completes. This function returns a [`JoinHandle`] that the caller
    /// can `.await` on for the results of the [`Future`].
    pub async fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
    where
        F: Future + Send + 'static,
        F::Output: Send + 'static,
    {
        let permit = self.acquire_permit().await;
        self.executor.spawn(future_with_permit(future, permit))
    }

    /// Try to spawn a [`Future`] on the `BoundedExecutor`. If the `BoundedExecutor`
    /// is at capacity, this will return an `Err(F)`, passing back the future the
    /// caller attempted to spawn. Otherwise, this will spawn the future on the
    /// executor and send back a [`JoinHandle`] that the caller can `.await` on
    /// for the results of the [`Future`].
    pub fn try_spawn<F>(&self, future: F) -> Result<JoinHandle<F::Output>, F>
    where
        F: Future + Send + 'static,
        F::Output: Send + 'static,
    {
        match self.try_acquire_permit() {
            Some(permit) => Ok(self.executor.spawn(future_with_permit(future, permit))),
            None => Err(future),
        }
    }

    /// Like [`BoundedExecutor::spawn`] but spawns the given closure onto a
    /// blocking task (see [`tokio::task::spawn_blocking`] for details).
    pub async fn spawn_blocking<F, R>(&self, func: F) -> JoinHandle<R>
    where
        F: FnOnce() -> R + Send + 'static,
        R: Send + 'static,
    {
        let permit = self.acquire_permit().await;
        self.executor
            .spawn_blocking(function_with_permit(func, permit))
    }

    /// Like [`BoundedExecutor::try_spawn`] but spawns the given closure
    /// onto a blocking task (see [`tokio::task::spawn_blocking`] for details).
    pub async fn try_spawn_blocking<F, R>(&self, func: F) -> Result<JoinHandle<R>, F>
    where
        F: FnOnce() -> R + Send + 'static,
        R: Send + 'static,
    {
        match self.try_acquire_permit() {
            Some(permit) => Ok(self
                .executor
                .spawn_blocking(function_with_permit(func, permit))),
            None => Err(func),
        }
    }
}

/// Wrap a `Future` so it releases the spawn permit back to the semaphore when
/// it completes.
fn future_with_permit<F>(future: F, permit: OwnedSemaphorePermit) -> impl Future<Output = F::Output>
where
    F: Future + Send + 'static,
    F::Output: Send + 'static,
{
    future.map(move |ret| {
        drop(permit);
        ret
    })
}

fn function_with_permit<F, R>(
    func: F,
    permit: OwnedSemaphorePermit,
) -> impl FnOnce() -> R + Send + 'static
where
    F: FnOnce() -> R + Send + 'static,
    R: Send + 'static,
{
    move || {
        let ret = func();
        drop(permit);
        ret
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use futures::{channel::oneshot, executor::block_on, future::Future};
    use std::{
        sync::atomic::{AtomicU32, Ordering},
        time::Duration,
    };
    use tokio::{runtime::Runtime, time::sleep};

    #[test]
    fn try_spawn() {
        let rt = Runtime::new().unwrap();
        let executor = rt.handle().clone();
        let executor = BoundedExecutor::new(1, executor);

        let (tx1, rx1) = oneshot::channel();
        let (tx2, rx2) = oneshot::channel();

        // executor has a free slot, spawn should succeed

        let f1 = executor.try_spawn(rx1).unwrap();

        // executor is full, try_spawn should return err and give back the task
        // we attempted to spawn

        let rx2 = executor.try_spawn(rx2).unwrap_err();

        // complete f1 future, should open a free slot in executor

        tx1.send(()).unwrap();
        block_on(f1).unwrap().unwrap();

        // should successfully spawn a new task now that the first is complete

        let f2 = executor.try_spawn(rx2).unwrap();

        // cleanup

        tx2.send(()).unwrap();
        block_on(f2).unwrap().unwrap();
    }

    fn yield_task() -> impl Future<Output = ()> {
        sleep(Duration::from_millis(1)).map(|_| ())
    }

    // spawn NUM_TASKS futures on a BoundedExecutor, ensuring that no more than
    // MAX_WORKERS ever enter the critical section.
    #[test]
    fn concurrent_bounded_executor() {
        const MAX_WORKERS: u32 = 20;
        const NUM_TASKS: u32 = 1000;
        static WORKERS: AtomicU32 = AtomicU32::new(0);
        static COMPLETED_TASKS: AtomicU32 = AtomicU32::new(0);

        let rt = Runtime::new().unwrap();
        let executor = rt.handle().clone();
        let executor = BoundedExecutor::new(MAX_WORKERS as usize, executor);

        for _ in 0..NUM_TASKS {
            block_on(executor.spawn(async move {
                // acquired permit, there should only ever be MAX_WORKERS in this
                // critical section

                let prev_workers = WORKERS.fetch_add(1, Ordering::SeqCst);
                assert!(prev_workers < MAX_WORKERS);

                // yield back to the tokio scheduler
                yield_task().await;

                let prev_workers = WORKERS.fetch_sub(1, Ordering::SeqCst);
                assert!(prev_workers > 0 && prev_workers <= MAX_WORKERS);

                COMPLETED_TASKS.fetch_add(1, Ordering::Relaxed);
            }));
        }

        // spin until completed
        loop {
            let completed = COMPLETED_TASKS.load(Ordering::Relaxed);
            if completed == NUM_TASKS {
                break;
            } else {
                std::hint::spin_loop()
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::{borrow::Borrow, cmp::Ordering, mem};

const T: usize = 2;
const MAX_LEN: usize = 2 * T - 1;
const MID: usize = T - 1;
const RIGHT: usize = MID + 1;

#[derive(Debug)]
struct KeyValue<K, V> {
    key: K,
    value: V,
}

impl<K: Ord, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &KeyValue<K, V>) -> bool {
        self.key.eq(&other.key)
    }
}

impl<K: Ord, V> Eq for KeyValue<K, V> {}

impl<K: Ord, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &KeyValue<K, V>) -> Option<Ordering> {
        self.key.partial_cmp(&other.key)
    }
}

impl<K: Ord, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.key.cmp(&other.key)
    }
}

#[derive(Default, Debug)]
pub struct NaiveBTree<K: Ord, V> {
    root: Node<K, V>,
    len: usize,
}

impl<K: Ord, V> NaiveBTree<K, V> {
    pub fn insert(&mut self, key: K, value: V) {
        let kv = KeyValue { key, value };

        if let Some((kv, right)) = self.root.insert(kv) {
            let mut new_root = Node::new_leaf(kv);
            mem::swap(&mut new_root, &mut self.root);
            self.root.children = vec![new_root, right];
        }

        self.len += 1;
    }

    pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
    where
        K: Borrow<Q>,
        Q: Ord,
    {
        self.root.find_key(key)
    }
}

#[derive(Default, Debug)]
struct Node<K: Ord, V> {
    values: Vec<KeyValue<K, V>>,
    children: Vec<Node<K, V>>,
}

impl<K: Ord, V> Node<K, V> {
    fn new_leaf(kv: KeyValue<K, V>) -> Self {
        Self {
            values: vec![kv],
            children: vec![],
        }
    }

    fn insert(&mut self, kv: KeyValue<K, V>) -> Option<(KeyValue<K, V>, Node<K, V>)> {
        if !self.is_leaf() {
            let child_index = match self.values.binary_search(&kv) {
                // Just modify value.
                Ok(idx) => {
                    self.values[idx].value = kv.value;
                    return None;
                }

                Err(idx) => idx,
            };

            if let Some((kv, right)) = self.children[child_index].insert(kv) {
                self.children.push(right);
                self.insert_leaf(kv)
            } else {
                None
            }
        } else {
            self.insert_leaf(kv)
        }
    }

    fn find_key<Q: ?Sized>(&self, key: &Q) -> Option<&V>
    where
        K: Borrow<Q>,
        Q: Ord,
    {
        match self
            .values
            .binary_search_by(|probe| key.cmp(probe.key.borrow()).reverse())
        {
            Ok(idx) => Some(&self.values[idx].value),

            Err(child_index) => {
                if child_index < self.children.len() {
                    self.children[child_index].find_key(key)
                } else {
                    None
                }
            }
        }
    }

    fn insert_leaf(&mut self, kv: KeyValue<K, V>) -> Option<(KeyValue<K, V>, Node<K, V>)> {
        self.insert_kv(kv);
        if self.need_split() {
            let right_values = self.values.drain(RIGHT..).collect();
            let right_children = if self.children.len() > RIGHT {
                self.children.drain(RIGHT..).collect()
            } else {
                vec![]
            };
            let mid = self.values.pop().unwrap();

            Some((
                mid,
                Node {
                    values: right_values,
                    children: right_children,
                },
            ))
        } else {
            None
        }
    }

    fn insert_kv(&mut self, kv: KeyValue<K, V>) {
        let idx = match self.values.binary_search(&kv) {
            Ok(idx) => idx,
            Err(idx) => idx,
        };

        self.values.push(kv);
        if idx < self.values.len() {
            // Rotate tail right.
            self.values[idx..].rotate_right(1);
        }
    }

    fn need_split(&self) -> bool {
        self.values.len() == MAX_LEN
    }

    // Indicates whether node is terminal or not.
    fn is_leaf(&self) -> bool {
        self.children.is_empty()
    }
}

#[test]
fn test_insert() {
    let mut map = NaiveBTree::default();

    let kvs = vec![
        (1, "a"),
        (2, "b"),
        (3, "c"),
        (4, "d"),
        (5, "e"),
        (6, "f"),
        (7, "g"),
        (8, "h"),
        (9, "i"),
        (10, "j"),
    ];

    for (key, value) in &kvs {
        map.insert(*key, *value);
    }

    for (key, value) in &kvs {
        assert_eq!(map.get(key), Some(value));
    }

    assert!(map.get(&11).is_none());
}
<commit_msg>Partial remove implementation<commit_after>use std::{borrow::Borrow, cmp::Ordering, mem};

const T: usize = 2;
const MAX_LEN: usize = 2 * T - 1;
const MID: usize = T - 1;
const RIGHT: usize = MID + 1;

#[derive(Debug)]
struct KeyValue<K, V> {
    key: K,
    value: V,
}

impl<K: Ord, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &KeyValue<K, V>) -> bool {
        self.key.eq(&other.key)
    }
}

impl<K: Ord, V> Eq for KeyValue<K, V> {}

impl<K: Ord, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &KeyValue<K, V>) -> Option<Ordering> {
        self.key.partial_cmp(&other.key)
    }
}

impl<K: Ord, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.key.cmp(&other.key)
    }
}

#[derive(Default, Debug)]
pub struct NaiveBTree<K: Ord, V> {
    root: Node<K, V>,
}

impl<K: Ord, V> NaiveBTree<K, V> {
    pub fn insert(&mut self, key: K, value: V) {
        let kv = KeyValue { key, value };

        if let Some((kv, right)) = self.root.insert(kv) {
            let mut new_root = Node::new_leaf(kv);
            mem::swap(&mut new_root, &mut self.root);
            self.root.children = vec![new_root, right];
        }
    }

    pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
    where
        K: Borrow<Q>,
        Q: Ord,
    {
        self.root.find_key(key)
    }

    pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
    where
        K: Borrow<Q>,
        Q: Ord,
        K: std::fmt::Debug,
        V: std::fmt::Debug,
    {
        let (value, state) = self.root.remove(key);
        value
    }
}

#[derive(Debug, PartialEq)]
enum BalanceState {
    Finished,
    UnbalancedLeaf,
}

#[derive(Default, Debug)]
struct Node<K: Ord, V> {
    values: Vec<KeyValue<K, V>>,
    children: Vec<Node<K, V>>,
}

impl<K: Ord, V> Node<K, V> {
    fn new_leaf(kv: KeyValue<K, V>) -> Self {
        Self {
            values: vec![kv],
            children: vec![],
        }
    }

    fn insert(&mut self, kv: KeyValue<K, V>) -> Option<(KeyValue<K, V>, Node<K, V>)> {
        if !self.is_leaf() {
            let child_index = match self.values.binary_search(&kv) {
                // Just modify value.
                Ok(idx) => {
                    self.values[idx].value = kv.value;
                    return None;
                }

                Err(idx) => idx,
            };

            if let Some((kv, right)) = self.children[child_index].insert(kv) {
                self.children.push(right);
                self.insert_leaf(kv)
            } else {
                None
            }
        } else {
            self.insert_leaf(kv)
        }
    }

    fn find_key<Q: ?Sized>(&self, key: &Q) -> Option<&V>
    where
        K: Borrow<Q>,
        Q: Ord,
    {
        match self
            .values
            .binary_search_by(|probe| key.cmp(probe.key.borrow()).reverse())
        {
            Ok(idx) => Some(&self.values[idx].value),

            Err(child_index) => {
                if child_index < self.children.len() {
                    self.children[child_index].find_key(key)
                } else {
                    None
                }
            }
        }
    }

    fn insert_leaf(&mut self, kv: KeyValue<K, V>) -> Option<(KeyValue<K, V>, Node<K, V>)> {
        self.insert_kv(kv);

        if self.need_split() {
            let right_values = self.values.drain(RIGHT..).collect();
            let right_children = if self.children.len() > RIGHT {
                self.children.drain(RIGHT..).collect()
            } else {
                vec![]
            };
            let mid = self.values.pop().unwrap();

            Some((
                mid,
                Node {
                    values: right_values,
                    children: right_children,
                },
            ))
        } else {
            None
        }
    }

    fn remove<Q: ?Sized>(&mut self, key: &Q) -> (Option<V>, BalanceState)
    where
        K: Borrow<Q>,
        Q: Ord,
        K: std::fmt::Debug,
        V: std::fmt::Debug,
    {
        match self
            .values
            .binary_search_by(|probe| key.cmp(probe.key.borrow()).reverse())
        {
            Ok(idx) => {
                if self.is_leaf() {
                    self.remove_leaf(idx)
                } else {
                    todo!()
                }
            }

            Err(child_index) => {
                if child_index < self.children.len() {
                    dbg!(&self, child_index);

                    let (value, state) = self.children[child_index].remove(key);

                    match state {
                        BalanceState::UnbalancedLeaf => {

                        },
                        BalanceState::Finished => {}
                    }

                    dbg!(&state, &value);

                    (value, state)
                } else {
                    (None, BalanceState::Finished)
                }
            }
        }
    }

    fn remove_leaf(&mut self, idx: usize) -> (Option<V>, BalanceState) {
        self.values[idx..].rotate_left(1);

        match self.values.pop() {
            None => (None, BalanceState::Finished),
            Some(x) if self.values.len() > MID => (Some(x.value), BalanceState::Finished),
            Some(x) => (Some(x.value), BalanceState::UnbalancedLeaf),
        }
    }

    fn insert_kv(&mut self, kv: KeyValue<K, V>) {
        let idx = match self.values.binary_search(&kv) {
            Ok(idx) => idx,
            Err(idx) => idx,
        };

        self.values.push(kv);
        if idx < self.values.len() {
            // Rotate tail right.
            self.values[idx..].rotate_right(1);
        }
    }

    fn need_split(&self) -> bool {
        self.values.len() == MAX_LEN
    }

    // Indicates whether node is terminal or not.
    fn is_leaf(&self) -> bool {
        self.children.is_empty()
    }
}

#[test]
fn test_basic() {
    let mut map = NaiveBTree::default();

    let kvs = vec![
        (1, "a"),
        (2, "b"),
        (3, "c"),
        (4, "d"),
        (5, "e"),
        (6, "f"),
        (7, "g"),
        (8, "h"),
        (9, "i"),
        (10, "j"),
    ];

    for (key, value) in &kvs {
        map.insert(*key, *value);
    }

    for (key, value) in &kvs {
        assert_eq!(map.get(key), Some(value));
    }

    assert!(map.get(&11).is_none());

    map.remove(&10);

    dbg!(&map);
}
<|endoftext|>


<commit_before>// Copyright 2016 Alexander Reece
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(not(feature="clippy"), allow(unknown_lints))]

#[macro_use]
extern crate log;

extern crate amqp0_specs as specs;
extern crate inflections;
extern crate lazycell;
extern crate phf;

#[cfg(feature = "rustfmt")]
extern crate rustfmt;

pub mod primalgen;
pub mod parsergen;

mod common;

use std::fs::{self, File};
use std::io::{self, BufWriter};
use std::path::{Path, PathBuf};

pub use common::{Specs, Spec, Class, ClassMethod};

pub trait Source {
    fn name(&self) -> &str;
    fn crates(&self) -> &[&str];

    fn rebuild_features(&self) -> &[&str];
    fn pregeneration_features(&self) -> &[&str];

    fn base_dir(&self) -> &Path;
    fn should_format(&self) -> bool;

    fn write_header_to<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        writeln!(writer, "\
// Generated by build.rs script in {}
// Pre-generated files are used by default. Generation is done with the {} crate{}
//
// To regenerate, and not use pre-generated files, use: cargo --features=\"{}\"
// To format and replace the pre-generated files, use: cargo --features=\"{}\"
//
// EDITORS BEWARE: Your modifications may be overridden",
             self.name(),
             self.crates().join(", "),
             if self.crates().len() != 1 { "s" } else { "" },
             self.rebuild_features().join(" "),
             self.pregeneration_features().join(" ")
        )
    }
}

pub trait WriteRust {
    fn write_rust_to<W>(&self, &mut W) -> io::Result<()>
        where W: io::Write;

    fn write_rust_to_path<S, P>(&self, source: &S, path: &P) -> io::Result<()>
        where S: Source,
              P: AsRef<Path>
    {
        let path = path.as_ref();

        // create directory
        let parent = path.parent().unwrap();
        try!(fs::create_dir_all(parent));

        // create file and write contents
        let mut writer = BufWriter::new(try!(File::create(path)));
        try!(source.write_header_to(&mut writer));
        try!(self.write_rust_to(&mut writer));

        Ok(())
    }
}

#[cfg(not(feature = "rustfmt"))]
#[doc(hidden)]
fn format_files(_: Vec<PathBuf>) {}

#[cfg(feature = "rustfmt")]
#[doc(hidden)]
fn format_files(paths: Vec<PathBuf>) {
    use rustfmt::Input;
    use rustfmt::config::{self as fmtconfig};

    let config = {
    let mut config = fmtconfig::Config::default();
        config.write_mode = fmtconfig::WriteMode::Overwrite;
        config
    };

    for path in paths {
        println!("Formatting {}", path.display());
        let summary = rustfmt::run(Input::File(path), &config);
        println!("rustfmt Summary: {:?}", summary)
    }
}<commit_msg>[codegen] Update the header for pregenerated files.<commit_after>// Copyright 2016 Alexander Reece
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(not(feature="clippy"), allow(unknown_lints))]

#[macro_use]
extern crate log;

extern crate amqp0_specs as specs;
extern crate inflections;
extern crate lazycell;
extern crate phf;

#[cfg(feature = "rustfmt")]
extern crate rustfmt;

pub mod primalgen;
pub mod parsergen;

mod common;

use std::fs::{self, File};
use std::io::{self, BufWriter};
use std::path::{Path, PathBuf};

pub use common::{Specs, Spec, Class, ClassMethod};

pub trait Source {
    fn name(&self) -> &str;
    fn crates(&self) -> &[&str];

    fn rebuild_features(&self) -> &[&str];
    fn pregeneration_features(&self) -> &[&str];

    fn base_dir(&self) -> &Path;
    fn should_format(&self) -> bool;

    fn write_header_to<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        writeln!(writer, "\
// Generated by build.rs script in the {} crate.
// Pre-generated files are used by default. Generation is done with the {} crate{}.
//
// To regenerate, ignoring the pre-generated files, use: cargo --features=\"{}\"
// To format and replace the pre-generated files, use: cargo --features=\"{}\"
//
// EDITORS BEWARE: Your modifications may be overridden or removed.",
             self.name(),
             self.crates().join(", "),
             if self.crates().len() != 1 { "s" } else { "" },
             self.rebuild_features().join(" "),
             self.pregeneration_features().join(" ")
        )
    }
}

pub trait WriteRust {
    fn write_rust_to<W>(&self, &mut W) -> io::Result<()>
        where W: io::Write;

    fn write_rust_to_path<S, P>(&self, source: &S, path: &P) -> io::Result<()>
        where S: Source,
              P: AsRef<Path>
    {
        let path = path.as_ref();

        // create directory
        let parent = path.parent().unwrap();
        try!(fs::create_dir_all(parent));

        // create file and write contents
        let mut writer = BufWriter::new(try!(File::create(path)));
        try!(source.write_header_to(&mut writer));
        try!(self.write_rust_to(&mut writer));

        Ok(())
    }
}

#[cfg(not(feature = "rustfmt"))]
#[doc(hidden)]
fn format_files(_: Vec<PathBuf>) {}

#[cfg(feature = "rustfmt")]
#[doc(hidden)]
fn format_files(paths: Vec<PathBuf>) {
    use rustfmt::Input;
    use rustfmt::config::{self as fmtconfig};

    let config = {
    let mut config = fmtconfig::Config::default();
        config.write_mode = fmtconfig::WriteMode::Overwrite;
        config
    };

    for path in paths {
        println!("Formatting {}", path.display());
        let summary = rustfmt::run(Input::File(path), &config);
        println!("rustfmt Summary: {:?}", summary)
    }
}<|endoftext|>


<commit_before>use std::io::{self, Read, Write};
use std::time::Duration;

/// A factory for creating a listener on a given address.
/// For TCP, an address might be an IPv4 address; for Unix sockets, it
/// is just a file name.
pub trait Transport {
    /// The type of listener that binds to the given address.
    type Listener: Listener;
    /// Return a listener on the given address, and a dialer to that address.
    fn bind(&self) -> io::Result<Self::Listener>;
}

/// Accepts incoming connections from dialers.
pub trait Listener: Send + 'static {
    /// The type of address being listened on.
    type Dialer: Dialer;
    /// The type of stream this listener accepts.
    type Stream: Stream;
    /// Accept an incoming stream.
    fn accept(&self) -> io::Result<Self::Stream>;
    /// Returns the local address being listened on.
    fn dialer(&self) -> io::Result<Self::Dialer>;
    /// Iterate over incoming connections.
    fn incoming(&self) -> Incoming<Self> {
        Incoming { listener: self }
    }
}

/// A cloneable Reader/Writer.
pub trait Stream: Read + Write + Send + Sized + 'static {
    /// Creates a new independently owned handle to the underlying socket.
    ///
    /// The returned TcpStream should reference the same stream that this
    /// object references. Both handles should read and write the same
    /// stream of data, and options set on one stream should be propagated
    /// to the other stream.
    fn try_clone(&self) -> io::Result<Self>;
    /// Sets a read timeout.
    ///
    /// If the value specified is `None`, then read calls will block indefinitely.
    /// It is an error to pass the zero `Duration` to this method.
    fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()>;
    /// Sets a write timeout.
    ///
    /// If the value specified is `None`, then write calls will block indefinitely.
    /// It is an error to pass the zero `Duration` to this method.
    fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()>;
    /// Shuts down both ends of the stream.
    ///
    /// Implementations should cause all pending and future I/O on the specified
    /// portions to return immediately with an appropriate value.
    fn shutdown(&self) -> io::Result<()>;
}

/// A `Stream` factory.
pub trait Dialer {
    /// The type of `Stream` this can create.
    type Stream: Stream;
    /// Open a stream.
    fn dial(&self) -> io::Result<Self::Stream>;
}

impl<P, D: ?Sized> Dialer for P
    where P: ::std::ops::Deref<Target = D>,
          D: Dialer + 'static
{
    type Stream = D::Stream;
    fn dial(&self) -> io::Result<Self::Stream> {
        (**self).dial()
    }
}

/// Iterates over incoming connections.
pub struct Incoming<'a, L: Listener + ?Sized + 'a> {
    listener: &'a L,
}

impl<'a, L: Listener> Iterator for Incoming<'a, L> {
    type Item = io::Result<L::Stream>;

    fn next(&mut self) -> Option<Self::Item> {
        Some(self.listener.accept())
    }
}

/// Provides a TCP transport.
pub mod tcp;
/// Provides a unix socket transport.
pub mod unix;
<commit_msg>Generify doc comment<commit_after>use std::io::{self, Read, Write};
use std::time::Duration;

/// A factory for creating a listener on a given address.
/// For TCP, an address might be an IPv4 address; for Unix sockets, it
/// is just a file name.
pub trait Transport {
    /// The type of listener that binds to the given address.
    type Listener: Listener;
    /// Return a listener on the given address, and a dialer to that address.
    fn bind(&self) -> io::Result<Self::Listener>;
}

/// Accepts incoming connections from dialers.
pub trait Listener: Send + 'static {
    /// The type of address being listened on.
    type Dialer: Dialer;
    /// The type of stream this listener accepts.
    type Stream: Stream;
    /// Accept an incoming stream.
    fn accept(&self) -> io::Result<Self::Stream>;
    /// Returns the local address being listened on.
    fn dialer(&self) -> io::Result<Self::Dialer>;
    /// Iterate over incoming connections.
    fn incoming(&self) -> Incoming<Self> {
        Incoming { listener: self }
    }
}

/// A cloneable Reader/Writer.
pub trait Stream: Read + Write + Send + Sized + 'static {
    /// Creates a new independently owned handle to the Stream.
    ///
    /// The returned Stream should reference the same stream that this
    /// object references. Both handles should read and write the same
    /// stream of data, and options set on one stream should be propagated
    /// to the other stream.
    fn try_clone(&self) -> io::Result<Self>;
    /// Sets a read timeout.
    ///
    /// If the value specified is `None`, then read calls will block indefinitely.
    /// It is an error to pass the zero `Duration` to this method.
    fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()>;
    /// Sets a write timeout.
    ///
    /// If the value specified is `None`, then write calls will block indefinitely.
    /// It is an error to pass the zero `Duration` to this method.
    fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()>;
    /// Shuts down both ends of the stream.
    ///
    /// Implementations should cause all pending and future I/O on the specified
    /// portions to return immediately with an appropriate value.
    fn shutdown(&self) -> io::Result<()>;
}

/// A `Stream` factory.
pub trait Dialer {
    /// The type of `Stream` this can create.
    type Stream: Stream;
    /// Open a stream.
    fn dial(&self) -> io::Result<Self::Stream>;
}

impl<P, D: ?Sized> Dialer for P
    where P: ::std::ops::Deref<Target = D>,
          D: Dialer + 'static
{
    type Stream = D::Stream;
    fn dial(&self) -> io::Result<Self::Stream> {
        (**self).dial()
    }
}

/// Iterates over incoming connections.
pub struct Incoming<'a, L: Listener + ?Sized + 'a> {
    listener: &'a L,
}

impl<'a, L: Listener> Iterator for Incoming<'a, L> {
    type Item = io::Result<L::Stream>;

    fn next(&mut self) -> Option<Self::Item> {
        Some(self.listener.accept())
    }
}

/// Provides a TCP transport.
pub mod tcp;
/// Provides a unix socket transport.
pub mod unix;
<|endoftext|>


<commit_before>//! Checks the licenses of third-party dependencies by inspecting vendors.

use std::collections::{BTreeSet, HashSet, HashMap};
use std::fs;
use std::path::Path;
use std::process::Command;

use serde_json;

const LICENSES: &[&str] = &[
    "MIT/Apache-2.0",
    "MIT / Apache-2.0",
    "Apache-2.0/MIT",
    "Apache-2.0 / MIT",
    "MIT OR Apache-2.0",
    "MIT",
    "Unlicense/MIT",
    "Unlicense OR MIT",
];

/// These are exceptions to Rust's permissive licensing policy, and
/// should be considered bugs. Exceptions are only allowed in Rust
/// tooling. It is _crucial_ that no exception crates be dependencies
/// of the Rust runtime (std/test).
const EXCEPTIONS: &[&str] = &[
    "mdbook",             // MPL2, mdbook
    "openssl",            // BSD+advertising clause, cargo, mdbook
    "pest",               // MPL2, mdbook via handlebars
    "arrayref",           // BSD-2-Clause, mdbook via handlebars via pest
    "thread-id",          // Apache-2.0, mdbook
    "toml-query",         // MPL-2.0, mdbook
    "is-match",           // MPL-2.0, mdbook
    "cssparser",          // MPL-2.0, rustdoc
    "smallvec",           // MPL-2.0, rustdoc
    "fuchsia-zircon-sys", // BSD-3-Clause, rustdoc, rustc, cargo
    "fuchsia-zircon",     // BSD-3-Clause, rustdoc, rustc, cargo (jobserver & tempdir)
    "cssparser-macros",   // MPL-2.0, rustdoc
    "selectors",          // MPL-2.0, rustdoc
    "clippy_lints",       // MPL-2.0, rls
    "colored",            // MPL-2.0, rustfmt
    "ordslice",           // Apache-2.0, rls
    "cloudabi",           // BSD-2-Clause, (rls -> crossbeam-channel 0.2 -> rand 0.5)
    "ryu",                // Apache-2.0, rls/cargo/... (because of serde)
    "bytesize",           // Apache-2.0, cargo
    "im-rc",              // MPL-2.0+, cargo
    "adler32",            // BSD-3-Clause AND Zlib, cargo dep that isn't used
    "fortanix-sgx-abi",   // MPL-2.0+, libstd but only for `sgx` target
    "constant_time_eq",   // CC0-1.0, rustfmt
];

/// Which crates to check against the whitelist?
const WHITELIST_CRATES: &[CrateVersion] = &[
    CrateVersion("rustc", "0.0.0"),
    CrateVersion("rustc_codegen_llvm", "0.0.0"),
];

/// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible.
const WHITELIST: &[Crate] = &[
    Crate("adler32"),
    Crate("aho-corasick"),
    Crate("arrayvec"),
    Crate("atty"),
    Crate("backtrace"),
    Crate("backtrace-sys"),
    Crate("bitflags"),
    Crate("build_const"),
    Crate("byteorder"),
    Crate("cc"),
    Crate("cfg-if"),
    Crate("chalk-engine"),
    Crate("chalk-macros"),
    Crate("cloudabi"),
    Crate("cmake"),
    Crate("compiler_builtins"),
    Crate("crc"),
    Crate("crc32fast"),
    Crate("crossbeam-deque"),
    Crate("crossbeam-epoch"),
    Crate("crossbeam-utils"),
    Crate("datafrog"),
    Crate("either"),
    Crate("ena"),
    Crate("env_logger"),
    Crate("filetime"),
    Crate("flate2"),
    Crate("fuchsia-zircon"),
    Crate("fuchsia-zircon-sys"),
    Crate("getopts"),
    Crate("humantime"),
    Crate("jobserver"),
    Crate("kernel32-sys"),
    Crate("lazy_static"),
    Crate("libc"),
    Crate("libz-sys"),
    Crate("lock_api"),
    Crate("log"),
    Crate("log_settings"),
    Crate("memchr"),
    Crate("memmap"),
    Crate("memoffset"),
    Crate("miniz-sys"),
    Crate("miniz_oxide"),
    Crate("miniz_oxide_c_api"),
    Crate("nodrop"),
    Crate("num_cpus"),
    Crate("owning_ref"),
    Crate("parking_lot"),
    Crate("parking_lot_core"),
    Crate("pkg-config"),
    Crate("polonius-engine"),
    Crate("proc-macro2"),
    Crate("quick-error"),
    Crate("quote"),
    Crate("rand"),
    Crate("rand_chacha"),
    Crate("rand_core"),
    Crate("rand_hc"),
    Crate("rand_isaac"),
    Crate("rand_pcg"),
    Crate("rand_xorshift"),
    Crate("redox_syscall"),
    Crate("redox_termios"),
    Crate("regex"),
    Crate("regex-syntax"),
    Crate("remove_dir_all"),
    Crate("rustc-demangle"),
    Crate("rustc-hash"),
    Crate("rustc-rayon"),
    Crate("rustc-rayon-core"),
    Crate("rustc_version"),
    Crate("scoped-tls"),
    Crate("scopeguard"),
    Crate("semver"),
    Crate("semver-parser"),
    Crate("serde"),
    Crate("serde_derive"),
    Crate("smallvec"),
    Crate("stable_deref_trait"),
    Crate("syn"),
    Crate("tempfile"),
    Crate("termcolor"),
    Crate("terminon"),
    Crate("termion"),
    Crate("thread_local"),
    Crate("ucd-util"),
    Crate("unicode-width"),
    Crate("unicode-xid"),
    Crate("unreachable"),
    Crate("utf8-ranges"),
    Crate("vcpkg"),
    Crate("version_check"),
    Crate("void"),
    Crate("winapi"),
    Crate("winapi-build"),
    Crate("winapi-i686-pc-windows-gnu"),
    Crate("winapi-util"),
    Crate("winapi-x86_64-pc-windows-gnu"),
    Crate("wincolor"),
];

// Some types for Serde to deserialize the output of `cargo metadata` to.

#[derive(Deserialize)]
struct Output {
    resolve: Resolve,
}

#[derive(Deserialize)]
struct Resolve {
    nodes: Vec<ResolveNode>,
}

#[derive(Deserialize)]
struct ResolveNode {
    id: String,
    dependencies: Vec<String>,
}

/// A unique identifier for a crate.
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
struct Crate<'a>(&'a str); // (name)

#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
struct CrateVersion<'a>(&'a str, &'a str); // (name, version)

impl<'a> Crate<'a> {
    pub fn id_str(&self) -> String {
        format!("{} ", self.0)
    }
}

impl<'a> CrateVersion<'a> {
    /// Returns the struct and whether or not the dependency is in-tree.
    pub fn from_str(s: &'a str) -> (Self, bool) {
        let mut parts = s.split(' ');
        let name = parts.next().unwrap();
        let version = parts.next().unwrap();
        let path = parts.next().unwrap();

        let is_path_dep = path.starts_with("(path+");

        (CrateVersion(name, version), is_path_dep)
    }

    pub fn id_str(&self) -> String {
        format!("{} {}", self.0, self.1)
    }
}

impl<'a> From<CrateVersion<'a>> for Crate<'a> {
    fn from(cv: CrateVersion<'a>) -> Crate<'a> {
        Crate(cv.0)
    }
}

/// Checks the dependency at the given path. Changes `bad` to `true` if a check failed.
///
/// Specifically, this checks that the license is correct.
pub fn check(path: &Path, bad: &mut bool) {
    // Check licences.
    let path = path.join("../vendor");
    assert!(path.exists(), "vendor directory missing");
    let mut saw_dir = false;
    for dir in t!(path.read_dir()) {
        saw_dir = true;
        let dir = t!(dir);

        // Skip our exceptions.
        let is_exception = EXCEPTIONS.iter().any(|exception| {
            dir.path()
                .to_str()
                .unwrap()
                .contains(&format!("vendor/{}", exception))
        });
        if is_exception {
            continue;
        }

        let toml = dir.path().join("Cargo.toml");
        *bad = *bad || !check_license(&toml);
    }
    assert!(saw_dir, "no vendored source");
}

/// Checks the dependency of `WHITELIST_CRATES` at the given path. Changes `bad` to `true` if a
/// check failed.
///
/// Specifically, this checks that the dependencies are on the `WHITELIST`.
pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) {
    // Get dependencies from Cargo metadata.
    let resolve = get_deps(path, cargo);

    // Get the whitelist in a convenient form.
    let whitelist: HashSet<_> = WHITELIST.iter().cloned().collect();

    // Check dependencies.
    let mut visited = BTreeSet::new();
    let mut unapproved = BTreeSet::new();
    for &krate in WHITELIST_CRATES.iter() {
        let mut bad = check_crate_whitelist(&whitelist, &resolve, &mut visited, krate, false);
        unapproved.append(&mut bad);
    }

    if !unapproved.is_empty() {
        println!("Dependencies not on the whitelist:");
        for dep in unapproved {
            println!("* {}", dep.id_str());
        }
        *bad = true;
    }

    check_crate_duplicate(&resolve, bad);
}

fn check_license(path: &Path) -> bool {
    if !path.exists() {
        panic!("{} does not exist", path.display());
    }
    let contents = t!(fs::read_to_string(&path));

    let mut found_license = false;
    for line in contents.lines() {
        if !line.starts_with("license") {
            continue;
        }
        let license = extract_license(line);
        if !LICENSES.contains(&&*license) {
            println!("invalid license {} in {}", license, path.display());
            return false;
        }
        found_license = true;
        break;
    }
    if !found_license {
        println!("no license in {}", path.display());
        return false;
    }

    true
}

fn extract_license(line: &str) -> String {
    let first_quote = line.find('"');
    let last_quote = line.rfind('"');
    if let (Some(f), Some(l)) = (first_quote, last_quote) {
        let license = &line[f + 1..l];
        license.into()
    } else {
        "bad-license-parse".into()
    }
}

/// Gets the dependencies of the crate at the given path using `cargo metadata`.
fn get_deps(path: &Path, cargo: &Path) -> Resolve {
    // Run `cargo metadata` to get the set of dependencies.
    let output = Command::new(cargo)
        .arg("metadata")
        .arg("--format-version")
        .arg("1")
        .arg("--manifest-path")
        .arg(path.join("../Cargo.toml"))
        .output()
        .expect("Unable to run `cargo metadata`")
        .stdout;
    let output = String::from_utf8_lossy(&output);
    let output: Output = serde_json::from_str(&output).unwrap();

    output.resolve
}

/// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
/// the whitelist. Returns a list of illegal dependencies.
fn check_crate_whitelist<'a, 'b>(
    whitelist: &'a HashSet<Crate>,
    resolve: &'a Resolve,
    visited: &'b mut BTreeSet<CrateVersion<'a>>,
    krate: CrateVersion<'a>,
    must_be_on_whitelist: bool,
) -> BTreeSet<Crate<'a>> {
    // This will contain bad deps.
    let mut unapproved = BTreeSet::new();

    // Check if we have already visited this crate.
    if visited.contains(&krate) {
        return unapproved;
    }

    visited.insert(krate);

    // If this path is in-tree, we don't require it to be on the whitelist.
    if must_be_on_whitelist {
        // If this dependency is not on `WHITELIST`, add to bad set.
        if !whitelist.contains(&krate.into()) {
            unapproved.insert(krate.into());
        }
    }

    // Do a DFS in the crate graph (it's a DAG, so we know we have no cycles!).
    let to_check = resolve
        .nodes
        .iter()
        .find(|n| n.id.starts_with(&krate.id_str()))
        .expect("crate does not exist");

    for dep in to_check.dependencies.iter() {
        let (krate, is_path_dep) = CrateVersion::from_str(dep);

        let mut bad = check_crate_whitelist(whitelist, resolve, visited, krate, !is_path_dep);
        unapproved.append(&mut bad);
    }

    unapproved
}

fn check_crate_duplicate(resolve: &Resolve, bad: &mut bool) {
    const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[
        // These two crates take quite a long time to build, so don't allow two versions of them
        // to accidentally sneak into our dependency graph, in order to ensure we keep our CI times
        // under control.

        // "cargo", // FIXME(#53005)
        "rustc-ap-syntax",
    ];
    let mut name_to_id: HashMap<_, Vec<_>> = HashMap::new();
    for node in resolve.nodes.iter() {
        name_to_id.entry(node.id.split_whitespace().next().unwrap())
            .or_default()
            .push(&node.id);
    }

    for name in FORBIDDEN_TO_HAVE_DUPLICATES {
        if name_to_id[name].len() <= 1 {
            continue
        }
        println!("crate `{}` is duplicated in `Cargo.lock`", name);
        for id in name_to_id[name].iter() {
            println!("  * {}", id);
        }
        *bad = true;
    }
}
<commit_msg>Forbid duplicating Cargo as a dependency<commit_after>//! Checks the licenses of third-party dependencies by inspecting vendors.

use std::collections::{BTreeSet, HashSet, HashMap};
use std::fs;
use std::path::Path;
use std::process::Command;

use serde_json;

const LICENSES: &[&str] = &[
    "MIT/Apache-2.0",
    "MIT / Apache-2.0",
    "Apache-2.0/MIT",
    "Apache-2.0 / MIT",
    "MIT OR Apache-2.0",
    "MIT",
    "Unlicense/MIT",
    "Unlicense OR MIT",
];

/// These are exceptions to Rust's permissive licensing policy, and
/// should be considered bugs. Exceptions are only allowed in Rust
/// tooling. It is _crucial_ that no exception crates be dependencies
/// of the Rust runtime (std/test).
const EXCEPTIONS: &[&str] = &[
    "mdbook",             // MPL2, mdbook
    "openssl",            // BSD+advertising clause, cargo, mdbook
    "pest",               // MPL2, mdbook via handlebars
    "arrayref",           // BSD-2-Clause, mdbook via handlebars via pest
    "thread-id",          // Apache-2.0, mdbook
    "toml-query",         // MPL-2.0, mdbook
    "is-match",           // MPL-2.0, mdbook
    "cssparser",          // MPL-2.0, rustdoc
    "smallvec",           // MPL-2.0, rustdoc
    "fuchsia-zircon-sys", // BSD-3-Clause, rustdoc, rustc, cargo
    "fuchsia-zircon",     // BSD-3-Clause, rustdoc, rustc, cargo (jobserver & tempdir)
    "cssparser-macros",   // MPL-2.0, rustdoc
    "selectors",          // MPL-2.0, rustdoc
    "clippy_lints",       // MPL-2.0, rls
    "colored",            // MPL-2.0, rustfmt
    "ordslice",           // Apache-2.0, rls
    "cloudabi",           // BSD-2-Clause, (rls -> crossbeam-channel 0.2 -> rand 0.5)
    "ryu",                // Apache-2.0, rls/cargo/... (because of serde)
    "bytesize",           // Apache-2.0, cargo
    "im-rc",              // MPL-2.0+, cargo
    "adler32",            // BSD-3-Clause AND Zlib, cargo dep that isn't used
    "fortanix-sgx-abi",   // MPL-2.0+, libstd but only for `sgx` target
    "constant_time_eq",   // CC0-1.0, rustfmt
];

/// Which crates to check against the whitelist?
const WHITELIST_CRATES: &[CrateVersion] = &[
    CrateVersion("rustc", "0.0.0"),
    CrateVersion("rustc_codegen_llvm", "0.0.0"),
];

/// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible.
const WHITELIST: &[Crate] = &[
    Crate("adler32"),
    Crate("aho-corasick"),
    Crate("arrayvec"),
    Crate("atty"),
    Crate("backtrace"),
    Crate("backtrace-sys"),
    Crate("bitflags"),
    Crate("build_const"),
    Crate("byteorder"),
    Crate("cc"),
    Crate("cfg-if"),
    Crate("chalk-engine"),
    Crate("chalk-macros"),
    Crate("cloudabi"),
    Crate("cmake"),
    Crate("compiler_builtins"),
    Crate("crc"),
    Crate("crc32fast"),
    Crate("crossbeam-deque"),
    Crate("crossbeam-epoch"),
    Crate("crossbeam-utils"),
    Crate("datafrog"),
    Crate("either"),
    Crate("ena"),
    Crate("env_logger"),
    Crate("filetime"),
    Crate("flate2"),
    Crate("fuchsia-zircon"),
    Crate("fuchsia-zircon-sys"),
    Crate("getopts"),
    Crate("humantime"),
    Crate("jobserver"),
    Crate("kernel32-sys"),
    Crate("lazy_static"),
    Crate("libc"),
    Crate("libz-sys"),
    Crate("lock_api"),
    Crate("log"),
    Crate("log_settings"),
    Crate("memchr"),
    Crate("memmap"),
    Crate("memoffset"),
    Crate("miniz-sys"),
    Crate("miniz_oxide"),
    Crate("miniz_oxide_c_api"),
    Crate("nodrop"),
    Crate("num_cpus"),
    Crate("owning_ref"),
    Crate("parking_lot"),
    Crate("parking_lot_core"),
    Crate("pkg-config"),
    Crate("polonius-engine"),
    Crate("proc-macro2"),
    Crate("quick-error"),
    Crate("quote"),
    Crate("rand"),
    Crate("rand_chacha"),
    Crate("rand_core"),
    Crate("rand_hc"),
    Crate("rand_isaac"),
    Crate("rand_pcg"),
    Crate("rand_xorshift"),
    Crate("redox_syscall"),
    Crate("redox_termios"),
    Crate("regex"),
    Crate("regex-syntax"),
    Crate("remove_dir_all"),
    Crate("rustc-demangle"),
    Crate("rustc-hash"),
    Crate("rustc-rayon"),
    Crate("rustc-rayon-core"),
    Crate("rustc_version"),
    Crate("scoped-tls"),
    Crate("scopeguard"),
    Crate("semver"),
    Crate("semver-parser"),
    Crate("serde"),
    Crate("serde_derive"),
    Crate("smallvec"),
    Crate("stable_deref_trait"),
    Crate("syn"),
    Crate("tempfile"),
    Crate("termcolor"),
    Crate("terminon"),
    Crate("termion"),
    Crate("thread_local"),
    Crate("ucd-util"),
    Crate("unicode-width"),
    Crate("unicode-xid"),
    Crate("unreachable"),
    Crate("utf8-ranges"),
    Crate("vcpkg"),
    Crate("version_check"),
    Crate("void"),
    Crate("winapi"),
    Crate("winapi-build"),
    Crate("winapi-i686-pc-windows-gnu"),
    Crate("winapi-util"),
    Crate("winapi-x86_64-pc-windows-gnu"),
    Crate("wincolor"),
];

// Some types for Serde to deserialize the output of `cargo metadata` to.

#[derive(Deserialize)]
struct Output {
    resolve: Resolve,
}

#[derive(Deserialize)]
struct Resolve {
    nodes: Vec<ResolveNode>,
}

#[derive(Deserialize)]
struct ResolveNode {
    id: String,
    dependencies: Vec<String>,
}

/// A unique identifier for a crate.
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
struct Crate<'a>(&'a str); // (name)

#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
struct CrateVersion<'a>(&'a str, &'a str); // (name, version)

impl<'a> Crate<'a> {
    pub fn id_str(&self) -> String {
        format!("{} ", self.0)
    }
}

impl<'a> CrateVersion<'a> {
    /// Returns the struct and whether or not the dependency is in-tree.
    pub fn from_str(s: &'a str) -> (Self, bool) {
        let mut parts = s.split(' ');
        let name = parts.next().unwrap();
        let version = parts.next().unwrap();
        let path = parts.next().unwrap();

        let is_path_dep = path.starts_with("(path+");

        (CrateVersion(name, version), is_path_dep)
    }

    pub fn id_str(&self) -> String {
        format!("{} {}", self.0, self.1)
    }
}

impl<'a> From<CrateVersion<'a>> for Crate<'a> {
    fn from(cv: CrateVersion<'a>) -> Crate<'a> {
        Crate(cv.0)
    }
}

/// Checks the dependency at the given path. Changes `bad` to `true` if a check failed.
///
/// Specifically, this checks that the license is correct.
pub fn check(path: &Path, bad: &mut bool) {
    // Check licences.
    let path = path.join("../vendor");
    assert!(path.exists(), "vendor directory missing");
    let mut saw_dir = false;
    for dir in t!(path.read_dir()) {
        saw_dir = true;
        let dir = t!(dir);

        // Skip our exceptions.
        let is_exception = EXCEPTIONS.iter().any(|exception| {
            dir.path()
                .to_str()
                .unwrap()
                .contains(&format!("vendor/{}", exception))
        });
        if is_exception {
            continue;
        }

        let toml = dir.path().join("Cargo.toml");
        *bad = *bad || !check_license(&toml);
    }
    assert!(saw_dir, "no vendored source");
}

/// Checks the dependency of `WHITELIST_CRATES` at the given path. Changes `bad` to `true` if a
/// check failed.
///
/// Specifically, this checks that the dependencies are on the `WHITELIST`.
pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) {
    // Get dependencies from Cargo metadata.
    let resolve = get_deps(path, cargo);

    // Get the whitelist in a convenient form.
    let whitelist: HashSet<_> = WHITELIST.iter().cloned().collect();

    // Check dependencies.
    let mut visited = BTreeSet::new();
    let mut unapproved = BTreeSet::new();
    for &krate in WHITELIST_CRATES.iter() {
        let mut bad = check_crate_whitelist(&whitelist, &resolve, &mut visited, krate, false);
        unapproved.append(&mut bad);
    }

    if !unapproved.is_empty() {
        println!("Dependencies not on the whitelist:");
        for dep in unapproved {
            println!("* {}", dep.id_str());
        }
        *bad = true;
    }

    check_crate_duplicate(&resolve, bad);
}

fn check_license(path: &Path) -> bool {
    if !path.exists() {
        panic!("{} does not exist", path.display());
    }
    let contents = t!(fs::read_to_string(&path));

    let mut found_license = false;
    for line in contents.lines() {
        if !line.starts_with("license") {
            continue;
        }
        let license = extract_license(line);
        if !LICENSES.contains(&&*license) {
            println!("invalid license {} in {}", license, path.display());
            return false;
        }
        found_license = true;
        break;
    }
    if !found_license {
        println!("no license in {}", path.display());
        return false;
    }

    true
}

fn extract_license(line: &str) -> String {
    let first_quote = line.find('"');
    let last_quote = line.rfind('"');
    if let (Some(f), Some(l)) = (first_quote, last_quote) {
        let license = &line[f + 1..l];
        license.into()
    } else {
        "bad-license-parse".into()
    }
}

/// Gets the dependencies of the crate at the given path using `cargo metadata`.
fn get_deps(path: &Path, cargo: &Path) -> Resolve {
    // Run `cargo metadata` to get the set of dependencies.
    let output = Command::new(cargo)
        .arg("metadata")
        .arg("--format-version")
        .arg("1")
        .arg("--manifest-path")
        .arg(path.join("../Cargo.toml"))
        .output()
        .expect("Unable to run `cargo metadata`")
        .stdout;
    let output = String::from_utf8_lossy(&output);
    let output: Output = serde_json::from_str(&output).unwrap();

    output.resolve
}

/// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
/// the whitelist. Returns a list of illegal dependencies.
fn check_crate_whitelist<'a, 'b>(
    whitelist: &'a HashSet<Crate>,
    resolve: &'a Resolve,
    visited: &'b mut BTreeSet<CrateVersion<'a>>,
    krate: CrateVersion<'a>,
    must_be_on_whitelist: bool,
) -> BTreeSet<Crate<'a>> {
    // This will contain bad deps.
    let mut unapproved = BTreeSet::new();

    // Check if we have already visited this crate.
    if visited.contains(&krate) {
        return unapproved;
    }

    visited.insert(krate);

    // If this path is in-tree, we don't require it to be on the whitelist.
    if must_be_on_whitelist {
        // If this dependency is not on `WHITELIST`, add to bad set.
        if !whitelist.contains(&krate.into()) {
            unapproved.insert(krate.into());
        }
    }

    // Do a DFS in the crate graph (it's a DAG, so we know we have no cycles!).
    let to_check = resolve
        .nodes
        .iter()
        .find(|n| n.id.starts_with(&krate.id_str()))
        .expect("crate does not exist");

    for dep in to_check.dependencies.iter() {
        let (krate, is_path_dep) = CrateVersion::from_str(dep);

        let mut bad = check_crate_whitelist(whitelist, resolve, visited, krate, !is_path_dep);
        unapproved.append(&mut bad);
    }

    unapproved
}

fn check_crate_duplicate(resolve: &Resolve, bad: &mut bool) {
    const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[
        // These two crates take quite a long time to build, so don't allow two versions of them
        // to accidentally sneak into our dependency graph, in order to ensure we keep our CI times
        // under control.

        "cargo",
        "rustc-ap-syntax",
    ];
    let mut name_to_id: HashMap<_, Vec<_>> = HashMap::new();
    for node in resolve.nodes.iter() {
        name_to_id.entry(node.id.split_whitespace().next().unwrap())
            .or_default()
            .push(&node.id);
    }

    for name in FORBIDDEN_TO_HAVE_DUPLICATES {
        if name_to_id[name].len() <= 1 {
            continue
        }
        println!("crate `{}` is duplicated in `Cargo.lock`", name);
        for id in name_to_id[name].iter() {
            println!("  * {}", id);
        }
        *bad = true;
    }
}
<|endoftext|>


<commit_before>use std::rc::*;
use std::ops::*;
use super::treenode::*;

///
/// Trait implemented by types that can work as a tree node index
///
pub trait TreeNodeIndex {
    ///
    /// Finds the tree node corresponding to the specified index in the tree
    ///
    fn lookup_index<'a>(&self, parent_node: &'a TreeNode) -> Option<&'a Rc<TreeNode>>;
}

impl TreeNodeIndex for usize {
    ///
    /// Finds the tree node corresponding to the specified index in the tree
    ///
    fn lookup_index<'a>(&self, parent_node: &'a TreeNode) -> Option<&'a Rc<TreeNode>> {
        let mut pos = *self;
        let mut current_child = parent_node.get_child_ref().to_owned();

        loop {
            match current_child {
                None        => return None,
                Some(child) => {
                    if pos == 0 { return current_child; }

                    pos = pos-1;
                    current_child = child.get_sibling_ref().to_owned();
                }
            }
        }
    }
}

///
/// Provides the ability to reference the children of a tree node by looking up a particular index
///
pub trait TreeNodeLookup : TreeNode {
    ///
    /// Looks up a child node at a particular index (panics if the child does not exist)
    ///
    fn get_child_at<'a, TIndex: TreeNodeIndex>(&'a self, index: TIndex) -> &'a TreeNode;
}

impl<T: TreeNode> TreeNodeLookup for T {
    ///
    /// Looks up a child node at a particular index (panics if the child does not exist)
    ///
    fn get_child_at<'a, TIndex: TreeNodeIndex>(&'a self, index: TIndex) -> &'a TreeNode {
        let opt_node = index.lookup_index(self);
        let node_ref = opt_node.unwrap();

        &**node_ref
    }
}

/*
impl<'b, T: TreeNode, TIndex: TreeNodeIndex> Index<TIndex> for T {
    type Output = TreeNode+'b;

    fn index<'a>(&'a self, index: TIndex) -> &'a TreeNode {
        self.get_child_at(index)
    }
}
*/

#[cfg(test)]
mod treenode_index_tests {
    use super::super::treenode::*;
    use super::super::basictree::*;
    use std::rc::*;

    #[test]
    fn lookup_usize() {
        let mut tree = BasicTree::new("test", ());
        let first_child = Rc::new(BasicTree::new("first_child", ()));

        tree.set_child_ref(first_child);

        let lookup = 0.lookup_index(&tree);
        assert!(lookup.is_some());
        assert!(lookup.unwrap().get_tag() == "first_child");
        assert!(tree.get_sibling_ref().is_none());
    }

    #[test]
    fn can_get_first_child() {
        let mut tree = BasicTree::new("test", ());
        let first_child = Rc::new(BasicTree::new("first_child", ()));

        tree.set_child_ref(first_child);

        assert!((tree.get_child_at(0).get_tag()) == "first_child");
        assert!(tree.get_sibling_ref().is_none());
    }

    /*
    #[test]
    fn can_get_first_child_via_index() {
        let mut tree = BasicTree::new("test", ());
        let first_child = Rc::new(BasicTree::new("first_child", ()));

        tree.set_child_ref(first_child);

        assert!((tree[0].get_tag()) == "first_child");
        assert!(tree.get_sibling_ref().is_none());
    }
    */
}
<commit_msg>Add a way to look up child nodes by tag as well as by index<commit_after>use std::rc::*;
use super::treenode::*;

///
/// Trait implemented by types that can work as a tree node index
///
pub trait TreeNodeIndex {
    ///
    /// Finds the tree node corresponding to the specified index in the tree
    ///
    fn lookup_index<'a>(&self, parent_node: &'a TreeNode) -> Option<&'a Rc<TreeNode>>;
}

impl TreeNodeIndex for usize {
    ///
    /// Finds the tree node corresponding to the specified index in the tree
    ///
    fn lookup_index<'a>(&self, parent_node: &'a TreeNode) -> Option<&'a Rc<TreeNode>> {
        let mut pos = *self;
        let mut current_child = parent_node.get_child_ref().to_owned();

        loop {
            match current_child {
                None        => return None,
                Some(child) => {
                    if pos == 0 { return current_child; }

                    pos = pos-1;
                    current_child = child.get_sibling_ref().to_owned();
                }
            }
        }
    }
}

impl<'b> TreeNodeIndex for &'b str {
    ///
    /// Finds the tree node corresponding to the specified index in the tree
    ///
    /// When searching by tag, we match only the first item that we find.
    ///
    fn lookup_index<'a>(&self, parent_node: &'a TreeNode) -> Option<&'a Rc<TreeNode>> {
        let mut current_child = parent_node.get_child_ref().to_owned();

        loop {
            match current_child {
                None        => return None,
                Some(child) => {
                    if (*child).get_tag() == *self {
                        return current_child;
                    }

                    current_child = child.get_sibling_ref().to_owned();
                }
            }
        }
    }
}

///
/// Provides the ability to reference the children of a tree node by looking up a particular index
///
pub trait TreeNodeLookup : TreeNode {
    ///
    /// Looks up a child node at a particular index (panics if the child does not exist)
    ///
    fn get_child_at<'a, TIndex: TreeNodeIndex>(&'a self, index: TIndex) -> &'a TreeNode;

    ///
    /// Looks up a child node at a particular index
    ///
    fn get_child_ref_at<'a, TIndex: TreeNodeIndex>(&'a self, index: TIndex) -> Option<&'a Rc<TreeNode>>;
}

impl<T: TreeNode> TreeNodeLookup for T {
    ///
    /// Looks up a child node at a particular index (panics if the child does not exist)
    ///
    fn get_child_at<'a, TIndex: TreeNodeIndex>(&'a self, index: TIndex) -> &'a TreeNode {
        let opt_node = index.lookup_index(self);
        let node_ref = opt_node.unwrap();

        &**node_ref
    }

    ///
    /// Looks up a child node at a particular index
    ///
    fn get_child_ref_at<'a, TIndex: TreeNodeIndex>(&'a self, index: TIndex) -> Option<&'a Rc<TreeNode>> {
        index.lookup_index(self)
    }
}

#[cfg(test)]
mod treenode_index_tests {
    use super::super::treenode::*;
    use super::super::basictree::*;
    use std::rc::*;

    #[test]
    fn lookup_usize() {
        let mut tree = BasicTree::new("test", ());
        let first_child = Rc::new(BasicTree::new("first_child", ()));

        tree.set_child_ref(first_child);

        let lookup = 0.lookup_index(&tree);
        assert!(lookup.is_some());
        assert!(lookup.unwrap().get_tag() == "first_child");
        assert!(tree.get_sibling_ref().is_none());
    }

    #[test]
    fn can_get_first_child() {
        let mut tree = BasicTree::new("test", ());
        let first_child = Rc::new(BasicTree::new("first_child", ()));

        tree.set_child_ref(first_child);

        assert!((tree.get_child_at(0).get_tag()) == "first_child");
        assert!(tree.get_sibling_ref().is_none());
    }

    #[test]
    fn can_get_first_child_by_string() {
        let mut tree = BasicTree::new("test", ());
        let first_child = Rc::new(BasicTree::new("first_child", ()));

        tree.set_child_ref(first_child);

        assert!((tree.get_child_at("first_child").get_tag()) == "first_child");
        assert!(tree.get_sibling_ref().is_none());
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;
use sdl2::event;

#[test]
fn test_events() {
    let sdl = sdl2::init().unwrap();
    let ev = sdl.event().unwrap();
    let mut ep = sdl.event_pump().unwrap();

    test1(&ev);
    test2(&ev, &mut ep);

    test3(&ev);
    test4(&ev, &mut ep);
}

fn test1(ev: &sdl2::EventSubsystem) {
    let user_event1_id = unsafe { ev.register_event().unwrap() };
    let user_event2_id = unsafe { ev.register_event().unwrap() };
    assert_ne!(user_event1_id, user_event2_id);
}

fn test2(ev: &sdl2::EventSubsystem, ep: &mut sdl2::EventPump) {
    let user_event_id = unsafe { ev.register_event().unwrap() };

    let event = event::Event::User {
        timestamp: 0,
        window_id: 0,
        type_: user_event_id,
        code: 456,
        data1: 0x12_34 as *mut ::std::os::raw::c_void,
        data2: 0x56_78 as *mut ::std::os::raw::c_void,
    };

    let (t1, a1, a2) = match event {
        event::Event::User { type_: t1, data1: a1, data2: a2, .. } => { (t1, a1, a2) }
        _ => { panic!("expected user event") }
    };
    ev.push_event(event.clone()).unwrap();
    let received = ep.poll_event().unwrap();
    assert_eq!(&event, &received);
    match &received {
        &event::Event::User { type_: t2, data1: b1, data2: b2, .. }  => {
            assert_eq!(t1, t2);
            assert_eq!(a1, b1);
            assert_eq!(a2, b2);
        }
        other => { panic!("Received non User event: {:?}", other) }
    }
}

#[allow(unused)]
struct SomeEventTypeTest3 {
    a: u32
}

#[allow(unused)]
struct SomeOtherEventTypeTest3 {
    b: u32
}

fn test3(ev: &sdl2::EventSubsystem) {
    ev.register_custom_event::<SomeEventTypeTest3>().unwrap();
    ev.register_custom_event::<SomeOtherEventTypeTest3>().unwrap();

    assert!(ev.register_custom_event::<SomeEventTypeTest3>().is_err());
}

struct SomeEventTypeTest4 {
    a: u32
}

fn test4(ev: &sdl2::EventSubsystem, ep: &mut sdl2::EventPump) {
    ev.register_custom_event::<SomeEventTypeTest4>().unwrap();
    let event = SomeEventTypeTest4 { a: 42 };
    ev.push_custom_event(event).unwrap();

    let received = ep.poll_event().unwrap();
    if received.is_user_event() {
        let e2 = received.as_user_event_type::<SomeEventTypeTest4>().unwrap();
        assert_eq!(e2.a, 42);
    }
}
<commit_msg>Fix test flakyness<commit_after>extern crate sdl2;
use sdl2::event;

#[test]
fn test_events() {
    let sdl = sdl2::init().unwrap();
    let ev = sdl.event().unwrap();
    let mut ep = sdl.event_pump().unwrap();

    test1(&ev);
    test2(&ev, &mut ep);

    test3(&ev);
    test4(&ev, &mut ep);
}

fn test1(ev: &sdl2::EventSubsystem) {
    let user_event1_id = unsafe { ev.register_event().unwrap() };
    let user_event2_id = unsafe { ev.register_event().unwrap() };
    assert_ne!(user_event1_id, user_event2_id);
}

fn test2(ev: &sdl2::EventSubsystem, ep: &mut sdl2::EventPump) {
    let user_event_id = unsafe { ev.register_event().unwrap() };

    let event = event::Event::User {
        timestamp: 0,
        window_id: 0,
        type_: user_event_id,
        code: 456,
        data1: 0x12_34 as *mut ::std::os::raw::c_void,
        data2: 0x56_78 as *mut ::std::os::raw::c_void,
    };

    let (w1, t1, c1, a1, a2) = match event {
        event::Event::User {
            window_id: w1,
            type_: t1,
            code: c1,
            data1: a1,
            data2: a2,
            ..
        } => (w1, t1, c1, a1, a2),
        _ => panic!("expected user event"),
    };
    ev.push_event(event.clone()).unwrap();
    let received = ep.poll_event().unwrap();
    // Do not check for timestamp here because it is always modified by
    // SDL_PushEvent.
    match &received {
        &event::Event::User {
            window_id: w2,
            type_: t2,
            code: c2,
            data1: b1,
            data2: b2,
            ..
        } => {
            assert_eq!(w1, w2);
            assert_eq!(t1, t2);
            assert_eq!(c1, c2);
            assert_eq!(a1, b1);
            assert_eq!(a2, b2);
        }
        other => panic!("Received non User event: {:?}", other),
    }
}

#[allow(unused)]
struct SomeEventTypeTest3 {
    a: u32
}

#[allow(unused)]
struct SomeOtherEventTypeTest3 {
    b: u32
}

fn test3(ev: &sdl2::EventSubsystem) {
    ev.register_custom_event::<SomeEventTypeTest3>().unwrap();
    ev.register_custom_event::<SomeOtherEventTypeTest3>().unwrap();

    assert!(ev.register_custom_event::<SomeEventTypeTest3>().is_err());
}

struct SomeEventTypeTest4 {
    a: u32
}

fn test4(ev: &sdl2::EventSubsystem, ep: &mut sdl2::EventPump) {
    ev.register_custom_event::<SomeEventTypeTest4>().unwrap();
    let event = SomeEventTypeTest4 { a: 42 };
    ev.push_custom_event(event).unwrap();

    let received = ep.poll_event().unwrap();
    if received.is_user_event() {
        let e2 = received.as_user_event_type::<SomeEventTypeTest4>().unwrap();
        assert_eq!(e2.a, 42);
    }
}
<|endoftext|>