<commit_before>// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2019, HST authors.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied.  See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------------------

//! Defines a process type that includes all of the CSP language.

use std::fmt::Debug;
use std::fmt::Display;
use std::rc::Rc;

use auto_enums::enum_derive;
use auto_from::From;

use crate::event::EmptyAlphabet;
use crate::external_choice::ExternalChoice;
use crate::internal_choice::InternalChoice;
use crate::prefix::Prefix;
use crate::primitives::Skip;
use crate::primitives::Stop;
use crate::primitives::Tau;
use crate::primitives::Tick;
use crate::process::Cursor;
use crate::process::Process;
use crate::sequential_composition::SequentialComposition;

/// A process type that includes all of the primitive processes and operators in the CSP language.
/// Note that you should never need to construct instances of this type directly; use the helper
/// constructor for each process (e.g. [`stop`]) or operator (e.g. [`prefix`]) instead.
///
/// [`stop`]: ../primitives/fn.stop.html
/// [`prefix`]: ../prefix/fn.prefix.html
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct CSP<E>(Rc<CSPSig<E, CSP<E>>>);

impl<E: Display> Display for CSP<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self.0.as_ref() as &dyn Display).fmt(f)
    }
}

impl<E: Display> Debug for CSP<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self.0.as_ref() as &dyn Debug).fmt(f)
    }
}

impl<E, T> From<T> for CSP<E>
where
    CSPSig<E, CSP<E>>: From<T>,
{
    fn from(t: T) -> CSP<E> {
        CSP(Rc::new(CSPSig::from(t)))
    }
}

impl<E> Process<E> for CSP<E>
where
    E: Clone + Display + Eq + From<Tau> + From<Tick> + 'static,
{
    type Cursor = CSPCursor<E>;

    fn root(&self) -> Self::Cursor {
        CSPCursor(Box::new(self.0.root()))
    }
}

#[doc(hidden)]
#[derive(Clone, Eq, PartialEq)]
pub struct CSPCursor<E>(
    Box<
        CSPSigCursor<
            <ExternalChoice<CSP<E>> as Process<E>>::Cursor,
            <InternalChoice<CSP<E>> as Process<E>>::Cursor,
            <Prefix<E, CSP<E>> as Process<E>>::Cursor,
            <SequentialComposition<CSP<E>> as Process<E>>::Cursor,
            <Skip<E> as Process<E>>::Cursor,
            <Stop<E> as Process<E>>::Cursor,
        >,
    >,
)
where
    E: Clone + Display + Eq + From<Tau> + From<Tick> + 'static;

impl<E> Debug for CSPCursor<E>
where
    E: Clone + Debug + Display + Eq + From<Tau> + From<Tick> + 'static,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self.0.as_ref() as &dyn Debug).fmt(f)
    }
}

impl<E> Cursor<E> for CSPCursor<E>
where
    E: Clone + Display + Eq + From<Tau> + From<Tick> + 'static,
{
    type Alphabet = EmptyAlphabet;

    fn initials(&self) -> EmptyAlphabet {
        EmptyAlphabet
    }

    fn events<'a>(&'a self) -> Box<dyn Iterator<Item = E> + 'a> {
        self.0.events()
    }

    fn can_perform(&self, event: &E) -> bool {
        self.0.can_perform(event)
    }

    fn perform(&mut self, event: &E) {
        self.0.perform(event);
    }
}

#[doc(hidden)]
#[enum_derive(Debug, Display)]
#[derive(Clone, Eq, From, Hash, PartialEq)]
pub enum CSPSig<E, P> {
    #[doc(hidden)]
    ExternalChoice(ExternalChoice<P>),
    #[doc(hidden)]
    InternalChoice(InternalChoice<P>),
    #[doc(hidden)]
    Prefix(Prefix<E, P>),
    #[doc(hidden)]
    SequentialComposition(SequentialComposition<P>),
    #[doc(hidden)]
    Skip(Skip<E>),
    #[doc(hidden)]
    Stop(Stop<E>),
}

#[doc(hidden)]
#[enum_derive(Debug, Display)]
#[derive(Clone, Eq, PartialEq)]
pub enum CSPSigCursor<ExternalChoice, InternalChoice, Prefix, SequentialComposition, Skip, Stop> {
    ExternalChoice(ExternalChoice),
    InternalChoice(InternalChoice),
    Prefix(Prefix),
    SequentialComposition(SequentialComposition),
    Skip(Skip),
    Stop(Stop),
}

impl<E, P> Process<E> for CSPSig<E, P>
where
    E: Clone + Display + Eq + From<Tau> + From<Tick> + 'static,
    P: Clone + Process<E>,
    P::Cursor: Clone,
{
    type Cursor = CSPSigCursor<
        <ExternalChoice<P> as Process<E>>::Cursor,
        <InternalChoice<P> as Process<E>>::Cursor,
        <Prefix<E, P> as Process<E>>::Cursor,
        <SequentialComposition<P> as Process<E>>::Cursor,
        <Skip<E> as Process<E>>::Cursor,
        <Stop<E> as Process<E>>::Cursor,
    >;

    fn root(&self) -> Self::Cursor {
        match self {
            CSPSig::ExternalChoice(this) => CSPSigCursor::ExternalChoice(this.root()),
            CSPSig::InternalChoice(this) => CSPSigCursor::InternalChoice(this.root()),
            CSPSig::Prefix(this) => CSPSigCursor::Prefix(this.root()),
            CSPSig::SequentialComposition(this) => CSPSigCursor::SequentialComposition(this.root()),
            CSPSig::Skip(this) => CSPSigCursor::Skip(this.root()),
            CSPSig::Stop(this) => CSPSigCursor::Stop(this.root()),
        }
    }
}

impl<E, ExternalChoice, InternalChoice, Prefix, SequentialComposition, Skip, Stop> Cursor<E>
    for CSPSigCursor<ExternalChoice, InternalChoice, Prefix, SequentialComposition, Skip, Stop>
where
    ExternalChoice: Cursor<E>,
    InternalChoice: Cursor<E>,
    Prefix: Cursor<E>,
    SequentialComposition: Cursor<E>,
    Skip: Cursor<E>,
    Stop: Cursor<E>,
{
    type Alphabet = EmptyAlphabet;

    fn initials(&self) -> EmptyAlphabet {
        EmptyAlphabet
    }

    fn events<'a>(&'a self) -> Box<dyn Iterator<Item = E> + 'a> {
        match self {
            CSPSigCursor::ExternalChoice(this) => this.events(),
            CSPSigCursor::InternalChoice(this) => this.events(),
            CSPSigCursor::Prefix(this) => this.events(),
            CSPSigCursor::SequentialComposition(this) => this.events(),
            CSPSigCursor::Skip(this) => this.events(),
            CSPSigCursor::Stop(this) => this.events(),
        }
    }

    fn can_perform(&self, event: &E) -> bool {
        match self {
            CSPSigCursor::ExternalChoice(this) => this.can_perform(event),
            CSPSigCursor::InternalChoice(this) => this.can_perform(event),
            CSPSigCursor::Prefix(this) => this.can_perform(event),
            CSPSigCursor::SequentialComposition(this) => this.can_perform(event),
            CSPSigCursor::Skip(this) => this.can_perform(event),
            CSPSigCursor::Stop(this) => this.can_perform(event),
        }
    }

    fn perform(&mut self, event: &E) {
        match self {
            CSPSigCursor::ExternalChoice(this) => this.perform(event),
            CSPSigCursor::InternalChoice(this) => this.perform(event),
            CSPSigCursor::Prefix(this) => this.perform(event),
            CSPSigCursor::SequentialComposition(this) => this.perform(event),
            CSPSigCursor::Skip(this) => this.perform(event),
            CSPSigCursor::Stop(this) => this.perform(event),
        }
    }
}

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

    use proptest::arbitrary::any;
    use proptest::arbitrary::Arbitrary;
    use proptest::collection::vec;
    use proptest::prop_oneof;
    use proptest::strategy::BoxedStrategy;
    use proptest::strategy::Just;
    use proptest::strategy::MapInto;
    use proptest::strategy::Strategy;

    use crate::external_choice::external_choice;
    use crate::external_choice::replicated_external_choice;
    use crate::internal_choice::internal_choice;
    use crate::internal_choice::replicated_internal_choice;
    use crate::prefix::prefix;
    use crate::primitives::skip;
    use crate::primitives::stop;
    use crate::sequential_composition::sequential_composition;
    use crate::test_support::NumberedEvent;
    use crate::test_support::TestEvent;

    pub trait NameableEvents {
        type Strategy: Strategy;
        fn nameable_events() -> Self::Strategy;
    }

    impl NameableEvents for TestEvent {
        type Strategy = MapInto<<NumberedEvent as Arbitrary>::Strategy, TestEvent>;
        fn nameable_events() -> Self::Strategy {
            any::<NumberedEvent>().prop_map_into()
        }
    }

    impl<E> Arbitrary for CSP<E>
    where
        E: Clone + Debug + Display + NameableEvents + 'static,
        E::Strategy: Strategy<Value = E>,
    {
        type Parameters = ();
        type Strategy = BoxedStrategy<CSP<E>>;

        fn arbitrary_with(_args: ()) -> Self::Strategy {
            let leaf = prop_oneof![Just(stop()), Just(skip()),];
            let basic = leaf.prop_recursive(8, 16, 2, move |inner| {
                // We use NumberedEvent here because you shouldn't really create processes that
                // explicitly refer to Tau and Tick; those should only be created as part of
                // the CSP operators.
                (E::nameable_events(), inner.clone())
                    .prop_map(|(initial, after)| prefix(initial.into(), after))
            });
            basic
                .prop_recursive(4, 64, 16, move |inner| {
                    prop_oneof![
                        (inner.clone(), inner.clone()).prop_map(|(p, q)| external_choice(p, q)),
                        (inner.clone(), inner.clone()).prop_map(|(p, q)| internal_choice(p, q)),
                        (inner.clone(), inner.clone())
                            .prop_map(|(p, q)| sequential_composition(p, q)),
                        vec(inner.clone(), 3..8).prop_map(replicated_external_choice),
                        vec(inner.clone(), 3..8).prop_map(replicated_internal_choice),
                    ]
                })
                .boxed()
        }
    }

}
<commit_msg>Add Alphabet impl for CSP<commit_after>// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2019, HST authors.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied.  See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------------------

//! Defines a process type that includes all of the CSP language.

use std::fmt::Debug;
use std::fmt::Display;
use std::rc::Rc;

use auto_enums::enum_derive;
use auto_from::From;

use crate::event::Alphabet;
use crate::external_choice::ExternalChoice;
use crate::internal_choice::InternalChoice;
use crate::prefix::Prefix;
use crate::primitives::Skip;
use crate::primitives::Stop;
use crate::primitives::Tau;
use crate::primitives::Tick;
use crate::process::Cursor;
use crate::process::Process;
use crate::sequential_composition::SequentialComposition;

/// A process type that includes all of the primitive processes and operators in the CSP language.
/// Note that you should never need to construct instances of this type directly; use the helper
/// constructor for each process (e.g. [`stop`]) or operator (e.g. [`prefix`]) instead.
///
/// [`stop`]: ../primitives/fn.stop.html
/// [`prefix`]: ../prefix/fn.prefix.html
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct CSP<E>(Rc<CSPSig<E, CSP<E>>>);

impl<E: Display> Display for CSP<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self.0.as_ref() as &dyn Display).fmt(f)
    }
}

impl<E: Display> Debug for CSP<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self.0.as_ref() as &dyn Debug).fmt(f)
    }
}

impl<E, T> From<T> for CSP<E>
where
    CSPSig<E, CSP<E>>: From<T>,
{
    fn from(t: T) -> CSP<E> {
        CSP(Rc::new(CSPSig::from(t)))
    }
}

impl<E> Process<E> for CSP<E>
where
    E: Clone + Display + Eq + From<Tau> + From<Tick> + 'static,
{
    type Cursor = CSPCursor<E>;

    fn root(&self) -> Self::Cursor {
        CSPCursor(Box::new(self.0.root()))
    }
}

#[doc(hidden)]
#[derive(Clone, Eq, PartialEq)]
pub struct CSPCursor<E>(
    Box<
        CSPSigCursor<
            <ExternalChoice<CSP<E>> as Process<E>>::Cursor,
            <InternalChoice<CSP<E>> as Process<E>>::Cursor,
            <Prefix<E, CSP<E>> as Process<E>>::Cursor,
            <SequentialComposition<CSP<E>> as Process<E>>::Cursor,
            <Skip<E> as Process<E>>::Cursor,
            <Stop<E> as Process<E>>::Cursor,
        >,
    >,
)
where
    E: Clone + Display + Eq + From<Tau> + From<Tick> + 'static;

impl<E> Debug for CSPCursor<E>
where
    E: Clone + Debug + Display + Eq + From<Tau> + From<Tick> + 'static,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self.0.as_ref() as &dyn Debug).fmt(f)
    }
}

impl<E> Cursor<E> for CSPCursor<E>
where
    E: Clone + Display + Eq + From<Tau> + From<Tick> + 'static,
{
    type Alphabet = CSPAlphabet<E>;

    fn initials(&self) -> Self::Alphabet {
        CSPAlphabet(Box::new(self.0.initials()))
    }

    fn events<'a>(&'a self) -> Box<dyn Iterator<Item = E> + 'a> {
        self.0.events()
    }

    fn can_perform(&self, event: &E) -> bool {
        self.0.can_perform(event)
    }

    fn perform(&mut self, event: &E) {
        self.0.perform(event);
    }
}

#[doc(hidden)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CSPAlphabet<E>(
    Box<
        CSPSigAlphabet<
            <<ExternalChoice<CSP<E>> as Process<E>>::Cursor as Cursor<E>>::Alphabet,
            <<InternalChoice<CSP<E>> as Process<E>>::Cursor as Cursor<E>>::Alphabet,
            <<Prefix<E, CSP<E>> as Process<E>>::Cursor as Cursor<E>>::Alphabet,
            <<SequentialComposition<CSP<E>> as Process<E>>::Cursor as Cursor<E>>::Alphabet,
            <<Skip<E> as Process<E>>::Cursor as Cursor<E>>::Alphabet,
            <<Stop<E> as Process<E>>::Cursor as Cursor<E>>::Alphabet,
        >,
    >,
)
where
    E: Clone + Display + Eq + From<Tau> + From<Tick> + 'static;

impl<E> Alphabet<E> for CSPAlphabet<E>
where
    E: Clone + Display + Eq + From<Tau> + From<Tick> + 'static,
{
    fn contains(&self, event: &E) -> bool {
        self.0.contains(event)
    }
}

#[doc(hidden)]
#[enum_derive(Debug, Display)]
#[derive(Clone, Eq, From, Hash, PartialEq)]
pub enum CSPSig<E, P> {
    #[doc(hidden)]
    ExternalChoice(ExternalChoice<P>),
    #[doc(hidden)]
    InternalChoice(InternalChoice<P>),
    #[doc(hidden)]
    Prefix(Prefix<E, P>),
    #[doc(hidden)]
    SequentialComposition(SequentialComposition<P>),
    #[doc(hidden)]
    Skip(Skip<E>),
    #[doc(hidden)]
    Stop(Stop<E>),
}

#[doc(hidden)]
#[enum_derive(Debug, Display)]
#[derive(Clone, Eq, PartialEq)]
pub enum CSPSigCursor<ExternalChoice, InternalChoice, Prefix, SequentialComposition, Skip, Stop> {
    ExternalChoice(ExternalChoice),
    InternalChoice(InternalChoice),
    Prefix(Prefix),
    SequentialComposition(SequentialComposition),
    Skip(Skip),
    Stop(Stop),
}

impl<E, P> Process<E> for CSPSig<E, P>
where
    E: Clone + Display + Eq + From<Tau> + From<Tick> + 'static,
    P: Clone + Process<E>,
    P::Cursor: Clone,
{
    type Cursor = CSPSigCursor<
        <ExternalChoice<P> as Process<E>>::Cursor,
        <InternalChoice<P> as Process<E>>::Cursor,
        <Prefix<E, P> as Process<E>>::Cursor,
        <SequentialComposition<P> as Process<E>>::Cursor,
        <Skip<E> as Process<E>>::Cursor,
        <Stop<E> as Process<E>>::Cursor,
    >;

    fn root(&self) -> Self::Cursor {
        match self {
            CSPSig::ExternalChoice(this) => CSPSigCursor::ExternalChoice(this.root()),
            CSPSig::InternalChoice(this) => CSPSigCursor::InternalChoice(this.root()),
            CSPSig::Prefix(this) => CSPSigCursor::Prefix(this.root()),
            CSPSig::SequentialComposition(this) => CSPSigCursor::SequentialComposition(this.root()),
            CSPSig::Skip(this) => CSPSigCursor::Skip(this.root()),
            CSPSig::Stop(this) => CSPSigCursor::Stop(this.root()),
        }
    }
}

impl<E, ExternalChoice, InternalChoice, Prefix, SequentialComposition, Skip, Stop> Cursor<E>
    for CSPSigCursor<ExternalChoice, InternalChoice, Prefix, SequentialComposition, Skip, Stop>
where
    ExternalChoice: Cursor<E>,
    InternalChoice: Cursor<E>,
    Prefix: Cursor<E>,
    SequentialComposition: Cursor<E>,
    Skip: Cursor<E>,
    Stop: Cursor<E>,
{
    type Alphabet = CSPSigAlphabet<
        ExternalChoice::Alphabet,
        InternalChoice::Alphabet,
        Prefix::Alphabet,
        SequentialComposition::Alphabet,
        Skip::Alphabet,
        Stop::Alphabet,
    >;

    fn initials(&self) -> Self::Alphabet {
        match self {
            CSPSigCursor::ExternalChoice(this) => CSPSigAlphabet::ExternalChoice(this.initials()),
            CSPSigCursor::InternalChoice(this) => CSPSigAlphabet::InternalChoice(this.initials()),
            CSPSigCursor::Prefix(this) => CSPSigAlphabet::Prefix(this.initials()),
            CSPSigCursor::SequentialComposition(this) => {
                CSPSigAlphabet::SequentialComposition(this.initials())
            }
            CSPSigCursor::Skip(this) => CSPSigAlphabet::Skip(this.initials()),
            CSPSigCursor::Stop(this) => CSPSigAlphabet::Stop(this.initials()),
        }
    }

    fn events<'a>(&'a self) -> Box<dyn Iterator<Item = E> + 'a> {
        match self {
            CSPSigCursor::ExternalChoice(this) => this.events(),
            CSPSigCursor::InternalChoice(this) => this.events(),
            CSPSigCursor::Prefix(this) => this.events(),
            CSPSigCursor::SequentialComposition(this) => this.events(),
            CSPSigCursor::Skip(this) => this.events(),
            CSPSigCursor::Stop(this) => this.events(),
        }
    }

    fn can_perform(&self, event: &E) -> bool {
        match self {
            CSPSigCursor::ExternalChoice(this) => this.can_perform(event),
            CSPSigCursor::InternalChoice(this) => this.can_perform(event),
            CSPSigCursor::Prefix(this) => this.can_perform(event),
            CSPSigCursor::SequentialComposition(this) => this.can_perform(event),
            CSPSigCursor::Skip(this) => this.can_perform(event),
            CSPSigCursor::Stop(this) => this.can_perform(event),
        }
    }

    fn perform(&mut self, event: &E) {
        match self {
            CSPSigCursor::ExternalChoice(this) => this.perform(event),
            CSPSigCursor::InternalChoice(this) => this.perform(event),
            CSPSigCursor::Prefix(this) => this.perform(event),
            CSPSigCursor::SequentialComposition(this) => this.perform(event),
            CSPSigCursor::Skip(this) => this.perform(event),
            CSPSigCursor::Stop(this) => this.perform(event),
        }
    }
}

#[doc(hidden)]
#[enum_derive(Debug, Display)]
#[derive(Clone, Eq, PartialEq)]
pub enum CSPSigAlphabet<ExternalChoice, InternalChoice, Prefix, SequentialComposition, Skip, Stop> {
    ExternalChoice(ExternalChoice),
    InternalChoice(InternalChoice),
    Prefix(Prefix),
    SequentialComposition(SequentialComposition),
    Skip(Skip),
    Stop(Stop),
}

impl<E, ExternalChoice, InternalChoice, Prefix, SequentialComposition, Skip, Stop> Alphabet<E>
    for CSPSigAlphabet<ExternalChoice, InternalChoice, Prefix, SequentialComposition, Skip, Stop>
where
    ExternalChoice: Alphabet<E>,
    InternalChoice: Alphabet<E>,
    Prefix: Alphabet<E>,
    SequentialComposition: Alphabet<E>,
    Skip: Alphabet<E>,
    Stop: Alphabet<E>,
{
    fn contains(&self, event: &E) -> bool {
        match self {
            CSPSigAlphabet::ExternalChoice(this) => this.contains(event),
            CSPSigAlphabet::InternalChoice(this) => this.contains(event),
            CSPSigAlphabet::Prefix(this) => this.contains(event),
            CSPSigAlphabet::SequentialComposition(this) => this.contains(event),
            CSPSigAlphabet::Skip(this) => this.contains(event),
            CSPSigAlphabet::Stop(this) => this.contains(event),
        }
    }
}

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

    use proptest::arbitrary::any;
    use proptest::arbitrary::Arbitrary;
    use proptest::collection::vec;
    use proptest::prop_oneof;
    use proptest::strategy::BoxedStrategy;
    use proptest::strategy::Just;
    use proptest::strategy::MapInto;
    use proptest::strategy::Strategy;

    use crate::external_choice::external_choice;
    use crate::external_choice::replicated_external_choice;
    use crate::internal_choice::internal_choice;
    use crate::internal_choice::replicated_internal_choice;
    use crate::prefix::prefix;
    use crate::primitives::skip;
    use crate::primitives::stop;
    use crate::sequential_composition::sequential_composition;
    use crate::test_support::NumberedEvent;
    use crate::test_support::TestEvent;

    pub trait NameableEvents {
        type Strategy: Strategy;
        fn nameable_events() -> Self::Strategy;
    }

    impl NameableEvents for TestEvent {
        type Strategy = MapInto<<NumberedEvent as Arbitrary>::Strategy, TestEvent>;
        fn nameable_events() -> Self::Strategy {
            any::<NumberedEvent>().prop_map_into()
        }
    }

    impl<E> Arbitrary for CSP<E>
    where
        E: Clone + Debug + Display + NameableEvents + 'static,
        E::Strategy: Strategy<Value = E>,
    {
        type Parameters = ();
        type Strategy = BoxedStrategy<CSP<E>>;

        fn arbitrary_with(_args: ()) -> Self::Strategy {
            let leaf = prop_oneof![Just(stop()), Just(skip()),];
            let basic = leaf.prop_recursive(8, 16, 2, move |inner| {
                // We use NumberedEvent here because you shouldn't really create processes that
                // explicitly refer to Tau and Tick; those should only be created as part of
                // the CSP operators.
                (E::nameable_events(), inner.clone())
                    .prop_map(|(initial, after)| prefix(initial.into(), after))
            });
            basic
                .prop_recursive(4, 64, 16, move |inner| {
                    prop_oneof![
                        (inner.clone(), inner.clone()).prop_map(|(p, q)| external_choice(p, q)),
                        (inner.clone(), inner.clone()).prop_map(|(p, q)| internal_choice(p, q)),
                        (inner.clone(), inner.clone())
                            .prop_map(|(p, q)| sequential_composition(p, q)),
                        vec(inner.clone(), 3..8).prop_map(replicated_external_choice),
                        vec(inner.clone(), 3..8).prop_map(replicated_internal_choice),
                    ]
                })
                .boxed()
        }
    }

}
<|endoftext|>


<commit_before>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fs::File;
use std::io::{self, Read};

/// A simple prng based on a Linear congruential generator
/// https://en.wikipedia.org/wiki/Linear_congruential_generator
pub struct SimpleRng {
    seed: u64,
}

impl SimpleRng {
    /// Create a new SimpleRng
    pub fn new(seed: u64) -> SimpleRng {
        SimpleRng { seed }
    }

    /// Generate random u64
    pub fn rng(&mut self) -> u64 {
        // a simple Linear congruential generator
        let a: u64 = 6364136223846793005;
        let c: u64 = 1442695040888963407;
        self.seed = a.wrapping_mul(self.seed).wrapping_add(c);
        self.seed
    }
}

// Uniformly samples the ASCII alphanumeric characters given a random variable. If an `Err` is
// passed in, the error is returned as `Some(Err(...))`. If the the random variable can not be used
// to uniformly sample, `None` is returned.
fn uniform_sample_ascii_alphanumeric(
    b: Result<u8, std::io::Error>,
) -> Option<Result<char, std::io::Error>> {
    const ASCII_CHARS: &[u8] = b"\
          ABCDEFGHIJKLMNOPQRSTUVWXYZ\
          abcdefghijklmnopqrstuvwxyz\
          0123456789";
    let char_index = match b {
        Ok(c) => c as usize,
        Err(e) => return Some(Err(e)),
    };
    // Throw away numbers that would cause sampling bias.
    if char_index >= ASCII_CHARS.len() * 4 {
        None
    } else {
        Some(Ok(ASCII_CHARS[char_index % ASCII_CHARS.len()] as char))
    }
}

/// Samples `/dev/urandom` and generates a random ASCII string of length `len`
pub fn urandom_str(len: usize) -> io::Result<String> {
    File::open("/dev/urandom")?
        .bytes()
        .filter_map(uniform_sample_ascii_alphanumeric)
        .take(len)
        .collect::<io::Result<String>>()
}

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

    #[test]
    fn check_100() {
        for i in 0..100 {
            let s = urandom_str(i).unwrap();
            assert_eq!(s.len(), i);
            assert!(s.is_ascii());
            assert!(!s.contains(' '));
            assert!(!s.contains(|c: char| !c.is_ascii_alphanumeric()));
        }
    }
}
<commit_msg>rand_ish: Generate random string from SimpleRng<commit_after>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fs::File;
use std::io::{self, Read};

/// A simple prng based on a Linear congruential generator
/// https://en.wikipedia.org/wiki/Linear_congruential_generator
pub struct SimpleRng {
    seed: u64,
}

impl SimpleRng {
    /// Create a new SimpleRng
    pub fn new(seed: u64) -> SimpleRng {
        SimpleRng { seed }
    }

    /// Generate random u64
    pub fn rng(&mut self) -> u64 {
        // a simple Linear congruential generator
        let a: u64 = 6364136223846793005;
        let c: u64 = 1442695040888963407;
        self.seed = a.wrapping_mul(self.seed).wrapping_add(c);
        self.seed
    }

    /// Generate a random alphanumeric string.
    pub fn str(&mut self, len: usize) -> String {
        self.filter_map(|v| uniform_sample_ascii_alphanumeric(v as u8))
            .take(len)
            .collect()
    }
}

impl Iterator for SimpleRng {
    type Item = u64;

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

// Uniformly samples the ASCII alphanumeric characters given a random variable. If an `Err` is
// passed in, the error is returned as `Some(Err(...))`. If the the random variable can not be used
// to uniformly sample, `None` is returned.
fn uniform_sample_ascii_alphanumeric(b: u8) -> Option<char> {
    const ASCII_CHARS: &[u8] = b"\
          ABCDEFGHIJKLMNOPQRSTUVWXYZ\
          abcdefghijklmnopqrstuvwxyz\
          0123456789";
    let char_index = b as usize;
    // Throw away numbers that would cause sampling bias.
    if char_index >= ASCII_CHARS.len() * 4 {
        None
    } else {
        Some(ASCII_CHARS[char_index % ASCII_CHARS.len()] as char)
    }
}

/// Samples `/dev/urandom` and generates a random ASCII string of length `len`
pub fn urandom_str(len: usize) -> io::Result<String> {
    File::open("/dev/urandom")?
        .bytes()
        .filter_map(|b| b.map(uniform_sample_ascii_alphanumeric).transpose())
        .take(len)
        .collect::<io::Result<String>>()
}

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

    #[test]
    fn check_100() {
        for i in 0..100 {
            let s = urandom_str(i).unwrap();
            assert_eq!(s.len(), i);
            assert!(s.is_ascii());
            assert!(!s.contains(' '));
            assert!(!s.contains(|c: char| !c.is_ascii_alphanumeric()));
        }
    }
}
<|endoftext|>


<commit_before>use {Service};
use super::{Error, Frame, Transport};
use reactor::{Task, Tick};
use util::future::AwaitQueue;
use std::io;

/// A server `Task` that dispatches `Transport` messages to a `Service` using
/// protocol pipelining.
pub struct Server<S, T>
    where S: Service,
{
    run: bool,
    service: S,
    transport: T,
    in_flight: AwaitQueue<S::Fut>,
}

impl<S, T> Server<S, T>
    where S: Service,
{
    /// Create a new pipeline `Server` dispatcher with the given service and
    /// transport
    pub fn new(service: S, transport: T) -> io::Result<Server<S, T>> {
        Ok(Server {
            run: true,
            service: service,
            transport: transport,
            in_flight: try!(AwaitQueue::with_capacity(16)),
        })
    }
}

impl<S, T, E> Task for Server<S, T>
    where S: Service<Error = E>,
          T: Transport<In=S::Resp, Out=S::Req>,
          E: From<Error<T::Error>> + Send + 'static,
{
    fn tick(&mut self) -> io::Result<Tick> {
        trace!("pipeline::Server::tick");

        // The first action is always flushing the transport
        let mut flush = try!(self.transport.flush());

        // Handle completed responses
        while self.transport.is_writable() {
            trace!("pipeline transport is writable");

            // Try to get the next completed future
            match self.in_flight.poll() {
                Some(Ok(val)) => {
                    trace!("got in_flight value");
                    flush = try!(self.transport.write(Frame::Message(val)));
                }
                Some(Err(_)) => unimplemented!(),
                None => {
                    trace!("no response ready for write");
                    break;
                }
            }
        }

        // Process new requests as long as the server is accepting
        while self.run {
            trace!("pipeline trying to read transport");
            match self.transport.read() {
                Ok(Some(frame)) => {
                    match frame {
                        Frame::Message(req) => {
                            trace!("pipeline got request");
                            let resp = self.service.call(req);
                            self.in_flight.push(resp)
                        }
                        Frame::Done => {
                            trace!("received Frame::Done");
                            // At this point, we just return. This works
                            // because tick() will be called again and go
                            // through the read-cycle again.
                            self.run = false;
                            break;
                        }
                        Frame::Error(_) => {
                            return Err(io::Error::new(io::ErrorKind::BrokenPipe, "An error occurred."));
                        }
                    }
                }
                Ok(None) => break,
                Err(_) => unimplemented!(),
            }
        }

        // Clean shutdown of the pipeline server can happen when
        //
        // 1. The server is done running, this is signaled by Transport::read()
        //    returning Frame::Done.
        //
        // 2. The transport is done writing all data to the socket, this is
        //    signaled by Transport::flush() returning Ok(Some(())).
        //
        // 3. There are no further responses to write to the transport.
        //
        // It is necessary to perfom these three checks in order to handle the
        // case where the client shuts down half the socket.
        //
        if !self.run && flush.is_some() && self.in_flight.is_empty() {
            return Ok(Tick::Final);
        }

        // Tick again later
        Ok(Tick::WouldBlock)
    }
}
<commit_msg>Panic with error msg instead of unimplemented<commit_after>use {Service};
use super::{Error, Frame, Transport};
use reactor::{Task, Tick};
use util::future::AwaitQueue;
use std::io;

/// A server `Task` that dispatches `Transport` messages to a `Service` using
/// protocol pipelining.
pub struct Server<S, T>
    where S: Service,
{
    run: bool,
    service: S,
    transport: T,
    in_flight: AwaitQueue<S::Fut>,
}

impl<S, T> Server<S, T>
    where S: Service,
{
    /// Create a new pipeline `Server` dispatcher with the given service and
    /// transport
    pub fn new(service: S, transport: T) -> io::Result<Server<S, T>> {
        Ok(Server {
            run: true,
            service: service,
            transport: transport,
            in_flight: try!(AwaitQueue::with_capacity(16)),
        })
    }
}

impl<S, T, E> Task for Server<S, T>
    where S: Service<Error = E>,
          T: Transport<In=S::Resp, Out=S::Req>,
          E: From<Error<T::Error>> + Send + 'static,
{
    fn tick(&mut self) -> io::Result<Tick> {
        trace!("pipeline::Server::tick");

        // The first action is always flushing the transport
        let mut flush = try!(self.transport.flush());

        // Handle completed responses
        while self.transport.is_writable() {
            trace!("pipeline transport is writable");

            // Try to get the next completed future
            match self.in_flight.poll() {
                Some(Ok(val)) => {
                    trace!("got in_flight value");
                    flush = try!(self.transport.write(Frame::Message(val)));
                }
                Some(Err(_)) => unimplemented!(),
                None => {
                    trace!("no response ready for write");
                    break;
                }
            }
        }

        // Process new requests as long as the server is accepting
        while self.run {
            trace!("pipeline trying to read transport");
            match self.transport.read() {
                Ok(Some(frame)) => {
                    match frame {
                        Frame::Message(req) => {
                            trace!("pipeline got request");
                            let resp = self.service.call(req);
                            self.in_flight.push(resp)
                        }
                        Frame::Done => {
                            trace!("received Frame::Done");
                            // At this point, we just return. This works
                            // because tick() will be called again and go
                            // through the read-cycle again.
                            self.run = false;
                            break;
                        }
                        Frame::Error(_) => {
                            return Err(io::Error::new(io::ErrorKind::BrokenPipe, "An error occurred."));
                        }
                    }
                }
                Ok(None) => break,
                Err(e) => panic!(e.to_string()),
            }
        }

        // Clean shutdown of the pipeline server can happen when
        //
        // 1. The server is done running, this is signaled by Transport::read()
        //    returning Frame::Done.
        //
        // 2. The transport is done writing all data to the socket, this is
        //    signaled by Transport::flush() returning Ok(Some(())).
        //
        // 3. There are no further responses to write to the transport.
        //
        // It is necessary to perfom these three checks in order to handle the
        // case where the client shuts down half the socket.
        //
        if !self.run && flush.is_some() && self.in_flight.is_empty() {
            return Ok(Tick::Final);
        }

        // Tick again later
        Ok(Tick::WouldBlock)
    }
}
<|endoftext|>


<commit_before>use error::Error;
use client::Client;
use resources::{Address, Card, Currency};
use params::{Metadata, Timestamp};

#[derive(Serialize)]
pub struct OwnerParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub address: Option<Address>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub email: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub phone: Option<&'a str>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct CodeVerification {
    pub attempts_remaining: i64,
    pub status: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct VerifiedAddress {
    pub city: Address,
    pub country: String,
    pub line1: String,
    pub line2: String,
    pub postal_code: String,
    pub state: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Receiver {
    pub address: String,
    pub amount_charged: i64,
    pub amount_receive: i64,
    pub amount_returned: i64,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Redirect {
    pub failure_reason: String,
    pub return_url: String,
    pub status: String,
    pub url: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Owner {
    pub address: Address,
    pub email: String,
    pub name: String,
    pub phone: String,
    pub verified_address: VerifiedAddress,
    pub verified_email: String,
    pub verified_name: String,
    pub verified_phone: String,
    pub receiver: Option<Receiver>,
    pub redirect: Option<Redirect>,
}

#[derive(Serialize)]
pub struct RedirectParams<'a> {
    return_url: &'a str,
}

#[derive(Default, Serialize)]
pub struct SourceParams<'a> {
    #[serde(rename = "type")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub source_type: Option<&'static str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub amount: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub currency: Option<Currency>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub flow: Option<&'a str>, // (redirect, receiver, code_verification, none)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<Metadata>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub owner: Option<OwnerParams<'a>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub statement_descriptor: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub redirect: Option<RedirectParams<'a>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub token: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub usage: Option<&'a str>, // (reusable, single-use)
}

#[derive(Debug, Deserialize)]
#[serde(tag = "object")]
pub enum PaymentSource {
    // BitcoinReceiver(...),
    #[serde(rename = "card")]
    Card(Card),
    #[serde(rename = "source")]
    Source(Source),
}

/// The resource representing a Stripe source.
///
/// For more details see https://stripe.com/docs/api#sources.
#[derive(Debug, Deserialize)]
pub struct Source {
    pub id: String,
    pub object: String, // source
    pub amount: i64,
    pub client_secret: String,
    pub code_verification: Option<CodeVerification>,
    pub created: Timestamp,
    pub currency: Currency,
    pub flow: String,
    pub livemode: bool,
    pub metadata: Metadata,
    pub owner: Owner,
    pub statement_descriptor: String,
    pub status: String,
    #[serde(rename = "type")]
    pub source_type: String, // (ach_credit_transfer, card, alipay etc.)
    pub usage: String, // (reusable, single-use)
}

impl PaymentSource {
    pub fn create(client: &Client, params: SourceParams) -> Result<PaymentSource, Error> {
        client.post("/sources", params)
    }

    pub fn get(client: &Client, source_id: &str) -> Result<PaymentSource, Error> {
        client.get(&format!("/sources/{}", source_id))
    }

    pub fn update(client: &Client, source_id: &str, params: SourceParams) -> Result<PaymentSource, Error> {
        client.post(&format!("/source/{}", source_id), params)
    }

    /// Attaches a source to a customer, does not change default Source for the Customer
    ///
    /// For more details see https://stripe.com/docs/api#attach_source.
    pub fn attach_source(client: &Client, customer_id: &str, source: &str) -> Result<PaymentSource, Error> {
        client.post(&format!("/customers/{}/sources", customer_id), source)
    }

    /// Detaches a source from a customer
    ///
    /// For more details see https://stripe.com/docs/api#detach_source.
    pub fn detach_source(client: &Client, customer_id: &str, source_id: &str) -> Result<PaymentSource, Error> {
        client.delete(&format!("/customers/{}/sources/{}", customer_id, source_id))
    }
}
<commit_msg>Update Source source_type type<commit_after>use error::Error;
use client::Client;
use resources::{Address, Card, Currency};
use params::{Metadata, Timestamp};

#[derive(Serialize)]
pub struct OwnerParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub address: Option<Address>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub email: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub phone: Option<&'a str>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct CodeVerification {
    pub attempts_remaining: i64,
    pub status: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct VerifiedAddress {
    pub city: Address,
    pub country: String,
    pub line1: String,
    pub line2: String,
    pub postal_code: String,
    pub state: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Receiver {
    pub address: String,
    pub amount_charged: i64,
    pub amount_receive: i64,
    pub amount_returned: i64,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Redirect {
    pub failure_reason: String,
    pub return_url: String,
    pub status: String,
    pub url: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Owner {
    pub address: Address,
    pub email: String,
    pub name: String,
    pub phone: String,
    pub verified_address: VerifiedAddress,
    pub verified_email: String,
    pub verified_name: String,
    pub verified_phone: String,
    pub receiver: Option<Receiver>,
    pub redirect: Option<Redirect>,
}

#[derive(Serialize)]
pub struct RedirectParams<'a> {
    return_url: &'a str,
}

#[derive(Default, Serialize)]
pub struct SourceParams<'a> {
    #[serde(rename = "type")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub source_type: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub amount: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub currency: Option<Currency>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub flow: Option<&'a str>, // (redirect, receiver, code_verification, none)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<Metadata>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub owner: Option<OwnerParams<'a>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub statement_descriptor: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub redirect: Option<RedirectParams<'a>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub token: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub usage: Option<&'a str>, // (reusable, single-use)
}

#[derive(Debug, Deserialize)]
#[serde(tag = "object")]
pub enum PaymentSource {
    // BitcoinReceiver(...),
    #[serde(rename = "card")]
    Card(Card),
    #[serde(rename = "source")]
    Source(Source),
}

/// The resource representing a Stripe source.
///
/// For more details see https://stripe.com/docs/api#sources.
#[derive(Debug, Deserialize)]
pub struct Source {
    pub id: String,
    pub object: String, // source
    pub amount: i64,
    pub client_secret: String,
    pub code_verification: Option<CodeVerification>,
    pub created: Timestamp,
    pub currency: Currency,
    pub flow: String,
    pub livemode: bool,
    pub metadata: Metadata,
    pub owner: Owner,
    pub statement_descriptor: String,
    pub status: String,
    #[serde(rename = "type")]
    pub source_type: String, // (ach_credit_transfer, card, alipay etc.)
    pub usage: String, // (reusable, single-use)
}

impl PaymentSource {
    pub fn create(client: &Client, params: SourceParams) -> Result<PaymentSource, Error> {
        client.post("/sources", params)
    }

    pub fn get(client: &Client, source_id: &str) -> Result<PaymentSource, Error> {
        client.get(&format!("/sources/{}", source_id))
    }

    pub fn update(client: &Client, source_id: &str, params: SourceParams) -> Result<PaymentSource, Error> {
        client.post(&format!("/source/{}", source_id), params)
    }

    /// Attaches a source to a customer, does not change default Source for the Customer
    ///
    /// For more details see https://stripe.com/docs/api#attach_source.
    pub fn attach_source(client: &Client, customer_id: &str, source: &str) -> Result<PaymentSource, Error> {
        client.post(&format!("/customers/{}/sources", customer_id), source)
    }

    /// Detaches a source from a customer
    ///
    /// For more details see https://stripe.com/docs/api#detach_source.
    pub fn detach_source(client: &Client, customer_id: &str, source_id: &str) -> Result<PaymentSource, Error> {
        client.delete(&format!("/customers/{}/sources/{}", customer_id, source_id))
    }
}
<|endoftext|>


<commit_before>use crate::utils::{match_def_path, span_lint_and_sugg};
use if_chain::if_chain;
use rustc::declare_lint_pass;
use rustc::hir;
use rustc::hir::def::{DefKind, Res};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc_errors::Applicability;
use rustc_session::declare_tool_lint;

declare_clippy_lint! {
    /// **What it does:** Checks for usage of `ATOMIC_X_INIT`, `ONCE_INIT`, and
    /// `uX/iX::MIN/MAX`.
    ///
    /// **Why is this bad?** `const fn`s exist
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// # use core::sync::atomic::{ATOMIC_ISIZE_INIT, AtomicIsize};
    /// static FOO: AtomicIsize = ATOMIC_ISIZE_INIT;
    /// ```
    ///
    /// Could be written:
    ///
    /// ```rust
    /// # use core::sync::atomic::AtomicIsize;
    /// static FOO: AtomicIsize = AtomicIsize::new(0);
    /// ```
    pub REPLACE_CONSTS,
    pedantic,
    "Lint usages of standard library `const`s that could be replaced by `const fn`s"
}

declare_lint_pass!(ReplaceConsts => [REPLACE_CONSTS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) {
        if_chain! {
            if let hir::ExprKind::Path(ref qp) = expr.kind;
            if let Res::Def(DefKind::Const, def_id) = cx.tables.qpath_res(qp, expr.hir_id);
            then {
                for &(ref const_path, repl_snip) in &REPLACEMENTS {
                    if match_def_path(cx, def_id, const_path) {
                        span_lint_and_sugg(
                            cx,
                            REPLACE_CONSTS,
                            expr.span,
                            &format!("using `{}`", const_path.last().expect("empty path")),
                            "try this",
                            repl_snip.to_string(),
                            Applicability::MachineApplicable,
                        );
                        return;
                    }
                }
            }
        }
    }
}

const REPLACEMENTS: [([&str; 3], &str); 24] = [
    // Min
    (["core", "isize", "MIN"], "isize::min_value()"),
    (["core", "i8", "MIN"], "i8::min_value()"),
    (["core", "i16", "MIN"], "i16::min_value()"),
    (["core", "i32", "MIN"], "i32::min_value()"),
    (["core", "i64", "MIN"], "i64::min_value()"),
    (["core", "i128", "MIN"], "i128::min_value()"),
    (["core", "usize", "MIN"], "usize::min_value()"),
    (["core", "u8", "MIN"], "u8::min_value()"),
    (["core", "u16", "MIN"], "u16::min_value()"),
    (["core", "u32", "MIN"], "u32::min_value()"),
    (["core", "u64", "MIN"], "u64::min_value()"),
    (["core", "u128", "MIN"], "u128::min_value()"),
    // Max
    (["core", "isize", "MAX"], "isize::max_value()"),
    (["core", "i8", "MAX"], "i8::max_value()"),
    (["core", "i16", "MAX"], "i16::max_value()"),
    (["core", "i32", "MAX"], "i32::max_value()"),
    (["core", "i64", "MAX"], "i64::max_value()"),
    (["core", "i128", "MAX"], "i128::max_value()"),
    (["core", "usize", "MAX"], "usize::max_value()"),
    (["core", "u8", "MAX"], "u8::max_value()"),
    (["core", "u16", "MAX"], "u16::max_value()"),
    (["core", "u32", "MAX"], "u32::max_value()"),
    (["core", "u64", "MAX"], "u64::max_value()"),
    (["core", "u128", "MAX"], "u128::max_value()"),
];
<commit_msg>Fix `replace_consts` lint documentation<commit_after>use crate::utils::{match_def_path, span_lint_and_sugg};
use if_chain::if_chain;
use rustc::declare_lint_pass;
use rustc::hir;
use rustc::hir::def::{DefKind, Res};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc_errors::Applicability;
use rustc_session::declare_tool_lint;

declare_clippy_lint! {
    /// **What it does:** Checks for usage of standard library
    /// `const`s that could be replaced by `const fn`s.
    ///
    /// **Why is this bad?** `const fn`s exist
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// let x = std::u32::MIN;
    /// let y = std::u32::MAX;
    /// ```
    ///
    /// Could be written:
    ///
    /// ```rust
    /// let x = u32::min_value();
    /// let y = u32::max_value();
    /// ```
    pub REPLACE_CONSTS,
    pedantic,
    "Lint usages of standard library `const`s that could be replaced by `const fn`s"
}

declare_lint_pass!(ReplaceConsts => [REPLACE_CONSTS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) {
        if_chain! {
            if let hir::ExprKind::Path(ref qp) = expr.kind;
            if let Res::Def(DefKind::Const, def_id) = cx.tables.qpath_res(qp, expr.hir_id);
            then {
                for &(ref const_path, repl_snip) in &REPLACEMENTS {
                    if match_def_path(cx, def_id, const_path) {
                        span_lint_and_sugg(
                            cx,
                            REPLACE_CONSTS,
                            expr.span,
                            &format!("using `{}`", const_path.last().expect("empty path")),
                            "try this",
                            repl_snip.to_string(),
                            Applicability::MachineApplicable,
                        );
                        return;
                    }
                }
            }
        }
    }
}

const REPLACEMENTS: [([&str; 3], &str); 24] = [
    // Min
    (["core", "isize", "MIN"], "isize::min_value()"),
    (["core", "i8", "MIN"], "i8::min_value()"),
    (["core", "i16", "MIN"], "i16::min_value()"),
    (["core", "i32", "MIN"], "i32::min_value()"),
    (["core", "i64", "MIN"], "i64::min_value()"),
    (["core", "i128", "MIN"], "i128::min_value()"),
    (["core", "usize", "MIN"], "usize::min_value()"),
    (["core", "u8", "MIN"], "u8::min_value()"),
    (["core", "u16", "MIN"], "u16::min_value()"),
    (["core", "u32", "MIN"], "u32::min_value()"),
    (["core", "u64", "MIN"], "u64::min_value()"),
    (["core", "u128", "MIN"], "u128::min_value()"),
    // Max
    (["core", "isize", "MAX"], "isize::max_value()"),
    (["core", "i8", "MAX"], "i8::max_value()"),
    (["core", "i16", "MAX"], "i16::max_value()"),
    (["core", "i32", "MAX"], "i32::max_value()"),
    (["core", "i64", "MAX"], "i64::max_value()"),
    (["core", "i128", "MAX"], "i128::max_value()"),
    (["core", "usize", "MAX"], "usize::max_value()"),
    (["core", "u8", "MAX"], "u8::max_value()"),
    (["core", "u16", "MAX"], "u16::max_value()"),
    (["core", "u32", "MAX"], "u32::max_value()"),
    (["core", "u64", "MAX"], "u64::max_value()"),
    (["core", "u128", "MAX"], "u128::max_value()"),
];
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! TcpRelay server that running on the server side

use std::io;
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::Arc;
use std::collections::HashSet;

use config::{Config, ServerConfig};

use crypto::CryptoMode;
use crypto::cipher;

use super::stream::{EncryptedWriter, DecryptedReader};

use relay::socks5::Address;

use futures::{self, Future, BoxFuture};
use futures::stream::Stream;

use futures_cpupool::CpuPool;

use tokio_core::reactor::Handle;
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::io::Io;
use tokio_core::io::{ReadHalf, WriteHalf};
use tokio_core::io::{read_exact, write_all, copy, flush};

use ip::IpAddr;

type ClientRead = ReadHalf<TcpStream>;
type ClientWrite = WriteHalf<TcpStream>;

type EncryptedHalf = EncryptedWriter<ClientWrite>;
type DecryptedHalf = DecryptedReader<ClientRead>;

/// TCP Relay backend
pub struct TcpRelayServer {
    config: Arc<Config>,
    cpu_pool: CpuPool,
}

impl TcpRelayServer {
    /// Creates an instance
    pub fn new(config: Arc<Config>, threads: usize) -> TcpRelayServer {
        TcpRelayServer {
            config: config,
            cpu_pool: CpuPool::new(threads),
        }
    }

    fn handshake((r, w): (ClientRead, ClientWrite),
                 svr_cfg: Arc<ServerConfig>)
                 -> BoxFuture<(DecryptedHalf, EncryptedHalf), io::Error> {
        let iv_len = svr_cfg.method.iv_size();

        let svr_cfg_cloned = svr_cfg.clone();
        let read_fut = read_exact(r, vec![0u8; iv_len]).and_then(move |(r, iv)| {
            trace!("Got handshake iv: {:?}", iv);
            let decryptor = cipher::with_type(svr_cfg.method,
                                              svr_cfg.password.as_bytes(),
                                              &iv[..],
                                              CryptoMode::Decrypt);
            let decrypt_stream = DecryptedReader::new(r, decryptor);

            Ok(decrypt_stream)
        });

        let write_fut = futures::lazy(move || {
            let svr_cfg = svr_cfg_cloned;

            let iv = svr_cfg.method.gen_init_vec();
            trace!("Going to send handshake iv: {:?}", iv);
            write_all(w, iv)
                .and_then(|(w, iv)| flush(w).map(|w| (w, iv)))
                .and_then(move |(w, iv)| {
                    let encryptor = cipher::with_type(svr_cfg.method,
                                                      svr_cfg.password.as_bytes(),
                                                      &iv[..],
                                                      CryptoMode::Encrypt);
                    let encrypt_stream = EncryptedWriter::new(w, encryptor);

                    Ok(encrypt_stream)
                })
        });

        read_fut.join(write_fut).boxed()
    }

    fn resolve_address(addr: Address, cpu_pool: CpuPool) -> BoxFuture<SocketAddr, io::Error> {
        match addr {
            Address::SocketAddress(addr) => futures::finished(addr).boxed(),
            Address::DomainNameAddress(dname, port) => {
                cpu_pool.spawn(futures::lazy(move || {
                        let dname = format!("{}:{}", dname, port);
                        let mut addrs = try!(dname.to_socket_addrs());
                        addrs.next().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to resolve domain"))
                    }))
                    .boxed()
            }
        }
    }

    fn resolve_remote(cpu_pool: CpuPool,
                      addr: Address,
                      forbidden_ip: Arc<HashSet<IpAddr>>)
                      -> BoxFuture<SocketAddr, io::Error> {
        TcpRelayServer::resolve_address(addr, cpu_pool)
            .and_then(move |addr| {
                trace!("Resolved address as {}", addr);
                let ipaddr = match addr.clone() {
                    SocketAddr::V4(v4) => IpAddr::V4(v4.ip().clone()),
                    SocketAddr::V6(v6) => IpAddr::V6(v6.ip().clone()),
                };

                if forbidden_ip.contains(&ipaddr) {
                    info!("{} has been forbidden", ipaddr);
                    let err = io::Error::new(io::ErrorKind::Other, "Forbidden IP");
                    Err(err)
                } else {
                    Ok(addr)
                }
            })
            .boxed()
    }

    fn connect_remote(cpu_pool: CpuPool,
                      handle: Handle,
                      addr: Address,
                      forbidden_ip: Arc<HashSet<IpAddr>>)
                      -> Box<Future<Item = TcpStream, Error = io::Error>> {
        trace!("Connecting to remote {}", addr);
        Box::new(TcpRelayServer::resolve_remote(cpu_pool, addr, forbidden_ip)
            .and_then(move |addr| TcpStream::connect(&addr, &handle)))
    }

    pub fn handle_client(handle: &Handle,
                         cpu_pool: CpuPool,
                         s: TcpStream,
                         svr_cfg: Arc<ServerConfig>,
                         forbidden_ip: Arc<HashSet<IpAddr>>)
                         -> io::Result<()> {
        let peer_addr = try!(s.peer_addr());
        trace!("Got connection from {}", peer_addr);

        let cloned_handle = handle.clone();
        let fut = futures::lazy(|| Ok(s.split()))
            .and_then(move |(r, w)| TcpRelayServer::handshake((r, w), svr_cfg))
            .and_then(|(r, w)| Address::read_from(r).map(|(r, addr)| (r, w, addr)).map_err(From::from))
            .and_then(move |(r, w, addr)| {
                info!("Connecting {}", addr);
                let cloned_addr = addr.clone();
                TcpRelayServer::connect_remote(cpu_pool, cloned_handle, addr, forbidden_ip)
                    .map(|svr_s| (svr_s, r, w, cloned_addr))
            })
            .and_then(|(svr_s, r, w, addr)| {
                let (svr_r, svr_w) = svr_s.split();
                let c2s = copy(r, svr_w);
                let s2c = copy(svr_r, w);
                c2s.join(s2c)
                    .then(move |_| {
                        trace!("Relay {} is finished", addr);
                        Ok(())
                    })
            });

        handle.spawn(fut.then(|res| {
            match res {
                Ok(..) => Ok(()),
                Err(err) => {
                    error!("Failed to handle client: {}", err);
                    Err(())
                }
            }
        }));

        Ok(())
    }

    /// Runs the server
    pub fn run(self, handle: Handle) -> Box<Future<Item = (), Error = io::Error>> {
        let mut fut: Option<Box<Future<Item = (), Error = io::Error>>> = None;

        for svr_cfg in &self.config.server {
            let listener = {
                let addr = &svr_cfg.addr;
                let listener = TcpListener::bind(addr, &handle).unwrap();
                trace!("ShadowSocks TCP Listening on {}", addr);
                listener
            };

            let svr_cfg = svr_cfg.clone();
            let handle = handle.clone();
            let forbidden_ip = self.config.forbidden_ip.clone();
            let cpu_pool = self.cpu_pool.clone();
            let listening = listener.incoming()
                .for_each(move |(socket, addr)| {
                    let server_cfg = svr_cfg.clone();
                    let forbidden_ip = forbidden_ip.clone();
                    let cpu_pool = cpu_pool.clone();

                    trace!("Got connection, addr: {}", addr);
                    trace!("Picked proxy server: {:?}", server_cfg);
                    TcpRelayServer::handle_client(&handle, cpu_pool, socket, server_cfg, forbidden_ip)
                })
                .map_err(|err| {
                    error!("Server run failed: {}", err);
                    err
                });

            fut = Some(match fut.take() {
                Some(fut) => Box::new(fut.join(listening).map(|_| ())) as Box<Future<Item = (), Error = io::Error>>,
                None => Box::new(listening) as Box<Future<Item = (), Error = io::Error>>,
            })
        }

        fut.expect("Must have at least one server")
    }
}
<commit_msg>[#28] Split server handshake to futures<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! TcpRelay server that running on the server side

use std::io;
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::Arc;
use std::collections::HashSet;

use config::{Config, ServerConfig};

use crypto::CryptoMode;
use crypto::cipher;

use super::stream::{EncryptedWriter, DecryptedReader};

use relay::socks5::Address;

use futures::{self, Future, BoxFuture};
use futures::stream::Stream;

use futures_cpupool::CpuPool;

use tokio_core::reactor::Handle;
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::io::Io;
use tokio_core::io::{ReadHalf, WriteHalf};
use tokio_core::io::{read_exact, write_all, copy, flush};

use ip::IpAddr;

type ClientRead = ReadHalf<TcpStream>;
type ClientWrite = WriteHalf<TcpStream>;

type EncryptedHalf = EncryptedWriter<ClientWrite>;
type DecryptedHalf = DecryptedReader<ClientRead>;

/// TCP Relay backend
pub struct TcpRelayServer {
    config: Arc<Config>,
    cpu_pool: CpuPool,
}

type BoxIoFuture<T> = BoxFuture<T, io::Error>;

impl TcpRelayServer {
    /// Creates an instance
    pub fn new(config: Arc<Config>, threads: usize) -> TcpRelayServer {
        TcpRelayServer {
            config: config,
            cpu_pool: CpuPool::new(threads),
        }
    }

    fn handshake(client: TcpStream,
                 svr_cfg: Arc<ServerConfig>)
                 -> BoxIoFuture<(BoxIoFuture<(super::DecryptedHalf, Address)>, super::EncryptedHalfFut)> {
        let iv_len = svr_cfg.method.iv_size();

        futures::lazy(move || Ok(client.split()))
            .and_then(move |(r, w)| {
                let svr_cfg_cloned = svr_cfg.clone();
                let read_fut = read_exact(r, vec![0u8; iv_len])
                    .and_then(move |(r, iv)| {
                        trace!("Got handshake iv: {:?}", iv);
                        let decryptor = cipher::with_type(svr_cfg.method,
                                                          svr_cfg.password.as_bytes(),
                                                          &iv[..],
                                                          CryptoMode::Decrypt);
                        let decrypt_stream = DecryptedReader::new(r, decryptor);

                        Ok(decrypt_stream)
                    })
                    .and_then(|r| Address::read_from(r).map_err(From::from))
                    .boxed();

                let write_fut = futures::lazy(move || {
                        let svr_cfg = svr_cfg_cloned;

                        let iv = svr_cfg.method.gen_init_vec();
                        trace!("Going to send handshake iv: {:?}", iv);
                        write_all(w, iv)
                            .and_then(|(w, iv)| flush(w).map(|w| (w, iv)))
                            .and_then(move |(w, iv)| {
                                let encryptor = cipher::with_type(svr_cfg.method,
                                                                  svr_cfg.password.as_bytes(),
                                                                  &iv[..],
                                                                  CryptoMode::Encrypt);
                                let encrypt_stream = EncryptedWriter::new(w, encryptor);

                                Ok(encrypt_stream)
                            })
                    })
                    .boxed();

                Ok((read_fut, write_fut))
            })
            .boxed()
    }

    fn resolve_address(addr: Address, cpu_pool: CpuPool) -> BoxIoFuture<SocketAddr> {
        match addr {
            Address::SocketAddress(addr) => futures::finished(addr).boxed(),
            Address::DomainNameAddress(dname, port) => {
                cpu_pool.spawn(futures::lazy(move || {
                        let dname = format!("{}:{}", dname, port);
                        let mut addrs = try!(dname.to_socket_addrs());
                        addrs.next().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to resolve domain"))
                    }))
                    .boxed()
            }
        }
    }

    fn resolve_remote(cpu_pool: CpuPool,
                      addr: Address,
                      forbidden_ip: Arc<HashSet<IpAddr>>)
                      -> Box<Future<Item = SocketAddr, Error = io::Error>> {
        TcpRelayServer::resolve_address(addr, cpu_pool)
            .and_then(move |addr| {
                trace!("Resolved address as {}", addr);
                let ipaddr = match addr.clone() {
                    SocketAddr::V4(v4) => IpAddr::V4(v4.ip().clone()),
                    SocketAddr::V6(v6) => IpAddr::V6(v6.ip().clone()),
                };

                if forbidden_ip.contains(&ipaddr) {
                    info!("{} has been forbidden", ipaddr);
                    let err = io::Error::new(io::ErrorKind::Other, "Forbidden IP");
                    Err(err)
                } else {
                    Ok(addr)
                }
            })
            .boxed()
    }

    fn connect_remote(cpu_pool: CpuPool,
                      handle: Handle,
                      addr: Address,
                      forbidden_ip: Arc<HashSet<IpAddr>>)
                      -> Box<Future<Item = TcpStream, Error = io::Error>> {
        trace!("Connecting to remote {}", addr);
        Box::new(TcpRelayServer::resolve_remote(cpu_pool, addr, forbidden_ip)
            .and_then(move |addr| TcpStream::connect(&addr, &handle)))
    }

    pub fn handle_client(handle: &Handle,
                         cpu_pool: CpuPool,
                         s: TcpStream,
                         svr_cfg: Arc<ServerConfig>,
                         forbidden_ip: Arc<HashSet<IpAddr>>)
                         -> io::Result<()> {
        let peer_addr = try!(s.peer_addr());
        trace!("Got connection from {}", peer_addr);

        let cloned_handle = handle.clone();

        let fut = TcpRelayServer::handshake(s, svr_cfg).and_then(move |(r_fut, w_fut)| {
            r_fut.and_then(move |(r, addr)| {
                info!("Connecting {}", addr);
                let cloned_addr = addr.clone();
                TcpRelayServer::connect_remote(cpu_pool, cloned_handle, addr, forbidden_ip).and_then(|svr_s| {
                    let (svr_r, svr_w) = svr_s.split();
                    let c2s = copy(r, svr_w);
                    let s2c = w_fut.and_then(|w| copy(svr_r, w));
                    c2s.join(s2c)
                        .then(move |_| {
                            trace!("Relay {} is finished", cloned_addr);
                            Ok(())
                        })
                })
            })
        });

        handle.spawn(fut.then(|res| {
            match res {
                Ok(..) => Ok(()),
                Err(err) => {
                    error!("Failed to handle client: {}", err);
                    Err(())
                }
            }
        }));

        Ok(())
    }

    /// Runs the server
    pub fn run(self, handle: Handle) -> Box<Future<Item = (), Error = io::Error>> {
        let mut fut: Option<Box<Future<Item = (), Error = io::Error>>> = None;

        for svr_cfg in &self.config.server {
            let listener = {
                let addr = &svr_cfg.addr;
                let listener = TcpListener::bind(addr, &handle).unwrap();
                trace!("ShadowSocks TCP Listening on {}", addr);
                listener
            };

            let svr_cfg = svr_cfg.clone();
            let handle = handle.clone();
            let forbidden_ip = self.config.forbidden_ip.clone();
            let cpu_pool = self.cpu_pool.clone();
            let listening = listener.incoming()
                .for_each(move |(socket, addr)| {
                    let server_cfg = svr_cfg.clone();
                    let forbidden_ip = forbidden_ip.clone();
                    let cpu_pool = cpu_pool.clone();

                    trace!("Got connection, addr: {}", addr);
                    trace!("Picked proxy server: {:?}", server_cfg);
                    TcpRelayServer::handle_client(&handle, cpu_pool, socket, server_cfg, forbidden_ip)
                })
                .map_err(|err| {
                    error!("Server run failed: {}", err);
                    err
                });

            fut = Some(match fut.take() {
                Some(fut) => Box::new(fut.join(listening).map(|_| ())) as Box<Future<Item = (), Error = io::Error>>,
                None => Box::new(listening) as Box<Future<Item = (), Error = io::Error>>,
            })
        }

        fut.expect("Must have at least one server")
    }
}
<|endoftext|>


<commit_before>use input::Input;
use pdcurses::chtype;
use pdcurses::mmask_t;

pub fn COLOR_PAIR(n: chtype) -> chtype {
    (n << PDC_COLOR_SHIFT) & A_COLOR
}

pub const COLOR_BLACK: i16 = 0;
pub const COLOR_BLUE: i16 = 1;
pub const COLOR_GREEN: i16 = 2;
pub const COLOR_RED: i16 = 4;
pub const COLOR_CYAN: i16 = (COLOR_BLUE | COLOR_GREEN);
pub const COLOR_MAGENTA: i16 = (COLOR_RED | COLOR_BLUE);
pub const COLOR_YELLOW: i16 = (COLOR_RED | COLOR_GREEN);
pub const COLOR_WHITE: i16 = 7;

pub const PDC_CHARTEXT_BITS: chtype = 21;
pub const PDC_COLOR_SHIFT: chtype = PDC_CHARTEXT_BITS + 12;

pub const A_ALTCHARSET : chtype = 0x001 << PDC_CHARTEXT_BITS;
pub const A_BOLD       : chtype = 0x080 << PDC_CHARTEXT_BITS;
pub const A_BLINK      : chtype = 0x040 << PDC_CHARTEXT_BITS;
pub const A_COLOR      : chtype = 0x7fffffff << PDC_COLOR_SHIFT;
pub const A_CHARTEXT   : chtype = (0x1 << PDC_CHARTEXT_BITS) - 1;
pub const A_DIM        : chtype = 0x400 << PDC_CHARTEXT_BITS;
pub const A_LEFTLINE   : chtype = 0x004 << PDC_CHARTEXT_BITS;
pub const A_INVIS      : chtype = 0x008 << PDC_CHARTEXT_BITS;
pub const A_ITALIC     : chtype = A_INVIS;
pub const A_NORMAL     : chtype = 0;
pub const A_OVERLINE   : chtype = 0x100 << PDC_CHARTEXT_BITS;
pub const A_REVERSE    : chtype = 0x020 << PDC_CHARTEXT_BITS;
pub const A_RIGHTLINE  : chtype = 0x002 << PDC_CHARTEXT_BITS;
pub const A_STRIKEOUT  : chtype = 0x200 << PDC_CHARTEXT_BITS;
pub const A_UNDERLINE  : chtype = 0x010 << PDC_CHARTEXT_BITS;

pub const KEY_OFFSET: i32 = 0xec00;
pub const KEY_F15: i32 = (KEY_OFFSET + 0x17);
pub const KEY_UNDO: i32 = (KEY_OFFSET + 0x96);
pub const KEY_RESIZE: i32 = (KEY_OFFSET + 0x122);
pub const KEY_MOUSE: i32 = (KEY_OFFSET + 0x11b);

pub const SPECIAL_KEY_CODES: [Input; 102] = [Input::KeyCodeYes,

                                             Input::KeyBreak,
                                             Input::KeyDown,
                                             Input::KeyUp,
                                             Input::KeyLeft,
                                             Input::KeyRight,
                                             Input::KeyHome,
                                             Input::KeyBackspace,

                                             Input::KeyF0,
                                             Input::KeyF1,
                                             Input::KeyF2,
                                             Input::KeyF3,
                                             Input::KeyF4,
                                             Input::KeyF5,
                                             Input::KeyF6,
                                             Input::KeyF7,
                                             Input::KeyF8,
                                             Input::KeyF9,
                                             Input::KeyF10,
                                             Input::KeyF11,
                                             Input::KeyF12,
                                             Input::KeyF13,
                                             Input::KeyF14,
                                             Input::KeyF15,
                                             // PDcurses reserves space for 64 function keys, but we've
                                             // only implemented 15. This has to be taken into account
                                             // when converting the integer into an index of this array
                                             Input::KeyDL,
                                             Input::KeyIL,
                                             Input::KeyDC,
                                             Input::KeyIC,
                                             Input::KeyEIC,
                                             Input::KeyClear,
                                             Input::KeyEOS,
                                             Input::KeyEOL,
                                             Input::KeySF,
                                             Input::KeySR,
                                             Input::KeyNPage,
                                             Input::KeyPPage,
                                             Input::KeySTab,
                                             Input::KeyCTab,
                                             Input::KeyCATab,
                                             Input::KeyEnter,
                                             Input::KeySReset,
                                             Input::KeyReset,
                                             Input::KeyPrint,
                                             Input::KeyLL,
                                             Input::KeyAbort,
                                             Input::KeySHelp,
                                             Input::KeyLHelp,
                                             Input::KeyBTab,
                                             Input::KeyBeg,
                                             Input::KeyCancel,
                                             Input::KeyClose,
                                             Input::KeyCommand,
                                             Input::KeyCopy,
                                             Input::KeyCreate,
                                             Input::KeyEnd,
                                             Input::KeyExit,
                                             Input::KeyFind,
                                             Input::KeyHelp,
                                             Input::KeyMark,
                                             Input::KeyMessage,
                                             Input::KeyMove,
                                             Input::KeyNext,
                                             Input::KeyOpen,
                                             Input::KeyOptions,
                                             Input::KeyPrevious,
                                             Input::KeyRedo,
                                             Input::KeyReference,
                                             Input::KeyRefresh,
                                             Input::KeyReplace,
                                             Input::KeyRestart,
                                             Input::KeyResume,
                                             Input::KeySave,
                                             Input::KeySBeg,
                                             Input::KeySCancel,
                                             Input::KeySCommand,
                                             Input::KeySCopy,
                                             Input::KeySCreate,
                                             Input::KeySDC,
                                             Input::KeySDL,
                                             Input::KeySelect,
                                             Input::KeySEnd,
                                             Input::KeySEOL,
                                             Input::KeySExit,
                                             Input::KeySFind,
                                             Input::KeySHome,
                                             Input::KeySIC,

                                             Input::KeySLeft,
                                             Input::KeySMessage,
                                             Input::KeySMove,
                                             Input::KeySNext,
                                             Input::KeySOptions,
                                             Input::KeySPrevious,
                                             Input::KeySPrint,
                                             Input::KeySRedo,
                                             Input::KeySReplace,
                                             Input::KeySRight,
                                             Input::KeySResume,
                                             Input::KeySSave,
                                             Input::KeySSuspend,
                                             Input::KeySUndo,
                                             Input::KeySuspend,
                                             Input::KeyUndo];

pub const ALL_MOUSE_EVENTS: mmask_t = 0x1fffffff;
<commit_msg>Expect PDCurses to use RGB colors<commit_after>use input::Input;
use pdcurses::chtype;
use pdcurses::mmask_t;

pub fn COLOR_PAIR(n: chtype) -> chtype {
    (n << PDC_COLOR_SHIFT) & A_COLOR
}

pub const COLOR_BLACK: i16 = 0;
pub const COLOR_RED: i16 = 1;
pub const COLOR_GREEN: i16 = 2;
pub const COLOR_YELLOW: i16 = 3;
pub const COLOR_BLUE: i16 = 4;
pub const COLOR_MAGENTA: i16 = 5;
pub const COLOR_CYAN: i16 = 6;
pub const COLOR_WHITE: i16 = 7;

pub const PDC_CHARTEXT_BITS: chtype = 21;
pub const PDC_COLOR_SHIFT: chtype = PDC_CHARTEXT_BITS + 12;

pub const A_ALTCHARSET : chtype = 0x001 << PDC_CHARTEXT_BITS;
pub const A_BOLD       : chtype = 0x080 << PDC_CHARTEXT_BITS;
pub const A_BLINK      : chtype = 0x040 << PDC_CHARTEXT_BITS;
pub const A_COLOR      : chtype = 0x7fffffff << PDC_COLOR_SHIFT;
pub const A_CHARTEXT   : chtype = (0x1 << PDC_CHARTEXT_BITS) - 1;
pub const A_DIM        : chtype = 0x400 << PDC_CHARTEXT_BITS;
pub const A_LEFTLINE   : chtype = 0x004 << PDC_CHARTEXT_BITS;
pub const A_INVIS      : chtype = 0x008 << PDC_CHARTEXT_BITS;
pub const A_ITALIC     : chtype = A_INVIS;
pub const A_NORMAL     : chtype = 0;
pub const A_OVERLINE   : chtype = 0x100 << PDC_CHARTEXT_BITS;
pub const A_REVERSE    : chtype = 0x020 << PDC_CHARTEXT_BITS;
pub const A_RIGHTLINE  : chtype = 0x002 << PDC_CHARTEXT_BITS;
pub const A_STRIKEOUT  : chtype = 0x200 << PDC_CHARTEXT_BITS;
pub const A_UNDERLINE  : chtype = 0x010 << PDC_CHARTEXT_BITS;

pub const KEY_OFFSET: i32 = 0xec00;
pub const KEY_F15: i32 = (KEY_OFFSET + 0x17);
pub const KEY_UNDO: i32 = (KEY_OFFSET + 0x96);
pub const KEY_RESIZE: i32 = (KEY_OFFSET + 0x122);
pub const KEY_MOUSE: i32 = (KEY_OFFSET + 0x11b);

pub const SPECIAL_KEY_CODES: [Input; 102] = [Input::KeyCodeYes,

                                             Input::KeyBreak,
                                             Input::KeyDown,
                                             Input::KeyUp,
                                             Input::KeyLeft,
                                             Input::KeyRight,
                                             Input::KeyHome,
                                             Input::KeyBackspace,

                                             Input::KeyF0,
                                             Input::KeyF1,
                                             Input::KeyF2,
                                             Input::KeyF3,
                                             Input::KeyF4,
                                             Input::KeyF5,
                                             Input::KeyF6,
                                             Input::KeyF7,
                                             Input::KeyF8,
                                             Input::KeyF9,
                                             Input::KeyF10,
                                             Input::KeyF11,
                                             Input::KeyF12,
                                             Input::KeyF13,
                                             Input::KeyF14,
                                             Input::KeyF15,
                                             // PDcurses reserves space for 64 function keys, but we've
                                             // only implemented 15. This has to be taken into account
                                             // when converting the integer into an index of this array
                                             Input::KeyDL,
                                             Input::KeyIL,
                                             Input::KeyDC,
                                             Input::KeyIC,
                                             Input::KeyEIC,
                                             Input::KeyClear,
                                             Input::KeyEOS,
                                             Input::KeyEOL,
                                             Input::KeySF,
                                             Input::KeySR,
                                             Input::KeyNPage,
                                             Input::KeyPPage,
                                             Input::KeySTab,
                                             Input::KeyCTab,
                                             Input::KeyCATab,
                                             Input::KeyEnter,
                                             Input::KeySReset,
                                             Input::KeyReset,
                                             Input::KeyPrint,
                                             Input::KeyLL,
                                             Input::KeyAbort,
                                             Input::KeySHelp,
                                             Input::KeyLHelp,
                                             Input::KeyBTab,
                                             Input::KeyBeg,
                                             Input::KeyCancel,
                                             Input::KeyClose,
                                             Input::KeyCommand,
                                             Input::KeyCopy,
                                             Input::KeyCreate,
                                             Input::KeyEnd,
                                             Input::KeyExit,
                                             Input::KeyFind,
                                             Input::KeyHelp,
                                             Input::KeyMark,
                                             Input::KeyMessage,
                                             Input::KeyMove,
                                             Input::KeyNext,
                                             Input::KeyOpen,
                                             Input::KeyOptions,
                                             Input::KeyPrevious,
                                             Input::KeyRedo,
                                             Input::KeyReference,
                                             Input::KeyRefresh,
                                             Input::KeyReplace,
                                             Input::KeyRestart,
                                             Input::KeyResume,
                                             Input::KeySave,
                                             Input::KeySBeg,
                                             Input::KeySCancel,
                                             Input::KeySCommand,
                                             Input::KeySCopy,
                                             Input::KeySCreate,
                                             Input::KeySDC,
                                             Input::KeySDL,
                                             Input::KeySelect,
                                             Input::KeySEnd,
                                             Input::KeySEOL,
                                             Input::KeySExit,
                                             Input::KeySFind,
                                             Input::KeySHome,
                                             Input::KeySIC,

                                             Input::KeySLeft,
                                             Input::KeySMessage,
                                             Input::KeySMove,
                                             Input::KeySNext,
                                             Input::KeySOptions,
                                             Input::KeySPrevious,
                                             Input::KeySPrint,
                                             Input::KeySRedo,
                                             Input::KeySReplace,
                                             Input::KeySRight,
                                             Input::KeySResume,
                                             Input::KeySSave,
                                             Input::KeySSuspend,
                                             Input::KeySUndo,
                                             Input::KeySuspend,
                                             Input::KeyUndo];

pub const ALL_MOUSE_EVENTS: mmask_t = 0x1fffffff;
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use std::path::PathBuf;

use super::common::ServerArgs;
use crate::{
    configuration::{
        NodeAddress, DEFAULT_API_PORT_STR, DEFAULT_METRICS_PORT_STR, DEFAULT_NOISE_PORT_STR,
    },
    metric_collector::ReqwestMetricCollector,
    server::api::PreconfiguredNode,
};
use anyhow::{Context, Result};
use clap::Parser;
use log::info;
use poem::{listener::TcpListener, Route, Server};
use url::Url;

use super::{
    api::{build_openapi_service, Api},
    configurations_manager::build_server_with_blocking_runner,
};

#[derive(Clone, Debug, Parser)]
pub struct Run {
    #[clap(flatten)]
    server_args: ServerArgs,

    /// File paths leading to baseline node configurations.
    #[structopt(long, parse(from_os_str), required = true, min_values = 1)]
    pub baseline_node_config_paths: Vec<PathBuf>,

    /// If this is given, the user will be able to call the check_preconfigured_node
    /// endpoint, which takes no target, instead using this as the target. If
    /// allow_preconfigured_test_node_only is set, only the check_preconfigured_node
    /// endpoint will work, the node will not respond to requests for other nodes.
    #[clap(long)]
    pub target_node_url: Option<Url>,

    /// The metrics port for the target node.
    #[clap(long, requires = "target-node-url", default_value = &DEFAULT_METRICS_PORT_STR)]
    pub target_metrics_port: u16,

    /// The API port for the target node.
    #[clap(long, requires = "target-node-url", default_value = &DEFAULT_API_PORT_STR)]
    pub target_api_port: u16,

    /// The port over which validator nodes can talk to the target node.
    #[clap(long, requires = "target-node-url", default_value = &DEFAULT_NOISE_PORT_STR)]
    pub target_noise_port: u16,

    /// If a test node is preconfigured, you can set this to prevent the server
    /// from responding to requests for any node but that one.
    #[clap(long)]
    pub allow_preconfigured_test_node_only: bool,
}

pub async fn run(args: Run) -> Result<()> {
    let configurations_manager =
        build_server_with_blocking_runner(&args.baseline_node_config_paths)
            .await
            .context("Failed to build baseline node configurations")?;

    info!(
        "Running with the following configuration: {:#?}",
        configurations_manager.configurations
    );

    let preconfigured_test_node = match args.target_node_url {
        Some(ref url) => {
            let node_address = NodeAddress {
                url: url.clone(),
                api_port: args.target_api_port,
                metrics_port: args.target_metrics_port,
                noise_port: args.target_noise_port,
            };
            let metric_collector =
                ReqwestMetricCollector::new(node_address.url.clone(), node_address.metrics_port);
            Some(PreconfiguredNode {
                node_address,
                metric_collector,
            })
        }
        None => None,
    };

    let api = Api {
        configurations_manager,
        preconfigured_test_node,
        allow_preconfigured_test_node_only: args.allow_preconfigured_test_node_only,
    };

    let api_endpoint = format!("/{}", args.server_args.api_path);
    let api_service = build_openapi_service(api, args.server_args.clone());
    let ui = api_service.swagger_ui();
    let spec_json = api_service.spec_endpoint();
    let spec_yaml = api_service.spec_endpoint_yaml();

    Server::new(TcpListener::bind((
        args.server_args.listen_address,
        args.server_args.listen_port,
    )))
    .run(
        Route::new()
            .nest(api_endpoint, api_service)
            .nest("/spec", ui)
            .at("/spec.json", spec_json)
            .at("/spec.yaml", spec_yaml),
    )
    .await
    .map_err(anyhow::Error::msg)
}
<commit_msg>Configure CORS for NHC (#3696)<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use std::path::PathBuf;

use super::common::ServerArgs;
use crate::{
    configuration::{
        NodeAddress, DEFAULT_API_PORT_STR, DEFAULT_METRICS_PORT_STR, DEFAULT_NOISE_PORT_STR,
    },
    metric_collector::ReqwestMetricCollector,
    server::api::PreconfiguredNode,
};
use anyhow::{Context, Result};
use clap::Parser;
use log::info;
use poem::{http::Method, listener::TcpListener, middleware::Cors, EndpointExt, Route, Server};
use url::Url;

use super::{
    api::{build_openapi_service, Api},
    configurations_manager::build_server_with_blocking_runner,
};

#[derive(Clone, Debug, Parser)]
pub struct Run {
    #[clap(flatten)]
    server_args: ServerArgs,

    /// File paths leading to baseline node configurations.
    #[structopt(long, parse(from_os_str), required = true, min_values = 1)]
    pub baseline_node_config_paths: Vec<PathBuf>,

    /// If this is given, the user will be able to call the check_preconfigured_node
    /// endpoint, which takes no target, instead using this as the target. If
    /// allow_preconfigured_test_node_only is set, only the check_preconfigured_node
    /// endpoint will work, the node will not respond to requests for other nodes.
    #[clap(long)]
    pub target_node_url: Option<Url>,

    /// The metrics port for the target node.
    #[clap(long, requires = "target-node-url", default_value = &DEFAULT_METRICS_PORT_STR)]
    pub target_metrics_port: u16,

    /// The API port for the target node.
    #[clap(long, requires = "target-node-url", default_value = &DEFAULT_API_PORT_STR)]
    pub target_api_port: u16,

    /// The port over which validator nodes can talk to the target node.
    #[clap(long, requires = "target-node-url", default_value = &DEFAULT_NOISE_PORT_STR)]
    pub target_noise_port: u16,

    /// If a test node is preconfigured, you can set this to prevent the server
    /// from responding to requests for any node but that one.
    #[clap(long)]
    pub allow_preconfigured_test_node_only: bool,
}

pub async fn run(args: Run) -> Result<()> {
    let configurations_manager =
        build_server_with_blocking_runner(&args.baseline_node_config_paths)
            .await
            .context("Failed to build baseline node configurations")?;

    info!(
        "Running with the following configuration: {:#?}",
        configurations_manager.configurations
    );

    let preconfigured_test_node = match args.target_node_url {
        Some(ref url) => {
            let node_address = NodeAddress {
                url: url.clone(),
                api_port: args.target_api_port,
                metrics_port: args.target_metrics_port,
                noise_port: args.target_noise_port,
            };
            let metric_collector =
                ReqwestMetricCollector::new(node_address.url.clone(), node_address.metrics_port);
            Some(PreconfiguredNode {
                node_address,
                metric_collector,
            })
        }
        None => None,
    };

    let api = Api {
        configurations_manager,
        preconfigured_test_node,
        allow_preconfigured_test_node_only: args.allow_preconfigured_test_node_only,
    };

    let api_endpoint = format!("/{}", args.server_args.api_path);
    let api_service = build_openapi_service(api, args.server_args.clone());
    let ui = api_service.swagger_ui();
    let spec_json = api_service.spec_endpoint();
    let spec_yaml = api_service.spec_endpoint_yaml();

    let cors = Cors::new().allow_methods(vec![Method::GET]);

    Server::new(TcpListener::bind((
        args.server_args.listen_address,
        args.server_args.listen_port,
    )))
    .run(
        Route::new()
            .nest(api_endpoint, api_service)
            .nest("/spec", ui)
            .at("/spec.json", spec_json)
            .at("/spec.yaml", spec_yaml)
            .with(cors),
    )
    .await
    .map_err(anyhow::Error::msg)
}
<|endoftext|>


<commit_before>// compile-flags: -O
// min-llvm-version: 11.0

#![crate_type = "lib"]

// CHECK-LABEL: @trim_in_place
#[no_mangle]
pub fn trim_in_place(a: &mut &[u8]) {
    while a.first() == Some(&42) {
        // CHECK-NOT: slice_index_order_fail
        *a = &a[1..];
    }
}

// CHECK-LABEL: @trim_in_place2
#[no_mangle]
pub fn trim_in_place2(a: &mut &[u8]) {
    while let Some(&42) = a.first() {
        // CHECK-NOT: slice_index_order_fail
        *a = &a[1..];
    }
}
<commit_msg>Make sure the functions don't get merged<commit_after>// compile-flags: -O
// min-llvm-version: 11.0

#![crate_type = "lib"]

// CHECK-LABEL: @trim_in_place
#[no_mangle]
pub fn trim_in_place(a: &mut &[u8]) {
    while a.first() == Some(&42) {
        // CHECK-NOT: slice_index_order_fail
        *a = &a[1..];
    }
}

// CHECK-LABEL: @trim_in_place2
#[no_mangle]
pub fn trim_in_place2(a: &mut &[u8]) {
    while let Some(&42) = a.first() {
        // CHECK-NOT: slice_index_order_fail
        *a = &a[2..];
    }
}
<|endoftext|>