<commit_before>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of `Rand` for the built-in types.

use core::{char, mem};

use {Rand, Rng, SeedableRng};

impl Rand for isize {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> isize {
        if mem::size_of::<isize>() == 4 {
            rng.gen::<i32>() as isize
        } else {
            rng.gen::<i64>() as isize
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

#[cfg(feature = "i128_support")]
impl Rand for i128 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i128 {
        rng.gen::<u128>() as i128
    }
}

impl Rand for usize {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> usize {
        if mem::size_of::<usize>() == 4 {
            rng.gen::<u32>() as usize
        } else {
            rng.gen::<u64>() as usize
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

#[cfg(feature = "i128_support")]
impl Rand for u128 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u128 {
        ((rng.next_u64() as u128) << 64) | (rng.next_u64() as u128)
    }
}

macro_rules! float_impls {
    ($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => {
        mod $mod_name {
            use {Rand, Rng, Open01, Closed01};

            // 1.0 / epsilon
            const SCALE: $ty = (1u64 << $mantissa_bits) as $ty;

            impl Rand for $ty {
                /// Generate a floating point number in the half-open
                /// interval `[0,1)`.
                ///
                /// See `Closed01` for the closed interval `[0,1]`,
                /// and `Open01` for the open interval `(0,1)`.
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> $ty {
                    rng.$method_name()
                }
            }
            impl Rand for Open01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
                    // add a small amount (specifically 2 bits below
                    // the precision of f64/f32 at 1.0), so that small
                    // numbers are larger than 0, but large numbers
                    // aren't pushed to/above 1.
                    Open01(rng.$method_name() + 0.25 / SCALE)
                }
            }
            impl Rand for Closed01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
                    // rescale so that 1.0 - epsilon becomes 1.0
                    // precisely.
                    Closed01(rng.$method_name() * SCALE / (SCALE - 1.0))
                }
            }
        }
    }
}
float_impls! { f64_rand_impls, f64, 52, next_f64 }
float_impls! { f32_rand_impls, f32, 23, next_f32 }

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        const CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L}

macro_rules! array_impl {
    {$n:expr, $t:ident, $($ts:ident,)*} => {
        array_impl!{($n - 1), $($ts,)*}

        impl<T> Rand for [T; $n] where T: Rand {
            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> [T; $n] {
                [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
            }
        }
    };
    {$n:expr,} => {
        impl<T> Rand for [T; $n] {
            fn rand<R: Rng>(_rng: &mut R) -> [T; $n] { [] }
        }
    };
}

array_impl!{32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: SeedableRng> Rand for T {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Self::from_rng(rng).unwrap()
    }
}

#[cfg(test)]
mod tests {
    use impls;
    use {Rng, Open01, Closed01};

    const EPSILON32: f32 = ::core::f32::EPSILON;
    const EPSILON64: f64 = ::core::f64::EPSILON;

    struct ConstantRng(u64);
    impl Rng for ConstantRng {
        fn next_u32(&mut self) -> u32 {
            let ConstantRng(v) = *self;
            v as u32
        }
        fn next_u64(&mut self) -> u64 {
            let ConstantRng(v) = *self;
            v
        }

        fn fill_bytes(&mut self, dest: &mut [u8]) {
            impls::fill_bytes_via_u64(self, dest)
        }
    }

    #[test]
    fn floating_point_edge_cases() {
        let mut zeros = ConstantRng(0);
        assert_eq!(zeros.gen::<f32>(), 0.0);
        assert_eq!(zeros.gen::<f64>(), 0.0);

        let mut one = ConstantRng(1);
        assert_eq!(one.gen::<f32>(), EPSILON32);
        assert_eq!(one.gen::<f64>(), EPSILON64);

        let mut max = ConstantRng(!0);
        assert_eq!(max.gen::<f32>(), 1.0 - EPSILON32);
        assert_eq!(max.gen::<f64>(), 1.0 - EPSILON64);
    }

    #[test]
    fn fp_closed_edge_cases() {
        let mut zeros = ConstantRng(0);
        let Closed01(zero32) = zeros.gen::<Closed01<f32>>();
        let Closed01(zero64) = zeros.gen::<Closed01<f64>>();
        assert_eq!(zero32, 0.0);
        assert_eq!(zero64, 0.0);

        let mut one = ConstantRng(1);
        let Closed01(one32) = one.gen::<Closed01<f32>>();
        let Closed01(one64) = one.gen::<Closed01<f64>>();
        assert!(EPSILON32 < one32 && one32 < EPSILON32 * 1.01);
        assert!(EPSILON64 < one64 && one64 < EPSILON64 * 1.01);

        let mut max = ConstantRng(!0);
        let Closed01(max32) = max.gen::<Closed01<f32>>();
        let Closed01(max64) = max.gen::<Closed01<f64>>();
        assert_eq!(max32, 1.0);
        assert_eq!(max64, 1.0);
    }

    #[test]
    fn fp_open_edge_cases() {
        let mut zeros = ConstantRng(0);
        let Open01(zero32) = zeros.gen::<Open01<f32>>();
        let Open01(zero64) = zeros.gen::<Open01<f64>>();
        assert_eq!(zero32, 0.0 + EPSILON32 / 4.0);
        assert_eq!(zero64, 0.0 + EPSILON64 / 4.0);

        let mut one = ConstantRng(1);
        let Open01(one32) = one.gen::<Open01<f32>>();
        let Open01(one64) = one.gen::<Open01<f64>>();
        assert!(EPSILON32 < one32 && one32 < EPSILON32 * 1.5);
        assert!(EPSILON64 < one64 && one64 < EPSILON64 * 1.5);

        let mut max = ConstantRng(!0);
        let Open01(max32) = max.gen::<Open01<f32>>();
        let Open01(max64) = max.gen::<Open01<f64>>();
        assert_eq!(max32, 1.0 - EPSILON32);
        assert_eq!(max64, 1.0 - EPSILON64);
    }

    #[test]
    fn rand_open() {
        // this is unlikely to catch an incorrect implementation that
        // generates exactly 0 or 1, but it keeps it sane.
        let mut rng = ::test::rng(501);
        for _ in 0..1_000 {
            // strict inequalities
            let Open01(f) = rng.gen::<Open01<f64>>();
            assert!(0.0 < f && f < 1.0);

            let Open01(f) = rng.gen::<Open01<f32>>();
            assert!(0.0 < f && f < 1.0);
        }
    }

    #[test]
    fn rand_closed() {
        let mut rng = ::test::rng(502);
        for _ in 0..1_000 {
            // strict inequalities
            let Closed01(f) = rng.gen::<Closed01<f64>>();
            assert!(0.0 <= f && f <= 1.0);

            let Closed01(f) = rng.gen::<Closed01<f32>>();
            assert!(0.0 <= f && f <= 1.0);
        }
    }
}
<commit_msg>remove bias in Open01<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of `Rand` for the built-in types.

use core::{char, mem};

use {Rand, Rng, SeedableRng};

impl Rand for isize {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> isize {
        if mem::size_of::<isize>() == 4 {
            rng.gen::<i32>() as isize
        } else {
            rng.gen::<i64>() as isize
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

#[cfg(feature = "i128_support")]
impl Rand for i128 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i128 {
        rng.gen::<u128>() as i128
    }
}

impl Rand for usize {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> usize {
        if mem::size_of::<usize>() == 4 {
            rng.gen::<u32>() as usize
        } else {
            rng.gen::<u64>() as usize
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

#[cfg(feature = "i128_support")]
impl Rand for u128 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u128 {
        ((rng.next_u64() as u128) << 64) | (rng.next_u64() as u128)
    }
}

macro_rules! float_impls {
    ($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => {
        mod $mod_name {
            use {Rand, Rng, Open01, Closed01};

            // 1.0 / epsilon
            const SCALE: $ty = (1u64 << $mantissa_bits) as $ty;

            impl Rand for $ty {
                /// Generate a floating point number in the half-open
                /// interval `[0,1)`.
                ///
                /// See `Closed01` for the closed interval `[0,1]`,
                /// and `Open01` for the open interval `(0,1)`.
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> $ty {
                    rng.$method_name()
                }
            }
            impl Rand for Open01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
                    // add 0.5 * epsilon, so that smallest number is
                    // greater than 0, and largest number is still
                    // less than 1, specifically 1 - 0.5 * epsilon.
                    Open01(rng.$method_name() + 0.5 / SCALE)
                }
            }
            impl Rand for Closed01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
                    // rescale so that 1.0 - epsilon becomes 1.0
                    // precisely.
                    Closed01(rng.$method_name() * SCALE / (SCALE - 1.0))
                }
            }
        }
    }
}
float_impls! { f64_rand_impls, f64, 52, next_f64 }
float_impls! { f32_rand_impls, f32, 23, next_f32 }

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        const CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L}

macro_rules! array_impl {
    {$n:expr, $t:ident, $($ts:ident,)*} => {
        array_impl!{($n - 1), $($ts,)*}

        impl<T> Rand for [T; $n] where T: Rand {
            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> [T; $n] {
                [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
            }
        }
    };
    {$n:expr,} => {
        impl<T> Rand for [T; $n] {
            fn rand<R: Rng>(_rng: &mut R) -> [T; $n] { [] }
        }
    };
}

array_impl!{32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: SeedableRng> Rand for T {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Self::from_rng(rng).unwrap()
    }
}

#[cfg(test)]
mod tests {
    use impls;
    use {Rng, Open01, Closed01};

    const EPSILON32: f32 = ::core::f32::EPSILON;
    const EPSILON64: f64 = ::core::f64::EPSILON;

    struct ConstantRng(u64);
    impl Rng for ConstantRng {
        fn next_u32(&mut self) -> u32 {
            let ConstantRng(v) = *self;
            v as u32
        }
        fn next_u64(&mut self) -> u64 {
            let ConstantRng(v) = *self;
            v
        }

        fn fill_bytes(&mut self, dest: &mut [u8]) {
            impls::fill_bytes_via_u64(self, dest)
        }
    }

    #[test]
    fn floating_point_edge_cases() {
        let mut zeros = ConstantRng(0);
        assert_eq!(zeros.gen::<f32>(), 0.0);
        assert_eq!(zeros.gen::<f64>(), 0.0);

        let mut one = ConstantRng(1);
        assert_eq!(one.gen::<f32>(), EPSILON32);
        assert_eq!(one.gen::<f64>(), EPSILON64);

        let mut max = ConstantRng(!0);
        assert_eq!(max.gen::<f32>(), 1.0 - EPSILON32);
        assert_eq!(max.gen::<f64>(), 1.0 - EPSILON64);
    }

    #[test]
    fn fp_closed_edge_cases() {
        let mut zeros = ConstantRng(0);
        let Closed01(zero32) = zeros.gen::<Closed01<f32>>();
        let Closed01(zero64) = zeros.gen::<Closed01<f64>>();
        assert_eq!(zero32, 0.0);
        assert_eq!(zero64, 0.0);

        let mut one = ConstantRng(1);
        let Closed01(one32) = one.gen::<Closed01<f32>>();
        let Closed01(one64) = one.gen::<Closed01<f64>>();
        assert!(EPSILON32 < one32 && one32 < EPSILON32 * 1.01);
        assert!(EPSILON64 < one64 && one64 < EPSILON64 * 1.01);

        let mut max = ConstantRng(!0);
        let Closed01(max32) = max.gen::<Closed01<f32>>();
        let Closed01(max64) = max.gen::<Closed01<f64>>();
        assert_eq!(max32, 1.0);
        assert_eq!(max64, 1.0);
    }

    #[test]
    fn fp_open_edge_cases() {
        let mut zeros = ConstantRng(0);
        let Open01(zero32) = zeros.gen::<Open01<f32>>();
        let Open01(zero64) = zeros.gen::<Open01<f64>>();
        assert_eq!(zero32, 0.0 + EPSILON32 / 2.0);
        assert_eq!(zero64, 0.0 + EPSILON64 / 2.0);

        let mut one = ConstantRng(1);
        let Open01(one32) = one.gen::<Open01<f32>>();
        let Open01(one64) = one.gen::<Open01<f64>>();
        assert!(EPSILON32 < one32 && one32 < EPSILON32 * 2.0);
        assert!(EPSILON64 < one64 && one64 < EPSILON64 * 2.0);

        let mut max = ConstantRng(!0);
        let Open01(max32) = max.gen::<Open01<f32>>();
        let Open01(max64) = max.gen::<Open01<f64>>();
        assert_eq!(max32, 1.0 - EPSILON32 / 2.0);
        assert_eq!(max64, 1.0 - EPSILON64 / 2.0);
    }

    #[test]
    fn rand_open() {
        // this is unlikely to catch an incorrect implementation that
        // generates exactly 0 or 1, but it keeps it sane.
        let mut rng = ::test::rng(501);
        for _ in 0..1_000 {
            // strict inequalities
            let Open01(f) = rng.gen::<Open01<f64>>();
            assert!(0.0 < f && f < 1.0);

            let Open01(f) = rng.gen::<Open01<f32>>();
            assert!(0.0 < f && f < 1.0);
        }
    }

    #[test]
    fn rand_closed() {
        let mut rng = ::test::rng(502);
        for _ in 0..1_000 {
            // strict inequalities
            let Closed01(f) = rng.gen::<Closed01<f64>>();
            assert!(0.0 <= f && f <= 1.0);

            let Closed01(f) = rng.gen::<Closed01<f32>>();
            assert!(0.0 <= f && f <= 1.0);
        }
    }
}
<|endoftext|>


<commit_before>use crate::sys;
use libc::c_void;
use std::marker::PhantomData;
use std::mem;

use crate::TimerSubsystem;

impl TimerSubsystem {
    /// Constructs a new timer using the boxed closure `callback`.
    ///
    /// The timer is started immediately, it will be cancelled either:
    ///
    /// * when the timer is dropped
    /// * or when the callback returns a non-positive continuation interval
    #[must_use = "if unused the Timer will be dropped immediately"]
    #[doc(alias = "SDL_AddTimer")]
    pub fn add_timer<'b, 'c>(&'b self, delay: u32, callback: TimerCallback<'c>) -> Timer<'b, 'c> {
        unsafe {
            let callback = Box::new(callback);
            let timer_id = sys::SDL_AddTimer(
                delay,
                Some(c_timer_callback),
                mem::transmute_copy(&callback),
            );

            Timer {
                callback: Some(callback),
                raw: timer_id,
                _marker: PhantomData,
            }
        }
    }

    /// Gets the number of milliseconds elapsed since the timer subsystem was initialized.
    ///
    /// It's recommended that you use another library for timekeeping, such as `time`.
    #[doc(alias = "SDL_GetTicks")]
    pub fn ticks(&self) -> u32 {
        // Google says this is probably not thread-safe (TODO: prove/disprove this).
        unsafe { sys::SDL_GetTicks() }
    }

    /// Sleeps the current thread for the specified amount of milliseconds.
    ///
    /// It's recommended that you use `std::thread::sleep()` instead.
    #[doc(alias = "SDL_Delay")]
    pub fn delay(&mut self, ms: u32) {
        // Google says this is probably not thread-safe (TODO: prove/disprove this).
        unsafe { sys::SDL_Delay(ms) }
    }

    #[doc(alias = "SDL_GetPerformanceCounter")]
    pub fn performance_counter(&self) -> u64 {
        unsafe { sys::SDL_GetPerformanceCounter() }
    }

    #[doc(alias = "SDL_GetPerformanceFrequency")]
    pub fn performance_frequency(&self) -> u64 {
        unsafe { sys::SDL_GetPerformanceFrequency() }
    }
}

pub type TimerCallback<'a> = Box<dyn FnMut() -> u32 + 'a + Sync>;

pub struct Timer<'b, 'a> {
    callback: Option<Box<TimerCallback<'a>>>,
    raw: sys::SDL_TimerID,
    _marker: PhantomData<&'b ()>,
}

impl<'b, 'a> Timer<'b, 'a> {
    /// Returns the closure as a trait-object and cancels the timer
    /// by consuming it...
    pub fn into_inner(mut self) -> TimerCallback<'a> {
        *self.callback.take().unwrap()
    }
}

impl<'b, 'a> Drop for Timer<'b, 'a> {
    #[inline]
    #[doc(alias = "SDL_RemoveTimer")]
    fn drop(&mut self) {
        // SDL_RemoveTimer returns SDL_FALSE if the timer wasn't found (impossible),
        // or the timer has been cancelled via the callback (possible).
        // The timer being cancelled isn't an issue, so we ignore the result.
        unsafe { sys::SDL_RemoveTimer(self.raw) };
    }
}

extern "C" fn c_timer_callback(_interval: u32, param: *mut c_void) -> u32 {
    let f = param as *mut std::boxed::Box<dyn std::ops::Fn() -> u32>;
    unsafe { (*f)() }
}

#[cfg(not(target_os = "macos"))]
#[cfg(test)]
mod test {
    use std::sync::{Arc, Mutex};
    use std::time::Duration;

    #[test]
    fn test_timer() {
        test_timer_runs_multiple_times();
        test_timer_runs_at_least_once();
        test_timer_can_be_recreated();
    }

    fn test_timer_runs_multiple_times() {
        let sdl_context = crate::sdl::init().unwrap();
        let timer_subsystem = sdl_context.timer().unwrap();

        let local_num = Arc::new(Mutex::new(0));
        let timer_num = local_num.clone();

        let _timer = timer_subsystem.add_timer(
            20,
            Box::new(|| {
                // increment up to 10 times (0 -> 9)
                // tick again in 100ms after each increment
                //
                let mut num = timer_num.lock().unwrap();
                if *num < 9 {
                    *num += 1;
                    20
                } else {
                    0
                }
            }),
        );

        // tick the timer at least 10 times w/ 200ms of "buffer"
        ::std::thread::sleep(Duration::from_millis(250));
        let num = local_num.lock().unwrap(); // read the number back
        assert_eq!(*num, 9); // it should have incremented at least 10 times...
    }

    fn test_timer_runs_at_least_once() {
        let sdl_context = crate::sdl::init().unwrap();
        let timer_subsystem = sdl_context.timer().unwrap();

        let local_flag = Arc::new(Mutex::new(false));
        let timer_flag = local_flag.clone();

        let _timer = timer_subsystem.add_timer(
            20,
            Box::new(|| {
                let mut flag = timer_flag.lock().unwrap();
                *flag = true;
                0
            }),
        );

        ::std::thread::sleep(Duration::from_millis(50));
        let flag = local_flag.lock().unwrap();
        assert_eq!(*flag, true);
    }

    fn test_timer_can_be_recreated() {
        let sdl_context = crate::sdl::init().unwrap();
        let timer_subsystem = sdl_context.timer().unwrap();

        let local_num = Arc::new(Mutex::new(0));
        let timer_num = local_num.clone();

        // run the timer once and reclaim its closure
        let timer_1 = timer_subsystem.add_timer(
            20,
            Box::new(move || {
                let mut num = timer_num.lock().unwrap();
                *num += 1; // increment the number
                0 // do not run timer again
            }),
        );

        // reclaim closure after timer runs
        ::std::thread::sleep(Duration::from_millis(50));
        let closure = timer_1.into_inner();

        // create a second timer and increment again
        let _timer_2 = timer_subsystem.add_timer(20, closure);
        ::std::thread::sleep(Duration::from_millis(50));

        // check that timer was incremented twice
        let num = local_num.lock().unwrap();
        assert_eq!(*num, 2);
    }
}
<commit_msg>Add additional contract for timer callbacks<commit_after>use crate::sys;
use libc::c_void;
use std::marker::PhantomData;
use std::mem;

use crate::TimerSubsystem;

impl TimerSubsystem {
    /// Constructs a new timer using the boxed closure `callback`.
    ///
    /// The timer is started immediately, it will be cancelled either:
    ///
    /// * when the timer is dropped
    /// * or when the callback returns a non-positive continuation interval
    #[must_use = "if unused the Timer will be dropped immediately"]
    #[doc(alias = "SDL_AddTimer")]
    pub fn add_timer<'b, 'c>(&'b self, delay: u32, callback: TimerCallback<'c>) -> Timer<'b, 'c> {
        unsafe {
            let callback = Box::new(callback);
            let timer_id = sys::SDL_AddTimer(
                delay,
                Some(c_timer_callback),
                mem::transmute_copy(&callback),
            );

            Timer {
                callback: Some(callback),
                raw: timer_id,
                _marker: PhantomData,
            }
        }
    }

    /// Gets the number of milliseconds elapsed since the timer subsystem was initialized.
    ///
    /// It's recommended that you use another library for timekeeping, such as `time`.
    #[doc(alias = "SDL_GetTicks")]
    pub fn ticks(&self) -> u32 {
        // Google says this is probably not thread-safe (TODO: prove/disprove this).
        unsafe { sys::SDL_GetTicks() }
    }

    /// Sleeps the current thread for the specified amount of milliseconds.
    ///
    /// It's recommended that you use `std::thread::sleep()` instead.
    #[doc(alias = "SDL_Delay")]
    pub fn delay(&mut self, ms: u32) {
        // Google says this is probably not thread-safe (TODO: prove/disprove this).
        unsafe { sys::SDL_Delay(ms) }
    }

    #[doc(alias = "SDL_GetPerformanceCounter")]
    pub fn performance_counter(&self) -> u64 {
        unsafe { sys::SDL_GetPerformanceCounter() }
    }

    #[doc(alias = "SDL_GetPerformanceFrequency")]
    pub fn performance_frequency(&self) -> u64 {
        unsafe { sys::SDL_GetPerformanceFrequency() }
    }
}

pub type TimerCallback<'a> = Box<dyn FnMut() -> u32 + 'a + Send>;

pub struct Timer<'b, 'a> {
    callback: Option<Box<TimerCallback<'a>>>,
    raw: sys::SDL_TimerID,
    _marker: PhantomData<&'b ()>,
}

impl<'b, 'a> Timer<'b, 'a> {
    /// Returns the closure as a trait-object and cancels the timer
    /// by consuming it...
    pub fn into_inner(mut self) -> TimerCallback<'a> {
        *self.callback.take().unwrap()
    }
}

impl<'b, 'a> Drop for Timer<'b, 'a> {
    #[inline]
    #[doc(alias = "SDL_RemoveTimer")]
    fn drop(&mut self) {
        // SDL_RemoveTimer returns SDL_FALSE if the timer wasn't found (impossible),
        // or the timer has been cancelled via the callback (possible).
        // The timer being cancelled isn't an issue, so we ignore the result.
        unsafe { sys::SDL_RemoveTimer(self.raw) };
    }
}

extern "C" fn c_timer_callback(_interval: u32, param: *mut c_void) -> u32 {
    let f = param as *mut std::boxed::Box<dyn std::ops::Fn() -> u32>;
    unsafe { (*f)() }
}

#[cfg(not(target_os = "macos"))]
#[cfg(test)]
mod test {
    use std::sync::{Arc, Mutex};
    use std::time::Duration;

    #[test]
    fn test_timer() {
        test_timer_runs_multiple_times();
        test_timer_runs_at_least_once();
        test_timer_can_be_recreated();
    }

    fn test_timer_runs_multiple_times() {
        let sdl_context = crate::sdl::init().unwrap();
        let timer_subsystem = sdl_context.timer().unwrap();

        let local_num = Arc::new(Mutex::new(0));
        let timer_num = local_num.clone();

        let _timer = timer_subsystem.add_timer(
            20,
            Box::new(|| {
                // increment up to 10 times (0 -> 9)
                // tick again in 100ms after each increment
                //
                let mut num = timer_num.lock().unwrap();
                if *num < 9 {
                    *num += 1;
                    20
                } else {
                    0
                }
            }),
        );

        // tick the timer at least 10 times w/ 200ms of "buffer"
        ::std::thread::sleep(Duration::from_millis(250));
        let num = local_num.lock().unwrap(); // read the number back
        assert_eq!(*num, 9); // it should have incremented at least 10 times...
    }

    fn test_timer_runs_at_least_once() {
        let sdl_context = crate::sdl::init().unwrap();
        let timer_subsystem = sdl_context.timer().unwrap();

        let local_flag = Arc::new(Mutex::new(false));
        let timer_flag = local_flag.clone();

        let _timer = timer_subsystem.add_timer(
            20,
            Box::new(|| {
                let mut flag = timer_flag.lock().unwrap();
                *flag = true;
                0
            }),
        );

        ::std::thread::sleep(Duration::from_millis(50));
        let flag = local_flag.lock().unwrap();
        assert_eq!(*flag, true);
    }

    fn test_timer_can_be_recreated() {
        let sdl_context = crate::sdl::init().unwrap();
        let timer_subsystem = sdl_context.timer().unwrap();

        let local_num = Arc::new(Mutex::new(0));
        let timer_num = local_num.clone();

        // run the timer once and reclaim its closure
        let timer_1 = timer_subsystem.add_timer(
            20,
            Box::new(move || {
                let mut num = timer_num.lock().unwrap();
                *num += 1; // increment the number
                0 // do not run timer again
            }),
        );

        // reclaim closure after timer runs
        ::std::thread::sleep(Duration::from_millis(50));
        let closure = timer_1.into_inner();

        // create a second timer and increment again
        let _timer_2 = timer_subsystem.add_timer(20, closure);
        ::std::thread::sleep(Duration::from_millis(50));

        // check that timer was incremented twice
        let num = local_num.lock().unwrap();
        assert_eq!(*num, 2);
    }
}
<|endoftext|>


<commit_before>use libc::{uint32_t, c_void};
use std::marker::PhantomData;
use std::mem;
use sys::timer as ll;

use TimerSubsystem;

impl TimerSubsystem {
    /// Constructs a new timer using the boxed closure `callback`.
    ///
    /// The timer is started immediately, it will be cancelled either:
    ///
    /// * when the timer is dropped
    /// * or when the callback returns a non-positive continuation interval
    pub fn add_timer<'b, 'c>(&'b self, delay: u32, callback: TimerCallback<'c>) -> Timer<'b, 'c> {
        unsafe {
            let callback = Box::new(callback);
            let timer_id = ll::SDL_AddTimer(delay,
                                            Some(c_timer_callback),
                                            mem::transmute_copy(&callback));

            Timer {
                callback: Some(callback),
                raw: timer_id,
                _marker: PhantomData
            }
        }
    }

    /// Gets the number of milliseconds elapsed since the timer subsystem was initialized.
    ///
    /// It's recommended that you use another library for timekeeping, such as `time`.
    pub fn ticks(&mut self) -> u32 {
        // Google says this is probably not thread-safe (TODO: prove/disprove this).
        unsafe { ll::SDL_GetTicks() }
    }

    /// Sleeps the current thread for the specified amount of milliseconds.
    ///
    /// It's recommended that you use `std::thread::sleep_ms()` instead.
    pub fn delay(&mut self, ms: u32) {
        // Google says this is probably not thread-safe (TODO: prove/disprove this).
        unsafe { ll::SDL_Delay(ms) }
    }

    pub fn performance_counter(&self) -> u64 {
        unsafe { ll::SDL_GetPerformanceCounter() }
    }

    pub fn performance_frequency(&self) -> u64 {
        unsafe { ll::SDL_GetPerformanceFrequency() }
    }
}

pub type TimerCallback<'a> = Box<FnMut() -> u32+'a+Sync>;

pub struct Timer<'b, 'a> {
    callback: Option<Box<TimerCallback<'a>>>,
    raw: ll::SDL_TimerID,
    _marker: PhantomData<&'b ()>
}

impl<'b, 'a> Timer<'b, 'a> {
    /// Returns the closure as a trait-object and cancels the timer
    /// by consuming it...
    pub fn into_inner(mut self) -> TimerCallback<'a> {
        *self.callback.take().unwrap()
    }
}

impl<'b, 'a> Drop for Timer<'b, 'a> {
    #[inline]
    fn drop(&mut self) {
        // SDL_RemoveTimer returns SDL_FALSE if the timer wasn't found (impossible),
        // or the timer has been cancelled via the callback (possible).
        // The timer being cancelled isn't an issue, so we ignore the result.
        unsafe { ll::SDL_RemoveTimer(self.raw) };
    }
}

extern "C" fn c_timer_callback(_interval: u32, param: *mut c_void) -> uint32_t {
    unsafe {
        let f: *mut Box<Fn() -> u32> = mem::transmute(param);
        (*f)() as uint32_t
    }
}

#[cfg(test)]
fn test_timer_runs_multiple_times() {
    use std::sync::{Arc, Mutex};
    use std::time::Duration;

    let sdl_context = ::sdl::init().unwrap();
    let timer_subsystem = sdl_context.timer().unwrap();

    let local_num = Arc::new(Mutex::new(0));
    let timer_num = local_num.clone();

    let _timer = timer_subsystem.add_timer(20, Box::new(|| {
        // increment up to 10 times (0 -> 9)
        // tick again in 100ms after each increment
        //
        let mut num = timer_num.lock().unwrap();
        if *num < 9 {
            *num += 1;
            20
        } else { 0 }
    }));

    ::std::thread::sleep(Duration::from_millis(250));              // tick the timer at least 10 times w/ 200ms of "buffer"
    let num = local_num.lock().unwrap(); // read the number back
    assert_eq!(*num, 9);                 // it should have incremented at least 10 times...
}

#[cfg(test)]
fn test_timer_runs_at_least_once() {
    use std::sync::{Arc, Mutex};
    use std::time::Duration;

    let sdl_context = ::sdl::init().unwrap();
    let timer_subsystem = sdl_context.timer().unwrap();

    let local_flag = Arc::new(Mutex::new(false));
    let timer_flag = local_flag.clone();

    let _timer = timer_subsystem.add_timer(20, Box::new(|| {
        let mut flag = timer_flag.lock().unwrap();
        *flag = true; 0
    }));

    ::std::thread::sleep(Duration::from_millis(50));
    let flag = local_flag.lock().unwrap();
    assert_eq!(*flag, true);
}

#[cfg(test)]
fn test_timer_can_be_recreated() {
    use std::time::Duration;
    use std::sync::{Arc, Mutex};

    let sdl_context = ::sdl::init().unwrap();
    let timer_subsystem = sdl_context.timer().unwrap();

    let local_num = Arc::new(Mutex::new(0));
    let timer_num = local_num.clone();

    // run the timer once and reclaim its closure
    let timer_1 = timer_subsystem.add_timer(20, Box::new(move|| {
        let mut num = timer_num.lock().unwrap();
        *num += 1; // increment the number
        0          // do not run timer again
    }));

    // reclaim closure after timer runs
    ::std::thread::sleep(Duration::from_millis(50));
    let closure = timer_1.into_inner();

    // create a second timer and increment again
    let _timer_2 = timer_subsystem.add_timer(20, closure);
    ::std::thread::sleep(Duration::from_millis(50));

    // check that timer was incremented twice
    let num = local_num.lock().unwrap();
    assert_eq!(*num, 2);
}

#[test]
fn test_timer() {
    test_timer_runs_multiple_times();
    test_timer_runs_at_least_once();
    test_timer_can_be_recreated();
}
<commit_msg>doc: thread::sleep_ms -> sleep<commit_after>use libc::{uint32_t, c_void};
use std::marker::PhantomData;
use std::mem;
use sys::timer as ll;

use TimerSubsystem;

impl TimerSubsystem {
    /// Constructs a new timer using the boxed closure `callback`.
    ///
    /// The timer is started immediately, it will be cancelled either:
    ///
    /// * when the timer is dropped
    /// * or when the callback returns a non-positive continuation interval
    pub fn add_timer<'b, 'c>(&'b self, delay: u32, callback: TimerCallback<'c>) -> Timer<'b, 'c> {
        unsafe {
            let callback = Box::new(callback);
            let timer_id = ll::SDL_AddTimer(delay,
                                            Some(c_timer_callback),
                                            mem::transmute_copy(&callback));

            Timer {
                callback: Some(callback),
                raw: timer_id,
                _marker: PhantomData
            }
        }
    }

    /// Gets the number of milliseconds elapsed since the timer subsystem was initialized.
    ///
    /// It's recommended that you use another library for timekeeping, such as `time`.
    pub fn ticks(&mut self) -> u32 {
        // Google says this is probably not thread-safe (TODO: prove/disprove this).
        unsafe { ll::SDL_GetTicks() }
    }

    /// Sleeps the current thread for the specified amount of milliseconds.
    ///
    /// It's recommended that you use `std::thread::sleep()` instead.
    pub fn delay(&mut self, ms: u32) {
        // Google says this is probably not thread-safe (TODO: prove/disprove this).
        unsafe { ll::SDL_Delay(ms) }
    }

    pub fn performance_counter(&self) -> u64 {
        unsafe { ll::SDL_GetPerformanceCounter() }
    }

    pub fn performance_frequency(&self) -> u64 {
        unsafe { ll::SDL_GetPerformanceFrequency() }
    }
}

pub type TimerCallback<'a> = Box<FnMut() -> u32+'a+Sync>;

pub struct Timer<'b, 'a> {
    callback: Option<Box<TimerCallback<'a>>>,
    raw: ll::SDL_TimerID,
    _marker: PhantomData<&'b ()>
}

impl<'b, 'a> Timer<'b, 'a> {
    /// Returns the closure as a trait-object and cancels the timer
    /// by consuming it...
    pub fn into_inner(mut self) -> TimerCallback<'a> {
        *self.callback.take().unwrap()
    }
}

impl<'b, 'a> Drop for Timer<'b, 'a> {
    #[inline]
    fn drop(&mut self) {
        // SDL_RemoveTimer returns SDL_FALSE if the timer wasn't found (impossible),
        // or the timer has been cancelled via the callback (possible).
        // The timer being cancelled isn't an issue, so we ignore the result.
        unsafe { ll::SDL_RemoveTimer(self.raw) };
    }
}

extern "C" fn c_timer_callback(_interval: u32, param: *mut c_void) -> uint32_t {
    unsafe {
        let f: *mut Box<Fn() -> u32> = mem::transmute(param);
        (*f)() as uint32_t
    }
}

#[cfg(test)]
fn test_timer_runs_multiple_times() {
    use std::sync::{Arc, Mutex};
    use std::time::Duration;

    let sdl_context = ::sdl::init().unwrap();
    let timer_subsystem = sdl_context.timer().unwrap();

    let local_num = Arc::new(Mutex::new(0));
    let timer_num = local_num.clone();

    let _timer = timer_subsystem.add_timer(20, Box::new(|| {
        // increment up to 10 times (0 -> 9)
        // tick again in 100ms after each increment
        //
        let mut num = timer_num.lock().unwrap();
        if *num < 9 {
            *num += 1;
            20
        } else { 0 }
    }));

    ::std::thread::sleep(Duration::from_millis(250));              // tick the timer at least 10 times w/ 200ms of "buffer"
    let num = local_num.lock().unwrap(); // read the number back
    assert_eq!(*num, 9);                 // it should have incremented at least 10 times...
}

#[cfg(test)]
fn test_timer_runs_at_least_once() {
    use std::sync::{Arc, Mutex};
    use std::time::Duration;

    let sdl_context = ::sdl::init().unwrap();
    let timer_subsystem = sdl_context.timer().unwrap();

    let local_flag = Arc::new(Mutex::new(false));
    let timer_flag = local_flag.clone();

    let _timer = timer_subsystem.add_timer(20, Box::new(|| {
        let mut flag = timer_flag.lock().unwrap();
        *flag = true; 0
    }));

    ::std::thread::sleep(Duration::from_millis(50));
    let flag = local_flag.lock().unwrap();
    assert_eq!(*flag, true);
}

#[cfg(test)]
fn test_timer_can_be_recreated() {
    use std::time::Duration;
    use std::sync::{Arc, Mutex};

    let sdl_context = ::sdl::init().unwrap();
    let timer_subsystem = sdl_context.timer().unwrap();

    let local_num = Arc::new(Mutex::new(0));
    let timer_num = local_num.clone();

    // run the timer once and reclaim its closure
    let timer_1 = timer_subsystem.add_timer(20, Box::new(move|| {
        let mut num = timer_num.lock().unwrap();
        *num += 1; // increment the number
        0          // do not run timer again
    }));

    // reclaim closure after timer runs
    ::std::thread::sleep(Duration::from_millis(50));
    let closure = timer_1.into_inner();

    // create a second timer and increment again
    let _timer_2 = timer_subsystem.add_timer(20, closure);
    ::std::thread::sleep(Duration::from_millis(50));

    // check that timer was incremented twice
    let num = local_num.lock().unwrap();
    assert_eq!(*num, 2);
}

#[test]
fn test_timer() {
    test_timer_runs_multiple_times();
    test_timer_runs_at_least_once();
    test_timer_can_be_recreated();
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::fmt;
use std::mem;
use std::cmp;
use std::num::{Float, Int};

use text_writer::{mod, TextWriter};

use super::{Token, NumericValue, PercentageValue};

pub trait ToCss for Sized? {
    /// Serialize `self` in CSS syntax, writing to `dest`.
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter;

    /// Serialize `self` in CSS syntax and return a string.
    ///
    /// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
    #[inline]
    fn to_css_string(&self) -> String {
        let mut s = String::new();
        self.to_css(&mut s).unwrap();
        s
    }

    /// Serialize `self` in CSS syntax and return a result compatible with `std::fmt::Show`.
    ///
    /// Typical usage is, for a `Foo` that implements `ToCss`:
    ///
    /// ```{rust,ignore}
    /// use std::fmt;
    /// impl fmt::Show for Foo {
    ///     #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
    /// }
    /// ```
    ///
    /// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
    #[inline]
    fn fmt_to_css<W>(&self, dest: &mut W) -> fmt::Result where W: TextWriter {
        self.to_css(dest).map_err(|_| fmt::Error)
    }
}

#[inline]
fn write_numeric<W>(value: NumericValue, dest: &mut W) -> text_writer::Result
where W: TextWriter {
    // `value.value >= 0` is true for negative 0.
    if value.signed && value.value.is_positive() {
        try!(dest.write_str("+"));
    }

    if value.value == 0.0 && value.value.is_negative() {
        // Negative zero. Work around #20596.
        try!(dest.write_str("-0"))
    } else {
        try!(write!(dest, "{}", value.value))
    }

    if value.int_value.is_none() && value.value.fract() == 0. {
        try!(dest.write_str(".0"));
    }
    Ok(())
}

impl<'a> ToCss for Token<'a> {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        match *self {
            Token::Ident(ref value) => try!(serialize_identifier(value.as_slice(), dest)),
            Token::AtKeyword(ref value) => {
                try!(dest.write_char('@'));
                try!(serialize_identifier(value.as_slice(), dest));
            },
            Token::Hash(ref value) => {
                try!(dest.write_char('#'));
                for c in value.as_slice().chars() {
                    try!(serialize_char(c, dest, /* is_identifier_start = */ false));
                }
            },
            Token::IDHash(ref value) => {
                try!(dest.write_char('#'));
                try!(serialize_identifier(value.as_slice(), dest));
            }
            Token::QuotedString(ref value) => try!(serialize_string(value.as_slice(), dest)),
            Token::Url(ref value) => {
                try!(dest.write_str("url("));
                try!(serialize_string(value.as_slice(), dest));
                try!(dest.write_char(')'));
            },
            Token::Delim(value) => try!(dest.write_char(value)),

            Token::Number(value) => try!(write_numeric(value, dest)),
            Token::Percentage(PercentageValue { unit_value, int_value, signed }) => {
                let value = NumericValue {
                    value: unit_value * 100.,
                    int_value: int_value,
                    signed: signed,
                };
                try!(write_numeric(value, dest));
                try!(dest.write_char('%'));
            },
            Token::Dimension(value, ref unit) => {
                try!(write_numeric(value, dest));
                // Disambiguate with scientific notation.
                let unit = unit.as_slice();
                if unit == "e" || unit == "E" || unit.starts_with("e-") || unit.starts_with("E-") {
                    try!(dest.write_str("\\65 "));
                    for c in unit.slice_from(1).chars() {
                        try!(serialize_char(c, dest, /* is_identifier_start = */ false));
                    }
                } else {
                    try!(serialize_identifier(unit, dest));
                }
            },

            Token::UnicodeRange(start, end) => {
                try!(dest.write_str("U+"));
                let bits = cmp::min(start.trailing_zeros(), (!end).trailing_zeros());
                if bits >= 4 && start >> bits == end >> bits {
                    let question_marks = bits / 4;
                    let common = start >> question_marks * 4;
                    if common != 0 {
                        try!(write!(dest, "{:X}", common));
                    }
                    for _ in range(0, question_marks) {
                        try!(dest.write_str("?"));
                    }
                } else {
                    try!(write!(dest, "{:X}", start));
                    if end != start {
                        try!(write!(dest, "-{:X}", end));
                    }
                }
            }

            Token::WhiteSpace(content) => try!(dest.write_str(content)),
            Token::Comment(content) => try!(write!(dest, "/*{}*/", content)),
            Token::Colon => try!(dest.write_char(':')),
            Token::Semicolon => try!(dest.write_char(';')),
            Token::Comma => try!(dest.write_char(',')),
            Token::IncludeMatch => try!(dest.write_str("~=")),
            Token::DashMatch => try!(dest.write_str("|=")),
            Token::PrefixMatch => try!(dest.write_str("^=")),
            Token::SuffixMatch => try!(dest.write_str("$=")),
            Token::SubstringMatch => try!(dest.write_str("*=")),
            Token::Column => try!(dest.write_str("||")),
            Token::CDO => try!(dest.write_str("<!--")),
            Token::CDC => try!(dest.write_str("-->")),

            Token::Function(ref name) => {
                try!(serialize_identifier(name.as_slice(), dest));
                try!(dest.write_char('('));
            },
            Token::ParenthesisBlock => try!(dest.write_char('(')),
            Token::SquareBracketBlock => try!(dest.write_char('[')),
            Token::CurlyBracketBlock => try!(dest.write_char('{')),

            Token::BadUrl => try!(dest.write_str("url(<bad url>)")),
            Token::BadString => try!(dest.write_str("\"<bad string>\n")),
            Token::CloseParenthesis => try!(dest.write_char(')')),
            Token::CloseSquareBracket => try!(dest.write_char(']')),
            Token::CloseCurlyBracket => try!(dest.write_char('}')),
        }
        Ok(())
    }
}

pub fn serialize_identifier<W>(value: &str, dest: &mut W) -> text_writer::Result
where W:TextWriter {
    // TODO: avoid decoding/re-encoding UTF-8?
    let mut iter = value.chars();
    let mut c = iter.next().unwrap();
    if c == '-' {
        c = match iter.next() {
            None => return dest.write_str("\\-"),
            Some(c) => { try!(dest.write_char('-')); c },
        }
    };
    try!(serialize_char(c, dest, /* is_identifier_start = */ true));
    for c in iter {
        try!(serialize_char(c, dest, /* is_identifier_start = */ false));
    }
    Ok(())
}

#[inline]
fn serialize_char<W>(c: char, dest: &mut W, is_identifier_start: bool) -> text_writer::Result
where W: TextWriter {
    match c {
        '0'...'9' if is_identifier_start => try!(dest.write_str(format!("\\3{} ", c).as_slice())),
        '-' if is_identifier_start => try!(dest.write_str("\\-")),
        '0'...'9' | 'A'...'Z' | 'a'...'z' | '_' | '-' => try!(dest.write_char(c)),
        _ if c > '\x7F' => try!(dest.write_char(c)),
        '\n' => try!(dest.write_str("\\A ")),
        '\r' => try!(dest.write_str("\\D ")),
        '\x0C' => try!(dest.write_str("\\C ")),
        _ => { try!(dest.write_char('\\')); try!(dest.write_char(c)) },
    };
    Ok(())
}

pub fn serialize_string<W>(value: &str, dest: &mut W) -> text_writer::Result
where W: TextWriter {
    try!(dest.write_char('"'));
    try!(CssStringWriter::new(dest).write_str(value));
    try!(dest.write_char('"'));
    Ok(())
}

/// A `TextWriter` adaptor that escapes text for writing as a CSS string.
/// Quotes are not included.
///
/// Typical usage:
///
/// ```{rust,ignore}
/// fn write_foo<W>(foo: &Foo, dest: &mut W) -> text_writer::Result where W: TextWriter {
///     try!(dest.write_char('"'));
///     {
///         let mut string_dest = CssStringWriter::new(dest);
///         // Write into string_dest...
///     }
///     try!(dest.write_char('"'));
///     Ok(())
/// }
/// ```
pub struct CssStringWriter<'a, W: 'a> {
    inner: &'a mut W,
}

impl<'a, W> CssStringWriter<'a, W> where W: TextWriter {
    pub fn new(inner: &'a mut W) -> CssStringWriter<'a, W> {
        CssStringWriter { inner: inner }
    }
}

impl<'a, W> TextWriter for CssStringWriter<'a, W> where W: TextWriter {
    fn write_str(&mut self, s: &str) -> text_writer::Result {
        // TODO: avoid decoding/re-encoding UTF-8?
        for c in s.chars() {
            try!(self.write_char(c))
        }
        Ok(())
    }

    fn write_char(&mut self, c: char) -> text_writer::Result {
        match c {
            '"' => self.inner.write_str("\\\""),
            '\\' => self.inner.write_str("\\\\"),
            '\n' => self.inner.write_str("\\A "),
            '\r' => self.inner.write_str("\\D "),
            '\x0C' => self.inner.write_str("\\C "),
            _ => self.inner.write_char(c),
        }
    }
}

impl<'a> ToCss for [Token<'a>] {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        let mut writer = TokenWriter::new(dest);
        for token in self.iter() {
            try!(writer.write(token))
        }
        Ok(())
    }
}

pub struct TokenWriter<'i, 'a, W: 'a> {
    dest: &'a mut W,
    previous_token: Option<Token<'i>>,
}

impl<'i, 'a, W> TokenWriter<'i, 'a, W> where W: TextWriter {
    pub fn new<'a>(dest: &'a mut W) -> TokenWriter<'i, 'a, W> {
        TokenWriter {
            dest: dest,
            previous_token: None,
        }
    }

    pub fn write(&mut self, token: &Token<'i>) -> text_writer::Result {
        use Token::*;
        let previous = &mem::replace(&mut self.previous_token, Some((*token).clone()))
                        // A "not special" token:
                        .unwrap_or(Colon);
        let (a, b) = (previous, token);
        if (
            matches!(*a, Ident(..) | AtKeyword(..) | Hash(..) | IDHash(..) |
                         Dimension(..) | Delim('#') | Delim('-') | Number(..)) &&
            matches!(*b, Ident(..) | Function(..) | Url(..) | BadUrl(..) |
                         Number(..) | Percentage(..) | Dimension(..) | UnicodeRange(..))
        ) || (
            matches!(*a, Ident(..)) &&
            matches!(*b, ParenthesisBlock(..))
        ) || (
            matches!(*a, Ident(..) | AtKeyword(..) | Hash(..) | IDHash(..) | Dimension(..)) &&
            matches!(*b, Delim('-') | CDC)
        ) || (
            matches!(*a, Delim('#') | Delim('-') | Number(..) | Delim('@')) &&
            matches!(*b, Ident(..) | Function(..) | Url(..) | BadUrl(..))
        ) || (
            matches!(*a, Delim('@')) &&
            matches!(*b, Ident(..) | Function(..) | Url(..) | BadUrl(..) |
                         UnicodeRange(..) | Delim('-'))
        ) || (
            matches!(*a, UnicodeRange(..) | Delim('.') | Delim('+')) &&
            matches!(*b, Number(..) | Percentage(..) | Dimension(..))
        ) || (
            matches!(*a, UnicodeRange(..)) &&
            matches!(*b, Ident(..) | Function(..) | Delim('?'))
        ) || matches!((a, b), (&Delim(a), &Delim(b)) if matches!((a, b),
            ('#', '-') |
            ('$', '=') |
            ('*', '=') |
            ('^', '=') |
            ('~', '=') |
            ('|', '=') |
            ('|', '|') |
            ('/', '*')
        )) {
            try!(self.dest.write_str("/**/"));
        }
        // Skip whitespace when '\n' was previously written at the previous iteration.
        if !matches!((previous, token), (&Delim('\\'), &WhiteSpace(_))) {
            try!(token.to_css(self.dest));
        }
        if token == &Delim('\\') {
            try!(self.dest.write_char('\n'));
        }
        Ok(())
    }
}
<commit_msg>Remove some unnecessary conversions.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::fmt;
use std::mem;
use std::cmp;
use std::num::{Float, Int};

use text_writer::{mod, TextWriter};

use super::{Token, NumericValue, PercentageValue};

pub trait ToCss for Sized? {
    /// Serialize `self` in CSS syntax, writing to `dest`.
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter;

    /// Serialize `self` in CSS syntax and return a string.
    ///
    /// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
    #[inline]
    fn to_css_string(&self) -> String {
        let mut s = String::new();
        self.to_css(&mut s).unwrap();
        s
    }

    /// Serialize `self` in CSS syntax and return a result compatible with `std::fmt::Show`.
    ///
    /// Typical usage is, for a `Foo` that implements `ToCss`:
    ///
    /// ```{rust,ignore}
    /// use std::fmt;
    /// impl fmt::Show for Foo {
    ///     #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
    /// }
    /// ```
    ///
    /// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
    #[inline]
    fn fmt_to_css<W>(&self, dest: &mut W) -> fmt::Result where W: TextWriter {
        self.to_css(dest).map_err(|_| fmt::Error)
    }
}

#[inline]
fn write_numeric<W>(value: NumericValue, dest: &mut W) -> text_writer::Result
where W: TextWriter {
    // `value.value >= 0` is true for negative 0.
    if value.signed && value.value.is_positive() {
        try!(dest.write_str("+"));
    }

    if value.value == 0.0 && value.value.is_negative() {
        // Negative zero. Work around #20596.
        try!(dest.write_str("-0"))
    } else {
        try!(write!(dest, "{}", value.value))
    }

    if value.int_value.is_none() && value.value.fract() == 0. {
        try!(dest.write_str(".0"));
    }
    Ok(())
}

impl<'a> ToCss for Token<'a> {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        match *self {
            Token::Ident(ref value) => try!(serialize_identifier(value.as_slice(), dest)),
            Token::AtKeyword(ref value) => {
                try!(dest.write_char('@'));
                try!(serialize_identifier(value.as_slice(), dest));
            },
            Token::Hash(ref value) => {
                try!(dest.write_char('#'));
                for c in value.chars() {
                    try!(serialize_char(c, dest, /* is_identifier_start = */ false));
                }
            },
            Token::IDHash(ref value) => {
                try!(dest.write_char('#'));
                try!(serialize_identifier(value.as_slice(), dest));
            }
            Token::QuotedString(ref value) => try!(serialize_string(value.as_slice(), dest)),
            Token::Url(ref value) => {
                try!(dest.write_str("url("));
                try!(serialize_string(value.as_slice(), dest));
                try!(dest.write_char(')'));
            },
            Token::Delim(value) => try!(dest.write_char(value)),

            Token::Number(value) => try!(write_numeric(value, dest)),
            Token::Percentage(PercentageValue { unit_value, int_value, signed }) => {
                let value = NumericValue {
                    value: unit_value * 100.,
                    int_value: int_value,
                    signed: signed,
                };
                try!(write_numeric(value, dest));
                try!(dest.write_char('%'));
            },
            Token::Dimension(value, ref unit) => {
                try!(write_numeric(value, dest));
                // Disambiguate with scientific notation.
                let unit = unit.as_slice();
                if unit == "e" || unit == "E" || unit.starts_with("e-") || unit.starts_with("E-") {
                    try!(dest.write_str("\\65 "));
                    for c in unit.slice_from(1).chars() {
                        try!(serialize_char(c, dest, /* is_identifier_start = */ false));
                    }
                } else {
                    try!(serialize_identifier(unit, dest));
                }
            },

            Token::UnicodeRange(start, end) => {
                try!(dest.write_str("U+"));
                let bits = cmp::min(start.trailing_zeros(), (!end).trailing_zeros());
                if bits >= 4 && start >> bits == end >> bits {
                    let question_marks = bits / 4;
                    let common = start >> question_marks * 4;
                    if common != 0 {
                        try!(write!(dest, "{:X}", common));
                    }
                    for _ in range(0, question_marks) {
                        try!(dest.write_str("?"));
                    }
                } else {
                    try!(write!(dest, "{:X}", start));
                    if end != start {
                        try!(write!(dest, "-{:X}", end));
                    }
                }
            }

            Token::WhiteSpace(content) => try!(dest.write_str(content)),
            Token::Comment(content) => try!(write!(dest, "/*{}*/", content)),
            Token::Colon => try!(dest.write_char(':')),
            Token::Semicolon => try!(dest.write_char(';')),
            Token::Comma => try!(dest.write_char(',')),
            Token::IncludeMatch => try!(dest.write_str("~=")),
            Token::DashMatch => try!(dest.write_str("|=")),
            Token::PrefixMatch => try!(dest.write_str("^=")),
            Token::SuffixMatch => try!(dest.write_str("$=")),
            Token::SubstringMatch => try!(dest.write_str("*=")),
            Token::Column => try!(dest.write_str("||")),
            Token::CDO => try!(dest.write_str("<!--")),
            Token::CDC => try!(dest.write_str("-->")),

            Token::Function(ref name) => {
                try!(serialize_identifier(name.as_slice(), dest));
                try!(dest.write_char('('));
            },
            Token::ParenthesisBlock => try!(dest.write_char('(')),
            Token::SquareBracketBlock => try!(dest.write_char('[')),
            Token::CurlyBracketBlock => try!(dest.write_char('{')),

            Token::BadUrl => try!(dest.write_str("url(<bad url>)")),
            Token::BadString => try!(dest.write_str("\"<bad string>\n")),
            Token::CloseParenthesis => try!(dest.write_char(')')),
            Token::CloseSquareBracket => try!(dest.write_char(']')),
            Token::CloseCurlyBracket => try!(dest.write_char('}')),
        }
        Ok(())
    }
}

pub fn serialize_identifier<W>(value: &str, dest: &mut W) -> text_writer::Result
where W:TextWriter {
    // TODO: avoid decoding/re-encoding UTF-8?
    let mut iter = value.chars();
    let mut c = iter.next().unwrap();
    if c == '-' {
        c = match iter.next() {
            None => return dest.write_str("\\-"),
            Some(c) => { try!(dest.write_char('-')); c },
        }
    };
    try!(serialize_char(c, dest, /* is_identifier_start = */ true));
    for c in iter {
        try!(serialize_char(c, dest, /* is_identifier_start = */ false));
    }
    Ok(())
}

#[inline]
fn serialize_char<W>(c: char, dest: &mut W, is_identifier_start: bool) -> text_writer::Result
where W: TextWriter {
    match c {
        '0'...'9' if is_identifier_start => try!(write!(dest, "\\3{} ", c)),
        '-' if is_identifier_start => try!(dest.write_str("\\-")),
        '0'...'9' | 'A'...'Z' | 'a'...'z' | '_' | '-' => try!(dest.write_char(c)),
        _ if c > '\x7F' => try!(dest.write_char(c)),
        '\n' => try!(dest.write_str("\\A ")),
        '\r' => try!(dest.write_str("\\D ")),
        '\x0C' => try!(dest.write_str("\\C ")),
        _ => { try!(dest.write_char('\\')); try!(dest.write_char(c)) },
    };
    Ok(())
}

pub fn serialize_string<W>(value: &str, dest: &mut W) -> text_writer::Result
where W: TextWriter {
    try!(dest.write_char('"'));
    try!(CssStringWriter::new(dest).write_str(value));
    try!(dest.write_char('"'));
    Ok(())
}

/// A `TextWriter` adaptor that escapes text for writing as a CSS string.
/// Quotes are not included.
///
/// Typical usage:
///
/// ```{rust,ignore}
/// fn write_foo<W>(foo: &Foo, dest: &mut W) -> text_writer::Result where W: TextWriter {
///     try!(dest.write_char('"'));
///     {
///         let mut string_dest = CssStringWriter::new(dest);
///         // Write into string_dest...
///     }
///     try!(dest.write_char('"'));
///     Ok(())
/// }
/// ```
pub struct CssStringWriter<'a, W: 'a> {
    inner: &'a mut W,
}

impl<'a, W> CssStringWriter<'a, W> where W: TextWriter {
    pub fn new(inner: &'a mut W) -> CssStringWriter<'a, W> {
        CssStringWriter { inner: inner }
    }
}

impl<'a, W> TextWriter for CssStringWriter<'a, W> where W: TextWriter {
    fn write_str(&mut self, s: &str) -> text_writer::Result {
        // TODO: avoid decoding/re-encoding UTF-8?
        for c in s.chars() {
            try!(self.write_char(c))
        }
        Ok(())
    }

    fn write_char(&mut self, c: char) -> text_writer::Result {
        match c {
            '"' => self.inner.write_str("\\\""),
            '\\' => self.inner.write_str("\\\\"),
            '\n' => self.inner.write_str("\\A "),
            '\r' => self.inner.write_str("\\D "),
            '\x0C' => self.inner.write_str("\\C "),
            _ => self.inner.write_char(c),
        }
    }
}

impl<'a> ToCss for [Token<'a>] {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        let mut writer = TokenWriter::new(dest);
        for token in self.iter() {
            try!(writer.write(token))
        }
        Ok(())
    }
}

pub struct TokenWriter<'i, 'a, W: 'a> {
    dest: &'a mut W,
    previous_token: Option<Token<'i>>,
}

impl<'i, 'a, W> TokenWriter<'i, 'a, W> where W: TextWriter {
    pub fn new<'a>(dest: &'a mut W) -> TokenWriter<'i, 'a, W> {
        TokenWriter {
            dest: dest,
            previous_token: None,
        }
    }

    pub fn write(&mut self, token: &Token<'i>) -> text_writer::Result {
        use Token::*;
        let previous = &mem::replace(&mut self.previous_token, Some((*token).clone()))
                        // A "not special" token:
                        .unwrap_or(Colon);
        let (a, b) = (previous, token);
        if (
            matches!(*a, Ident(..) | AtKeyword(..) | Hash(..) | IDHash(..) |
                         Dimension(..) | Delim('#') | Delim('-') | Number(..)) &&
            matches!(*b, Ident(..) | Function(..) | Url(..) | BadUrl(..) |
                         Number(..) | Percentage(..) | Dimension(..) | UnicodeRange(..))
        ) || (
            matches!(*a, Ident(..)) &&
            matches!(*b, ParenthesisBlock(..))
        ) || (
            matches!(*a, Ident(..) | AtKeyword(..) | Hash(..) | IDHash(..) | Dimension(..)) &&
            matches!(*b, Delim('-') | CDC)
        ) || (
            matches!(*a, Delim('#') | Delim('-') | Number(..) | Delim('@')) &&
            matches!(*b, Ident(..) | Function(..) | Url(..) | BadUrl(..))
        ) || (
            matches!(*a, Delim('@')) &&
            matches!(*b, Ident(..) | Function(..) | Url(..) | BadUrl(..) |
                         UnicodeRange(..) | Delim('-'))
        ) || (
            matches!(*a, UnicodeRange(..) | Delim('.') | Delim('+')) &&
            matches!(*b, Number(..) | Percentage(..) | Dimension(..))
        ) || (
            matches!(*a, UnicodeRange(..)) &&
            matches!(*b, Ident(..) | Function(..) | Delim('?'))
        ) || matches!((a, b), (&Delim(a), &Delim(b)) if matches!((a, b),
            ('#', '-') |
            ('$', '=') |
            ('*', '=') |
            ('^', '=') |
            ('~', '=') |
            ('|', '=') |
            ('|', '|') |
            ('/', '*')
        )) {
            try!(self.dest.write_str("/**/"));
        }
        // Skip whitespace when '\n' was previously written at the previous iteration.
        if !matches!((previous, token), (&Delim('\\'), &WhiteSpace(_))) {
            try!(token.to_css(self.dest));
        }
        if token == &Delim('\\') {
            try!(self.dest.write_char('\n'));
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::io;
use std::net::{SocketAddr, TcpListener as StdTcpListener};
use std::time::Duration;

use tokio::net::TcpListener;
use tokio::time::Sleep;
use tracing::{debug, error, trace};

use crate::common::{task, Future, Pin, Poll};

#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
pub use self::addr_stream::AddrStream;
use super::accept::Accept;

/// A stream of connections from binding to an address.
#[must_use = "streams do nothing unless polled"]
pub struct AddrIncoming {
    addr: SocketAddr,
    listener: TcpListener,
    sleep_on_errors: bool,
    tcp_keepalive_timeout: Option<Duration>,
    tcp_nodelay: bool,
    timeout: Option<Pin<Box<Sleep>>>,
}

impl AddrIncoming {
    pub(super) fn new(addr: &SocketAddr) -> crate::Result<Self> {
        let std_listener = StdTcpListener::bind(addr).map_err(crate::Error::new_listen)?;

        AddrIncoming::from_std(std_listener)
    }

    pub(super) fn from_std(std_listener: StdTcpListener) -> crate::Result<Self> {
        // TcpListener::from_std doesn't set O_NONBLOCK
        std_listener
            .set_nonblocking(true)
            .map_err(crate::Error::new_listen)?;
        let listener = TcpListener::from_std(std_listener).map_err(crate::Error::new_listen)?;
        AddrIncoming::from_listener(listener)
    }

    /// Creates a new `AddrIncoming` binding to provided socket address.
    pub fn bind(addr: &SocketAddr) -> crate::Result<Self> {
        AddrIncoming::new(addr)
    }

    /// Creates a new `AddrIncoming` from an existing `tokio::net::TcpListener`.
    pub fn from_listener(listener: TcpListener) -> crate::Result<Self> {
        let addr = listener.local_addr().map_err(crate::Error::new_listen)?;
        Ok(AddrIncoming {
            listener,
            addr,
            sleep_on_errors: true,
            tcp_keepalive_timeout: None,
            tcp_nodelay: false,
            timeout: None,
        })
    }

    /// Get the local address bound to this listener.
    pub fn local_addr(&self) -> SocketAddr {
        self.addr
    }

    /// Set whether TCP keepalive messages are enabled on accepted connections.
    ///
    /// If `None` is specified, keepalive is disabled, otherwise the duration
    /// specified will be the time to remain idle before sending TCP keepalive
    /// probes.
    pub fn set_keepalive(&mut self, keepalive: Option<Duration>) -> &mut Self {
        self.tcp_keepalive_timeout = keepalive;
        self
    }

    /// Set the value of `TCP_NODELAY` option for accepted connections.
    pub fn set_nodelay(&mut self, enabled: bool) -> &mut Self {
        self.tcp_nodelay = enabled;
        self
    }

    /// Set whether to sleep on accept errors.
    ///
    /// A possible scenario is that the process has hit the max open files
    /// allowed, and so trying to accept a new connection will fail with
    /// `EMFILE`. In some cases, it's preferable to just wait for some time, if
    /// the application will likely close some files (or connections), and try
    /// to accept the connection again. If this option is `true`, the error
    /// will be logged at the `error` level, since it is still a big deal,
    /// and then the listener will sleep for 1 second.
    ///
    /// In other cases, hitting the max open files should be treat similarly
    /// to being out-of-memory, and simply error (and shutdown). Setting
    /// this option to `false` will allow that.
    ///
    /// Default is `true`.
    pub fn set_sleep_on_errors(&mut self, val: bool) {
        self.sleep_on_errors = val;
    }

    fn poll_next_(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<AddrStream>> {
        // Check if a previous timeout is active that was set by IO errors.
        if let Some(ref mut to) = self.timeout {
            ready!(Pin::new(to).poll(cx));
        }
        self.timeout = None;

        loop {
            match ready!(self.listener.poll_accept(cx)) {
                Ok((socket, addr)) => {
                    if let Some(dur) = self.tcp_keepalive_timeout {
                        let socket = socket2::SockRef::from(&socket);
                        let conf = socket2::TcpKeepalive::new().with_time(dur);
                        if let Err(e) = socket.set_tcp_keepalive(&conf) {
                            trace!("error trying to set TCP keepalive: {}", e);
                        }
                    }
                    if let Err(e) = socket.set_nodelay(self.tcp_nodelay) {
                        trace!("error trying to set TCP nodelay: {}", e);
                    }
                    return Poll::Ready(Ok(AddrStream::new(socket, addr)));
                }
                Err(e) => {
                    // Connection errors can be ignored directly, continue by
                    // accepting the next request.
                    if is_connection_error(&e) {
                        debug!("accepted connection already errored: {}", e);
                        continue;
                    }

                    if self.sleep_on_errors {
                        error!("accept error: {}", e);

                        // Sleep 1s.
                        let mut timeout = Box::pin(tokio::time::sleep(Duration::from_secs(1)));

                        match timeout.as_mut().poll(cx) {
                            Poll::Ready(()) => {
                                // Wow, it's been a second already? Ok then...
                                continue;
                            }
                            Poll::Pending => {
                                self.timeout = Some(timeout);
                                return Poll::Pending;
                            }
                        }
                    } else {
                        return Poll::Ready(Err(e));
                    }
                }
            }
        }
    }
}

impl Accept for AddrIncoming {
    type Conn = AddrStream;
    type Error = io::Error;

    fn poll_accept(
        mut self: Pin<&mut Self>,
        cx: &mut task::Context<'_>,
    ) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
        let result = ready!(self.poll_next_(cx));
        Poll::Ready(Some(result))
    }
}

/// This function defines errors that are per-connection. Which basically
/// means that if we get this error from `accept()` system call it means
/// next connection might be ready to be accepted.
///
/// All other errors will incur a timeout before next `accept()` is performed.
/// The timeout is useful to handle resource exhaustion errors like ENFILE
/// and EMFILE. Otherwise, could enter into tight loop.
fn is_connection_error(e: &io::Error) -> bool {
    matches!(e.kind(), io::ErrorKind::ConnectionRefused
        | io::ErrorKind::ConnectionAborted
        | io::ErrorKind::ConnectionReset)
}

impl fmt::Debug for AddrIncoming {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("AddrIncoming")
            .field("addr", &self.addr)
            .field("sleep_on_errors", &self.sleep_on_errors)
            .field("tcp_keepalive_timeout", &self.tcp_keepalive_timeout)
            .field("tcp_nodelay", &self.tcp_nodelay)
            .finish()
    }
}

mod addr_stream {
    use std::io;
    use std::net::SocketAddr;
    #[cfg(unix)]
    use std::os::unix::io::{AsRawFd, RawFd};
    use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
    use tokio::net::TcpStream;

    use crate::common::{task, Pin, Poll};

    pin_project_lite::pin_project! {
        /// A transport returned yieled by `AddrIncoming`.
        #[derive(Debug)]
        pub struct AddrStream {
            #[pin]
            inner: TcpStream,
            pub(super) remote_addr: SocketAddr,
        }
    }

    impl AddrStream {
        pub(super) fn new(tcp: TcpStream, addr: SocketAddr) -> AddrStream {
            AddrStream {
                inner: tcp,
                remote_addr: addr,
            }
        }

        /// Returns the remote (peer) address of this connection.
        #[inline]
        pub fn remote_addr(&self) -> SocketAddr {
            self.remote_addr
        }

        /// Consumes the AddrStream and returns the underlying IO object
        #[inline]
        pub fn into_inner(self) -> TcpStream {
            self.inner
        }

        /// Attempt to receive data on the socket, without removing that data
        /// from the queue, registering the current task for wakeup if data is
        /// not yet available.
        pub fn poll_peek(
            &mut self,
            cx: &mut task::Context<'_>,
            buf: &mut tokio::io::ReadBuf<'_>,
        ) -> Poll<io::Result<usize>> {
            self.inner.poll_peek(cx, buf)
        }
    }

    impl AsyncRead for AddrStream {
        #[inline]
        fn poll_read(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            buf: &mut ReadBuf<'_>,
        ) -> Poll<io::Result<()>> {
            self.project().inner.poll_read(cx, buf)
        }
    }

    impl AsyncWrite for AddrStream {
        #[inline]
        fn poll_write(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            buf: &[u8],
        ) -> Poll<io::Result<usize>> {
            self.project().inner.poll_write(cx, buf)
        }

        #[inline]
        fn poll_write_vectored(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            bufs: &[io::IoSlice<'_>],
        ) -> Poll<io::Result<usize>> {
            self.project().inner.poll_write_vectored(cx, bufs)
        }

        #[inline]
        fn poll_flush(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
            // TCP flush is a noop
            Poll::Ready(Ok(()))
        }

        #[inline]
        fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
            self.project().inner.poll_shutdown(cx)
        }

        #[inline]
        fn is_write_vectored(&self) -> bool {
            // Note that since `self.inner` is a `TcpStream`, this could
            // *probably* be hard-coded to return `true`...but it seems more
            // correct to ask it anyway (maybe we're on some platform without
            // scatter-gather IO?)
            self.inner.is_write_vectored()
        }
    }

    #[cfg(unix)]
    impl AsRawFd for AddrStream {
        fn as_raw_fd(&self) -> RawFd {
            self.inner.as_raw_fd()
        }
    }
}
<commit_msg>feat(server): add `AddrStream::local_addr()` (#2816)<commit_after>use std::fmt;
use std::io;
use std::net::{SocketAddr, TcpListener as StdTcpListener};
use std::time::Duration;

use tokio::net::TcpListener;
use tokio::time::Sleep;
use tracing::{debug, error, trace};

use crate::common::{task, Future, Pin, Poll};

#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
pub use self::addr_stream::AddrStream;
use super::accept::Accept;

/// A stream of connections from binding to an address.
#[must_use = "streams do nothing unless polled"]
pub struct AddrIncoming {
    addr: SocketAddr,
    listener: TcpListener,
    sleep_on_errors: bool,
    tcp_keepalive_timeout: Option<Duration>,
    tcp_nodelay: bool,
    timeout: Option<Pin<Box<Sleep>>>,
}

impl AddrIncoming {
    pub(super) fn new(addr: &SocketAddr) -> crate::Result<Self> {
        let std_listener = StdTcpListener::bind(addr).map_err(crate::Error::new_listen)?;

        AddrIncoming::from_std(std_listener)
    }

    pub(super) fn from_std(std_listener: StdTcpListener) -> crate::Result<Self> {
        // TcpListener::from_std doesn't set O_NONBLOCK
        std_listener
            .set_nonblocking(true)
            .map_err(crate::Error::new_listen)?;
        let listener = TcpListener::from_std(std_listener).map_err(crate::Error::new_listen)?;
        AddrIncoming::from_listener(listener)
    }

    /// Creates a new `AddrIncoming` binding to provided socket address.
    pub fn bind(addr: &SocketAddr) -> crate::Result<Self> {
        AddrIncoming::new(addr)
    }

    /// Creates a new `AddrIncoming` from an existing `tokio::net::TcpListener`.
    pub fn from_listener(listener: TcpListener) -> crate::Result<Self> {
        let addr = listener.local_addr().map_err(crate::Error::new_listen)?;
        Ok(AddrIncoming {
            listener,
            addr,
            sleep_on_errors: true,
            tcp_keepalive_timeout: None,
            tcp_nodelay: false,
            timeout: None,
        })
    }

    /// Get the local address bound to this listener.
    pub fn local_addr(&self) -> SocketAddr {
        self.addr
    }

    /// Set whether TCP keepalive messages are enabled on accepted connections.
    ///
    /// If `None` is specified, keepalive is disabled, otherwise the duration
    /// specified will be the time to remain idle before sending TCP keepalive
    /// probes.
    pub fn set_keepalive(&mut self, keepalive: Option<Duration>) -> &mut Self {
        self.tcp_keepalive_timeout = keepalive;
        self
    }

    /// Set the value of `TCP_NODELAY` option for accepted connections.
    pub fn set_nodelay(&mut self, enabled: bool) -> &mut Self {
        self.tcp_nodelay = enabled;
        self
    }

    /// Set whether to sleep on accept errors.
    ///
    /// A possible scenario is that the process has hit the max open files
    /// allowed, and so trying to accept a new connection will fail with
    /// `EMFILE`. In some cases, it's preferable to just wait for some time, if
    /// the application will likely close some files (or connections), and try
    /// to accept the connection again. If this option is `true`, the error
    /// will be logged at the `error` level, since it is still a big deal,
    /// and then the listener will sleep for 1 second.
    ///
    /// In other cases, hitting the max open files should be treat similarly
    /// to being out-of-memory, and simply error (and shutdown). Setting
    /// this option to `false` will allow that.
    ///
    /// Default is `true`.
    pub fn set_sleep_on_errors(&mut self, val: bool) {
        self.sleep_on_errors = val;
    }

    fn poll_next_(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<AddrStream>> {
        // Check if a previous timeout is active that was set by IO errors.
        if let Some(ref mut to) = self.timeout {
            ready!(Pin::new(to).poll(cx));
        }
        self.timeout = None;

        loop {
            match ready!(self.listener.poll_accept(cx)) {
                Ok((socket, remote_addr)) => {
                    if let Some(dur) = self.tcp_keepalive_timeout {
                        let socket = socket2::SockRef::from(&socket);
                        let conf = socket2::TcpKeepalive::new().with_time(dur);
                        if let Err(e) = socket.set_tcp_keepalive(&conf) {
                            trace!("error trying to set TCP keepalive: {}", e);
                        }
                    }
                    if let Err(e) = socket.set_nodelay(self.tcp_nodelay) {
                        trace!("error trying to set TCP nodelay: {}", e);
                    }
                    let local_addr = socket.local_addr()?;
                    return Poll::Ready(Ok(AddrStream::new(socket, remote_addr, local_addr)));
                }
                Err(e) => {
                    // Connection errors can be ignored directly, continue by
                    // accepting the next request.
                    if is_connection_error(&e) {
                        debug!("accepted connection already errored: {}", e);
                        continue;
                    }

                    if self.sleep_on_errors {
                        error!("accept error: {}", e);

                        // Sleep 1s.
                        let mut timeout = Box::pin(tokio::time::sleep(Duration::from_secs(1)));

                        match timeout.as_mut().poll(cx) {
                            Poll::Ready(()) => {
                                // Wow, it's been a second already? Ok then...
                                continue;
                            }
                            Poll::Pending => {
                                self.timeout = Some(timeout);
                                return Poll::Pending;
                            }
                        }
                    } else {
                        return Poll::Ready(Err(e));
                    }
                }
            }
        }
    }
}

impl Accept for AddrIncoming {
    type Conn = AddrStream;
    type Error = io::Error;

    fn poll_accept(
        mut self: Pin<&mut Self>,
        cx: &mut task::Context<'_>,
    ) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
        let result = ready!(self.poll_next_(cx));
        Poll::Ready(Some(result))
    }
}

/// This function defines errors that are per-connection. Which basically
/// means that if we get this error from `accept()` system call it means
/// next connection might be ready to be accepted.
///
/// All other errors will incur a timeout before next `accept()` is performed.
/// The timeout is useful to handle resource exhaustion errors like ENFILE
/// and EMFILE. Otherwise, could enter into tight loop.
fn is_connection_error(e: &io::Error) -> bool {
    matches!(
        e.kind(),
        io::ErrorKind::ConnectionRefused
            | io::ErrorKind::ConnectionAborted
            | io::ErrorKind::ConnectionReset
    )
}

impl fmt::Debug for AddrIncoming {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("AddrIncoming")
            .field("addr", &self.addr)
            .field("sleep_on_errors", &self.sleep_on_errors)
            .field("tcp_keepalive_timeout", &self.tcp_keepalive_timeout)
            .field("tcp_nodelay", &self.tcp_nodelay)
            .finish()
    }
}

mod addr_stream {
    use std::io;
    use std::net::SocketAddr;
    #[cfg(unix)]
    use std::os::unix::io::{AsRawFd, RawFd};
    use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
    use tokio::net::TcpStream;

    use crate::common::{task, Pin, Poll};

    pin_project_lite::pin_project! {
        /// A transport returned yieled by `AddrIncoming`.
        #[derive(Debug)]
        pub struct AddrStream {
            #[pin]
            inner: TcpStream,
            pub(super) remote_addr: SocketAddr,
            pub(super) local_addr: SocketAddr
        }
    }

    impl AddrStream {
        pub(super) fn new(
            tcp: TcpStream,
            remote_addr: SocketAddr,
            local_addr: SocketAddr,
        ) -> AddrStream {
            AddrStream {
                inner: tcp,
                remote_addr,
                local_addr,
            }
        }

        /// Returns the remote (peer) address of this connection.
        #[inline]
        pub fn remote_addr(&self) -> SocketAddr {
            self.remote_addr
        }

        /// Returns the local address of this connection.
        #[inline]
        pub fn local_addr(&self) -> SocketAddr {
            self.local_addr
        }

        /// Consumes the AddrStream and returns the underlying IO object
        #[inline]
        pub fn into_inner(self) -> TcpStream {
            self.inner
        }

        /// Attempt to receive data on the socket, without removing that data
        /// from the queue, registering the current task for wakeup if data is
        /// not yet available.
        pub fn poll_peek(
            &mut self,
            cx: &mut task::Context<'_>,
            buf: &mut tokio::io::ReadBuf<'_>,
        ) -> Poll<io::Result<usize>> {
            self.inner.poll_peek(cx, buf)
        }
    }

    impl AsyncRead for AddrStream {
        #[inline]
        fn poll_read(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            buf: &mut ReadBuf<'_>,
        ) -> Poll<io::Result<()>> {
            self.project().inner.poll_read(cx, buf)
        }
    }

    impl AsyncWrite for AddrStream {
        #[inline]
        fn poll_write(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            buf: &[u8],
        ) -> Poll<io::Result<usize>> {
            self.project().inner.poll_write(cx, buf)
        }

        #[inline]
        fn poll_write_vectored(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            bufs: &[io::IoSlice<'_>],
        ) -> Poll<io::Result<usize>> {
            self.project().inner.poll_write_vectored(cx, bufs)
        }

        #[inline]
        fn poll_flush(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
            // TCP flush is a noop
            Poll::Ready(Ok(()))
        }

        #[inline]
        fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
            self.project().inner.poll_shutdown(cx)
        }

        #[inline]
        fn is_write_vectored(&self) -> bool {
            // Note that since `self.inner` is a `TcpStream`, this could
            // *probably* be hard-coded to return `true`...but it seems more
            // correct to ask it anyway (maybe we're on some platform without
            // scatter-gather IO?)
            self.inner.is_write_vectored()
        }
    }

    #[cfg(unix)]
    impl AsRawFd for AddrStream {
        fn as_raw_fd(&self) -> RawFd {
            self.inner.as_raw_fd()
        }
    }
}
<|endoftext|>


<commit_before>pub mod human;
pub mod ki;

use arena;
use db::pokemon_token::PokemonToken;
use db::pokedex::*;
use std::collections::HashMap;
use db::{moves, enums};

/// The Player type represents if the Player is a Human or a specific Ai to call different funcions
/// for e.g. choosing Pokemon
#[derive(Clone, Debug)]
pub enum PlayerType {
    Human,
    SimpleAi,
}

/// The Player struct represents a Player and holds his Type (Human, Ai...), a list of his pokemon,
/// the amount of pokemon, his currently fighting pokemon and the next_move he wants to make
#[derive(Clone, Debug)]
pub struct Player {
    player: PlayerType,
    pokemon_list: Vec<PokemonToken>,
    pokemon_count: usize,
    current: usize,
    next_move: Option<(moves::Technique, u8)>,
    flags: HashMap<enums::PlayerFlag, u8>,
    last_move: Option<(moves::Technique, AttackSlot)>,
}

impl Player {
    // Constructor
    //
    /// Takes an array with pokemon id´s and the PlayerType and returns a player
    pub fn new_by_id(input: &[usize], player_type: PlayerType) -> Self {
        let mut pokemon = Vec::new();
        let len = input.len();
        let dex = Pokedex::new();
        for i in 0..input.len() {
            pokemon.push(PokemonToken::from_model(dex.pokemon_by_id(input[i]).unwrap()));
        }
        Player {
            player: player_type,
            pokemon_list: pokemon,
            pokemon_count: len,
            current: 0,
            next_move: None,
            flags: HashMap::new(),
            last_move: None,
        }
    }

    // Getter methods
    //
    /// Returns the list of pokemon choosen by the player
    pub fn get_pokemon_list(&mut self) -> &mut Vec<PokemonToken> {
        &mut self.pokemon_list
    }
    /// Returns the currently fighting pokemon
    pub fn get_current(&self) -> usize {
        self.current
    }
    /// Gets the amount of pokemon choosen by the player
    pub fn get_pokemon_count(&self) -> usize {
        self.pokemon_count
    }
    /// Returns the amount of pokemon with atleast one hp
    pub fn get_alive_count(&mut self) -> usize {
        // self.pokemon_list.iter().filter(|x| x.get_current().get_stat(enums::Stats::Hp) != 0)
        //     .count()
        3
    }
    /// Returns a Vec with the id´s from the pokemon which are alive
    pub fn get_alive_list(&self) -> Vec<usize> {
        let vec = Vec::new();
        // for i in 0..self.pokemon_list.len() {
        //     if self.get_pokemon_list()[i].get_current().get_stat(enums::Stats::Hp) != 0 {
        //         vec.push(i);
        //     }
        // }
        vec
    }
    /// Gets a attack saved in an attackslot
    pub fn get_attack(&mut self, slot: &AttackSlot) -> moves::Technique {
        match slot {
            &AttackSlot::One => self.pokemon_list[self.current].clone().get_move_one().unwrap(),
            &AttackSlot::Two => self.pokemon_list[self.current].clone().get_move_two().unwrap(),
            &AttackSlot::Three => self.pokemon_list[self.current].clone().get_move_three().unwrap(),
            &AttackSlot::Four => self.pokemon_list[self.current].clone().get_move_four().unwrap(),
        }
    }
    /// Gets the next attack from the Player. Returns none if no Technique is selected
    pub fn get_next_move(&self) -> Option<(moves::Technique, u8)> {
        self.next_move.clone()
    }
    /// Gets the last move with the Slot. Returns None if the last move wasn´t an attack
    pub fn get_last_move(&self) -> Option<(moves::Technique, AttackSlot)> {
        self.last_move.clone()
    }

    pub fn get_flags(&mut self) -> &mut HashMap<enums::PlayerFlag, u8> {
        &mut self.flags
    }

    // Setter methods
    //
    /// Sets the current value (e.g. after a pokemon swap)
    /// Given values should be between 1 and the maximum amount of pokemon you have
    pub fn set_current(&mut self, new: usize) {
        self.current = new;
    }
    /// Sets a next move to the Player
    pub fn set_next_move(&mut self, next: Option<(moves::Technique, u8)>) {
        self.next_move = next;
    }
    pub fn add_flag(&mut self, flag: enums::PlayerFlag) {
        self.flags.insert(flag, 0);
    }
    /// Sets the last move the attacking pokemon made with the Slot in which it is saved
    pub fn set_last_move(&mut self, last: Option<(moves::Technique, AttackSlot)>) {
        self.last_move = last;
    }
    // Other
    //
    pub fn attack_or_swap(&self) -> arena::to_ui::Move {
        match self.player {
            PlayerType::Human => arena::to_ui::ui_move(),
            PlayerType::SimpleAi => arena::to_ui::ui_move(),
        }
    }
}

/// An enum which represents the AttackSlot to match with it
#[derive(Debug, Clone)]
pub enum AttackSlot {
    One,
    Two,
    Three,
    Four,
}
<commit_msg>fixed last two getter methods in Player<commit_after>pub mod human;
pub mod ki;

use arena;
use db::pokemon_token::PokemonToken;
use db::pokedex::*;
use std::collections::HashMap;
use db::{moves, enums};

/// The Player type represents if the Player is a Human or a specific Ai to call different funcions
/// for e.g. choosing Pokemon
#[derive(Clone, Debug)]
pub enum PlayerType {
    Human,
    SimpleAi,
}

/// The Player struct represents a Player and holds his Type (Human, Ai...), a list of his pokemon,
/// the amount of pokemon, his currently fighting pokemon and the next_move he wants to make
#[derive(Clone, Debug)]
pub struct Player {
    player: PlayerType,
    pokemon_list: Vec<PokemonToken>,
    pokemon_count: usize,
    current: usize,
    next_move: Option<(moves::Technique, u8)>,
    flags: HashMap<enums::PlayerFlag, u8>,
    last_move: Option<(moves::Technique, AttackSlot)>,
}

impl Player {
    // Constructor
    //
    /// Takes an array with pokemon id´s and the PlayerType and returns a player
    pub fn new_by_id(input: &[usize], player_type: PlayerType) -> Self {
        let mut pokemon = Vec::new();
        let len = input.len();
        let dex = Pokedex::new();
        for i in 0..input.len() {
            pokemon.push(PokemonToken::from_model(dex.pokemon_by_id(input[i]).unwrap()));
        }
        Player {
            player: player_type,
            pokemon_list: pokemon,
            pokemon_count: len,
            current: 0,
            next_move: None,
            flags: HashMap::new(),
            last_move: None,
        }
    }

    // Getter methods
    //
    /// Returns the list of pokemon choosen by the player
    pub fn get_pokemon_list(&mut self) -> &mut Vec<PokemonToken> {
        &mut self.pokemon_list
    }
    /// Returns the currently fighting pokemon
    pub fn get_current(&self) -> usize {
        self.current
    }
    /// Gets the amount of pokemon choosen by the player
    pub fn get_pokemon_count(&self) -> usize {
        self.pokemon_count
    }
    /// Returns the amount of pokemon with atleast one hp
    pub fn get_alive_count(&mut self) -> usize {
        let mut alive = 0;
        for i in 0..self.pokemon_list.len() {
            if self.pokemon_list[i].get_current().get_stat(&enums::Stats::Hp) == 0 {
                alive += 1;
            }
        }
        alive
    }
    /// Returns a Vec with the id´s in the player model from the pokemon which are alive
    pub fn get_alive_list(&mut self) -> Vec<usize> {
        let mut vec = Vec::new();
         for i in 0..self.pokemon_list.len() {
            if self.get_pokemon_list()[i].get_current().get_stat(&enums::Stats::Hp) != 0 {
                vec.push(i);
            }
        }
        vec
    }
    /// Gets a attack saved in an attackslot
    pub fn get_attack(&mut self, slot: &AttackSlot) -> moves::Technique {
        match slot {
            &AttackSlot::One => self.pokemon_list[self.current].clone().get_move_one().unwrap(),
            &AttackSlot::Two => self.pokemon_list[self.current].clone().get_move_two().unwrap(),
            &AttackSlot::Three => self.pokemon_list[self.current].clone().get_move_three().unwrap(),
            &AttackSlot::Four => self.pokemon_list[self.current].clone().get_move_four().unwrap(),
        }
    }
    /// Gets the next attack from the Player. Returns none if no Technique is selected
    pub fn get_next_move(&self) -> Option<(moves::Technique, u8)> {
        self.next_move.clone()
    }
    /// Gets the last move with the Slot. Returns None if the last move wasn´t an attack
    pub fn get_last_move(&self) -> Option<(moves::Technique, AttackSlot)> {
        self.last_move.clone()
    }

    pub fn get_flags(&mut self) -> &mut HashMap<enums::PlayerFlag, u8> {
        &mut self.flags
    }

    // Setter methods
    //
    /// Sets the current value (e.g. after a pokemon swap)
    /// Given values should be between 1 and the maximum amount of pokemon you have
    pub fn set_current(&mut self, new: usize) {
        self.current = new;
    }
    /// Sets a next move to the Player
    pub fn set_next_move(&mut self, next: Option<(moves::Technique, u8)>) {
        self.next_move = next;
    }
    pub fn add_flag(&mut self, flag: enums::PlayerFlag) {
        self.flags.insert(flag, 0);
    }
    /// Sets the last move the attacking pokemon made with the Slot in which it is saved
    pub fn set_last_move(&mut self, last: Option<(moves::Technique, AttackSlot)>) {
        self.last_move = last;
    }
    // Other
    //
    pub fn attack_or_swap(&self) -> arena::to_ui::Move {
        match self.player {
            PlayerType::Human => arena::to_ui::ui_move(),
            PlayerType::SimpleAi => arena::to_ui::ui_move(),
        }
    }
}

/// An enum which represents the AttackSlot to match with it
#[derive(Debug, Clone)]
pub enum AttackSlot {
    One,
    Two,
    Three,
    Four,
}
<|endoftext|>