<commit_before>use std::io::prelude::*;

#[derive(Clone, Debug, PartialEq, PartialOrd, Default)]
pub struct Settings {
    /// The byte ordering of data transmitted.
    pub byte_order: ByteOrder,
}

/// Specifies the byte order of data transfer.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ByteOrder {
    LittleEndian,
    BigEndian,
    NativeEndian,
}

impl Default for ByteOrder {
    fn default() -> Self {
        ByteOrder::BigEndian
    }
}

macro_rules! impl_byte_order_helpers {
    ( $( $ty:ty => [ $read_name:ident : $write_name:ident ] )* ) => {
        impl ByteOrder {
            $(
                pub fn $read_name(&self, read: &mut Read) -> Result<$ty, ::Error> {
                    use byteorder as bo;

                    Ok(match *self {
                        ByteOrder::LittleEndian => bo::ReadBytesExt::$read_name::<bo::LittleEndian>(read),
                        ByteOrder::BigEndian => bo::ReadBytesExt::$read_name::<bo::BigEndian>(read),
                        ByteOrder::NativeEndian => bo::ReadBytesExt::$read_name::<bo::NativeEndian>(read),
                    }?)
                }

                pub fn $write_name(&self, value: $ty,
                                   write: &mut Write) -> Result<(), ::Error> {
                    use byteorder as bo;

                    Ok(match *self {
                        ByteOrder::LittleEndian => bo::WriteBytesExt::$write_name::<bo::LittleEndian>(write, value),
                        ByteOrder::BigEndian => bo::WriteBytesExt::$write_name::<bo::BigEndian>(write, value),
                        ByteOrder::NativeEndian => bo::WriteBytesExt::$write_name::<bo::NativeEndian>(write, value),
                    }?)
                }
            )*
        }
    };
}

impl_byte_order_helpers!(
    u16 => [read_u16 : write_u16]
    i16 => [read_i16 : write_i16]
    u32 => [read_u32 : write_u32]
    i32 => [read_i32 : write_i32]
    u64 => [read_u64 : write_u64]
    i64 => [read_i64 : write_i64]
    f32 => [read_f32 : write_f32]
    f64 => [read_f64 : write_f64]
);

<commit_msg>Properly support comparisons with ByteOrder::NativeEndian<commit_after>use std::io::prelude::*;

/// Defines serialization settings.
#[derive(Clone, Debug, PartialEq, PartialOrd, Default)]
pub struct Settings {
    /// The byte ordering of data transmitted.
    pub byte_order: ByteOrder,
}

/// Specifies the byte order of data transfer.
///
/// # `Eq` implementation
///
/// Here is a list of rules the `Eq` implementation satisfies.
///
///   * `LittleEndian == LittleEndian`
///   * `LittleEndian != BigEndian`
///   * `NativeEndian == LittleEndian` (but only on little endian machines)
///   * `NativeEndian == BigEndian` (but only on big endian machines)
///
/// The `NativeEndian` byte order will successfully match against
/// one of the two real-life byte orders.
#[derive(Copy, Clone, Debug, Eq, PartialOrd, Ord, Hash)]
pub enum ByteOrder {
    /// Least significant byte first.
    LittleEndian,
    /// Most significant byte first.
    BigEndian,
    /// Whatever the byte ordering of the current machine is.
    NativeEndian,
}

#[cfg(target_endian = "little")]
const NATIVE_BYTE_ORDER: ByteOrder = ByteOrder::LittleEndian;
#[cfg(target_endian = "big")]
const NATIVE_BYTE_ORDER: ByteOrder = ByteOrder::BigEndian;

impl ByteOrder {
    /// Resolves the byte order into either little or big endian.
    fn realize(self) -> Self {
        match self {
            ByteOrder::NativeEndian => NATIVE_BYTE_ORDER,
            b => b,
        }
    }
}

impl Default for ByteOrder {
    fn default() -> Self {
        ByteOrder::BigEndian
    }
}

impl ::std::cmp::PartialEq for ByteOrder {
    fn eq(&self, other: &Self) -> bool {
        use ByteOrder::*;

        match (self.realize(), other.realize()) {
            (LittleEndian, LittleEndian) => true,
            (BigEndian, BigEndian) => true,
            _ => false,
        }
    }
}

macro_rules! impl_byte_order_helpers {
    ( $( $ty:ty => [ $read_name:ident : $write_name:ident ] )* ) => {
        impl ByteOrder {
            $(
                pub fn $read_name(&self, read: &mut Read) -> Result<$ty, ::Error> {
                    use byteorder as bo;

                    Ok(match *self {
                        ByteOrder::LittleEndian => bo::ReadBytesExt::$read_name::<bo::LittleEndian>(read),
                        ByteOrder::BigEndian => bo::ReadBytesExt::$read_name::<bo::BigEndian>(read),
                        ByteOrder::NativeEndian => bo::ReadBytesExt::$read_name::<bo::NativeEndian>(read),
                    }?)
                }

                pub fn $write_name(&self, value: $ty,
                                   write: &mut Write) -> Result<(), ::Error> {
                    use byteorder as bo;

                    Ok(match *self {
                        ByteOrder::LittleEndian => bo::WriteBytesExt::$write_name::<bo::LittleEndian>(write, value),
                        ByteOrder::BigEndian => bo::WriteBytesExt::$write_name::<bo::BigEndian>(write, value),
                        ByteOrder::NativeEndian => bo::WriteBytesExt::$write_name::<bo::NativeEndian>(write, value),
                    }?)
                }
            )*
        }
    };
}

impl_byte_order_helpers!(
    u16 => [read_u16 : write_u16]
    i16 => [read_i16 : write_i16]
    u32 => [read_u32 : write_u32]
    i32 => [read_i32 : write_i32]
    u64 => [read_u64 : write_u64]
    i64 => [read_i64 : write_i64]
    f32 => [read_f32 : write_f32]
    f64 => [read_f64 : write_f64]
);

<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
// Copyright 2013-2017 The Rust Project Developers.
//
// 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.

//! Generating random samples from probability distributions
//!
//! This module is the home of the [`Distribution`] trait and several of its
//! implementations. It is the workhorse behind some of the convenient
//! functionality of the [`Rng`] trait, e.g. [`Rng::gen`] and of course
//! [`Rng::sample`].
//!
//! Abstractly, a [probability distribution] describes the probability of
//! occurrence of each value in its sample space.
//!
//! More concretely, an implementation of `Distribution<T>` for type `X` is an
//! algorithm for choosing values from the sample space (a subset of `T`)
//! according to the distribution `X` represents, using an external source of
//! randomness (an RNG supplied to the `sample` function).
//!
//! A type `X` may implement `Distribution<T>` for multiple types `T`.
//! Any type implementing [`Distribution`] is stateless (i.e. immutable),
//! but it may have internal parameters set at construction time (for example,
//! [`Uniform`] allows specification of its sample space as a range within `T`).
//!
//!
//! # The `Standard` distribution
//!
//! The [`Standard`] distribution is important to mention. This is the
//! distribution used by [`Rng::gen`] and represents the "default" way to
//! produce a random value for many different types, including most primitive
//! types, tuples, arrays, and a few derived types. See the documentation of
//! [`Standard`] for more details.
//!
//! Implementing `Distribution<T>` for [`Standard`] for user types `T` makes it
//! possible to generate type `T` with [`Rng::gen`], and by extension also
//! with the [`random`] function.
//!
//! ## Random characters
//!
//! [`Alphanumeric`] is a simple distribution to sample random letters and
//! numbers of the `char` type; in contrast [`Standard`] may sample any valid
//! `char`.
//!
//!
//! # Uniform numeric ranges
//!
//! The [`Uniform`] distribution is more flexible than [`Standard`], but also
//! more specialised: it supports fewer target types, but allows the sample
//! space to be specified as an arbitrary range within its target type `T`.
//! Both [`Standard`] and [`Uniform`] are in some sense uniform distributions.
//!
//! Values may be sampled from this distribution using [`Rng::sample(Range)`] or
//! by creating a distribution object with [`Uniform::new`],
//! [`Uniform::new_inclusive`] or `From<Range>`. When the range limits are not
//! known at compile time it is typically faster to reuse an existing
//! `Uniform` object than to call [`Rng::sample(Range)`].
//!
//! User types `T` may also implement `Distribution<T>` for [`Uniform`],
//! although this is less straightforward than for [`Standard`] (see the
//! documentation in the [`uniform`] module). Doing so enables generation of
//! values of type `T` with  [`Rng::sample(Range)`].
//!
//! ## Open and half-open ranges
//!
//! There are surprisingly many ways to uniformly generate random floats. A
//! range between 0 and 1 is standard, but the exact bounds (open vs closed)
//! and accuracy differ. In addition to the [`Standard`] distribution Rand offers
//! [`Open01`] and [`OpenClosed01`]. See "Floating point implementation" section of
//! [`Standard`] documentation for more details.
//!
//! # Non-uniform sampling
//!
//! Sampling a simple true/false outcome with a given probability has a name:
//! the [`Bernoulli`] distribution (this is used by [`Rng::gen_bool`]).
//!
//! For weighted sampling from a sequence of discrete values, use the
//! [`weighted`] module.
//!
//! This crate no longer includes other non-uniform distributions; instead
//! it is recommended that you use either [`rand_distr`] or [`statrs`].
//!
//!
//! [probability distribution]: https://en.wikipedia.org/wiki/Probability_distribution
//! [`rand_distr`]: https://crates.io/crates/rand_distr
//! [`statrs`]: https://crates.io/crates/statrs

//! [`random`]: crate::random
//! [`rand_distr`]: https://crates.io/crates/rand_distr
//! [`statrs`]: https://crates.io/crates/statrs

use crate::Rng;
use core::iter;

pub use self::bernoulli::{Bernoulli, BernoulliError};
pub use self::float::{Open01, OpenClosed01};
pub use self::other::Alphanumeric;
#[doc(inline)] pub use self::uniform::Uniform;

#[cfg(feature = "alloc")]
pub use self::weighted_index::{WeightedError, WeightedIndex};

mod bernoulli;
pub mod uniform;

#[deprecated(since = "0.8.0", note = "use rand::distributions::{WeightedIndex, WeightedError} instead")]
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub mod weighted;
#[cfg(feature = "alloc")] mod weighted_index;

#[cfg(feature = "serde1")]
use serde::{Serialize, Deserialize};

mod float;
#[doc(hidden)]
pub mod hidden_export {
    pub use super::float::IntoFloat; // used by rand_distr
}
mod integer;
mod other;
mod utils;

/// Types (distributions) that can be used to create a random instance of `T`.
///
/// It is possible to sample from a distribution through both the
/// `Distribution` and [`Rng`] traits, via `distr.sample(&mut rng)` and
/// `rng.sample(distr)`. They also both offer the [`sample_iter`] method, which
/// produces an iterator that samples from the distribution.
///
/// All implementations are expected to be immutable; this has the significant
/// advantage of not needing to consider thread safety, and for most
/// distributions efficient state-less sampling algorithms are available.
///
/// Implementations are typically expected to be portable with reproducible
/// results when used with a PRNG with fixed seed; see the
/// [portability chapter](https://rust-random.github.io/book/portability.html)
/// of The Rust Rand Book. In some cases this does not apply, e.g. the `usize`
/// type requires different sampling on 32-bit and 64-bit machines.
///
/// [`sample_iter`]: Distribution::method.sample_iter
pub trait Distribution<T> {
    /// Generate a random value of `T`, using `rng` as the source of randomness.
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T;

    /// Create an iterator that generates random values of `T`, using `rng` as
    /// the source of randomness.
    ///
    /// Note that this function takes `self` by value. This works since
    /// `Distribution<T>` is impl'd for `&D` where `D: Distribution<T>`,
    /// however borrowing is not automatic hence `distr.sample_iter(...)` may
    /// need to be replaced with `(&distr).sample_iter(...)` to borrow or
    /// `(&*distr).sample_iter(...)` to reborrow an existing reference.
    ///
    /// # Example
    ///
    /// ```
    /// use rand::thread_rng;
    /// use rand::distributions::{Distribution, Alphanumeric, Uniform, Standard};
    ///
    /// let rng = thread_rng();
    ///
    /// // Vec of 16 x f32:
    /// let v: Vec<f32> = Standard.sample_iter(rng).take(16).collect();
    ///
    /// // String:
    /// let s: String = Alphanumeric.sample_iter(rng).take(7).map(char::from).collect();
    ///
    /// // Dice-rolling:
    /// let die_range = Uniform::new_inclusive(1, 6);
    /// let mut roll_die = die_range.sample_iter(rng);
    /// while roll_die.next().unwrap() != 6 {
    ///     println!("Not a 6; rolling again!");
    /// }
    /// ```
    fn sample_iter<R>(self, rng: R) -> DistIter<Self, R, T>
    where
        R: Rng,
        Self: Sized,
    {
        DistIter {
            distr: self,
            rng,
            phantom: ::core::marker::PhantomData,
        }
    }
}

impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T {
        (*self).sample(rng)
    }
}

/// An iterator that generates random values of `T` with distribution `D`,
/// using `R` as the source of randomness.
///
/// This `struct` is created by the [`sample_iter`] method on [`Distribution`].
/// See its documentation for more.
///
/// [`sample_iter`]: Distribution::sample_iter
#[derive(Debug)]
pub struct DistIter<D, R, T> {
    distr: D,
    rng: R,
    phantom: ::core::marker::PhantomData<T>,
}

impl<D, R, T> Iterator for DistIter<D, R, T>
where
    D: Distribution<T>,
    R: Rng,
{
    type Item = T;

    #[inline(always)]
    fn next(&mut self) -> Option<T> {
        // Here, self.rng may be a reference, but we must take &mut anyway.
        // Even if sample could take an R: Rng by value, we would need to do this
        // since Rng is not copyable and we cannot enforce that this is "reborrowable".
        Some(self.distr.sample(&mut self.rng))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (usize::max_value(), None)
    }
}

impl<D, R, T> iter::FusedIterator for DistIter<D, R, T>
where
    D: Distribution<T>,
    R: Rng,
{
}

#[cfg(features = "nightly")]
impl<D, R, T> iter::TrustedLen for DistIter<D, R, T>
where
    D: Distribution<T>,
    R: Rng,
{
}

/// A generic random value distribution, implemented for many primitive types.
/// Usually generates values with a numerically uniform distribution, and with a
/// range appropriate to the type.
///
/// ## Provided implementations
///
/// Assuming the provided `Rng` is well-behaved, these implementations
/// generate values with the following ranges and distributions:
///
/// * Integers (`i32`, `u32`, `isize`, `usize`, etc.): Uniformly distributed
///   over all values of the type.
/// * `char`: Uniformly distributed over all Unicode scalar values, i.e. all
///   code points in the range `0...0x10_FFFF`, except for the range
///   `0xD800...0xDFFF` (the surrogate code points). This includes
///   unassigned/reserved code points.
/// * `bool`: Generates `false` or `true`, each with probability 0.5.
/// * Floating point types (`f32` and `f64`): Uniformly distributed in the
///   half-open range `[0, 1)`. See notes below.
/// * Wrapping integers (`Wrapping<T>`), besides the type identical to their
///   normal integer variants.
///
/// The `Standard` distribution also supports generation of the following
/// compound types where all component types are supported:
///
/// *   Tuples (up to 12 elements): each element is generated sequentially.
/// *   Arrays (up to 32 elements): each element is generated sequentially;
///     see also [`Rng::fill`] which supports arbitrary array length for integer
///     types and tends to be faster for `u32` and smaller types.
/// *   `Option<T>` first generates a `bool`, and if true generates and returns
///     `Some(value)` where `value: T`, otherwise returning `None`.
///
/// ## Custom implementations
///
/// The [`Standard`] distribution may be implemented for user types as follows:
///
/// ```
/// # #![allow(dead_code)]
/// use rand::Rng;
/// use rand::distributions::{Distribution, Standard};
///
/// struct MyF32 {
///     x: f32,
/// }
///
/// impl Distribution<MyF32> for Standard {
///     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> MyF32 {
///         MyF32 { x: rng.gen() }
///     }
/// }
/// ```
///
/// ## Example usage
/// ```
/// use rand::prelude::*;
/// use rand::distributions::Standard;
///
/// let val: f32 = StdRng::from_entropy().sample(Standard);
/// println!("f32 from [0, 1): {}", val);
/// ```
///
/// # Floating point implementation
/// The floating point implementations for `Standard` generate a random value in
/// the half-open interval `[0, 1)`, i.e. including 0 but not 1.
///
/// All values that can be generated are of the form `n * ε/2`. For `f32`
/// the 24 most significant random bits of a `u32` are used and for `f64` the
/// 53 most significant bits of a `u64` are used. The conversion uses the
/// multiplicative method: `(rng.gen::<$uty>() >> N) as $ty * (ε/2)`.
///
/// See also: [`Open01`] which samples from `(0, 1)`, [`OpenClosed01`] which
/// samples from `(0, 1]` and `Rng::gen_range(0..1)` which also samples from
/// `[0, 1)`. Note that `Open01` uses transmute-based methods which yield 1 bit
/// less precision but may perform faster on some architectures (on modern Intel
/// CPUs all methods have approximately equal performance).
///
/// [`Uniform`]: uniform::Uniform
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Standard;

#[cfg(test)]
mod tests {
    use super::{Distribution, Uniform};
    use crate::Rng;

    #[test]
    fn test_distributions_iter() {
        use crate::distributions::Open01;
        let mut rng = crate::test::rng(210);
        let distr = Open01;
        let mut iter = Distribution::<f32>::sample_iter(distr, &mut rng);
        let mut sum: f32 = 0.;
        for _ in 0..100 {
            sum += iter.next().unwrap();
        }
        assert!(sum > 0.);
    }

    #[test]
    fn test_make_an_iter() {
        fn ten_dice_rolls_other_than_five<'a, R: Rng>(
            rng: &'a mut R,
        ) -> impl Iterator<Item = i32> + 'a {
            Uniform::new_inclusive(1, 6)
                .sample_iter(rng)
                .filter(|x| *x != 5)
                .take(10)
        }

        let mut rng = crate::test::rng(211);
        let mut count = 0;
        for val in ten_dice_rolls_other_than_five(&mut rng) {
            assert!(val >= 1 && val <= 6 && val != 5);
            count += 1;
        }
        assert_eq!(count, 10);
    }
}
<commit_msg>Slightly improve test<commit_after>// Copyright 2018 Developers of the Rand project.
// Copyright 2013-2017 The Rust Project Developers.
//
// 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.

//! Generating random samples from probability distributions
//!
//! This module is the home of the [`Distribution`] trait and several of its
//! implementations. It is the workhorse behind some of the convenient
//! functionality of the [`Rng`] trait, e.g. [`Rng::gen`] and of course
//! [`Rng::sample`].
//!
//! Abstractly, a [probability distribution] describes the probability of
//! occurrence of each value in its sample space.
//!
//! More concretely, an implementation of `Distribution<T>` for type `X` is an
//! algorithm for choosing values from the sample space (a subset of `T`)
//! according to the distribution `X` represents, using an external source of
//! randomness (an RNG supplied to the `sample` function).
//!
//! A type `X` may implement `Distribution<T>` for multiple types `T`.
//! Any type implementing [`Distribution`] is stateless (i.e. immutable),
//! but it may have internal parameters set at construction time (for example,
//! [`Uniform`] allows specification of its sample space as a range within `T`).
//!
//!
//! # The `Standard` distribution
//!
//! The [`Standard`] distribution is important to mention. This is the
//! distribution used by [`Rng::gen`] and represents the "default" way to
//! produce a random value for many different types, including most primitive
//! types, tuples, arrays, and a few derived types. See the documentation of
//! [`Standard`] for more details.
//!
//! Implementing `Distribution<T>` for [`Standard`] for user types `T` makes it
//! possible to generate type `T` with [`Rng::gen`], and by extension also
//! with the [`random`] function.
//!
//! ## Random characters
//!
//! [`Alphanumeric`] is a simple distribution to sample random letters and
//! numbers of the `char` type; in contrast [`Standard`] may sample any valid
//! `char`.
//!
//!
//! # Uniform numeric ranges
//!
//! The [`Uniform`] distribution is more flexible than [`Standard`], but also
//! more specialised: it supports fewer target types, but allows the sample
//! space to be specified as an arbitrary range within its target type `T`.
//! Both [`Standard`] and [`Uniform`] are in some sense uniform distributions.
//!
//! Values may be sampled from this distribution using [`Rng::sample(Range)`] or
//! by creating a distribution object with [`Uniform::new`],
//! [`Uniform::new_inclusive`] or `From<Range>`. When the range limits are not
//! known at compile time it is typically faster to reuse an existing
//! `Uniform` object than to call [`Rng::sample(Range)`].
//!
//! User types `T` may also implement `Distribution<T>` for [`Uniform`],
//! although this is less straightforward than for [`Standard`] (see the
//! documentation in the [`uniform`] module). Doing so enables generation of
//! values of type `T` with  [`Rng::sample(Range)`].
//!
//! ## Open and half-open ranges
//!
//! There are surprisingly many ways to uniformly generate random floats. A
//! range between 0 and 1 is standard, but the exact bounds (open vs closed)
//! and accuracy differ. In addition to the [`Standard`] distribution Rand offers
//! [`Open01`] and [`OpenClosed01`]. See "Floating point implementation" section of
//! [`Standard`] documentation for more details.
//!
//! # Non-uniform sampling
//!
//! Sampling a simple true/false outcome with a given probability has a name:
//! the [`Bernoulli`] distribution (this is used by [`Rng::gen_bool`]).
//!
//! For weighted sampling from a sequence of discrete values, use the
//! [`weighted`] module.
//!
//! This crate no longer includes other non-uniform distributions; instead
//! it is recommended that you use either [`rand_distr`] or [`statrs`].
//!
//!
//! [probability distribution]: https://en.wikipedia.org/wiki/Probability_distribution
//! [`rand_distr`]: https://crates.io/crates/rand_distr
//! [`statrs`]: https://crates.io/crates/statrs

//! [`random`]: crate::random
//! [`rand_distr`]: https://crates.io/crates/rand_distr
//! [`statrs`]: https://crates.io/crates/statrs

use crate::Rng;
use core::iter;

pub use self::bernoulli::{Bernoulli, BernoulliError};
pub use self::float::{Open01, OpenClosed01};
pub use self::other::Alphanumeric;
#[doc(inline)] pub use self::uniform::Uniform;

#[cfg(feature = "alloc")]
pub use self::weighted_index::{WeightedError, WeightedIndex};

mod bernoulli;
pub mod uniform;

#[deprecated(since = "0.8.0", note = "use rand::distributions::{WeightedIndex, WeightedError} instead")]
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub mod weighted;
#[cfg(feature = "alloc")] mod weighted_index;

#[cfg(feature = "serde1")]
use serde::{Serialize, Deserialize};

mod float;
#[doc(hidden)]
pub mod hidden_export {
    pub use super::float::IntoFloat; // used by rand_distr
}
mod integer;
mod other;
mod utils;

/// Types (distributions) that can be used to create a random instance of `T`.
///
/// It is possible to sample from a distribution through both the
/// `Distribution` and [`Rng`] traits, via `distr.sample(&mut rng)` and
/// `rng.sample(distr)`. They also both offer the [`sample_iter`] method, which
/// produces an iterator that samples from the distribution.
///
/// All implementations are expected to be immutable; this has the significant
/// advantage of not needing to consider thread safety, and for most
/// distributions efficient state-less sampling algorithms are available.
///
/// Implementations are typically expected to be portable with reproducible
/// results when used with a PRNG with fixed seed; see the
/// [portability chapter](https://rust-random.github.io/book/portability.html)
/// of The Rust Rand Book. In some cases this does not apply, e.g. the `usize`
/// type requires different sampling on 32-bit and 64-bit machines.
///
/// [`sample_iter`]: Distribution::method.sample_iter
pub trait Distribution<T> {
    /// Generate a random value of `T`, using `rng` as the source of randomness.
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T;

    /// Create an iterator that generates random values of `T`, using `rng` as
    /// the source of randomness.
    ///
    /// Note that this function takes `self` by value. This works since
    /// `Distribution<T>` is impl'd for `&D` where `D: Distribution<T>`,
    /// however borrowing is not automatic hence `distr.sample_iter(...)` may
    /// need to be replaced with `(&distr).sample_iter(...)` to borrow or
    /// `(&*distr).sample_iter(...)` to reborrow an existing reference.
    ///
    /// # Example
    ///
    /// ```
    /// use rand::thread_rng;
    /// use rand::distributions::{Distribution, Alphanumeric, Uniform, Standard};
    ///
    /// let rng = thread_rng();
    ///
    /// // Vec of 16 x f32:
    /// let v: Vec<f32> = Standard.sample_iter(rng).take(16).collect();
    ///
    /// // String:
    /// let s: String = Alphanumeric.sample_iter(rng).take(7).map(char::from).collect();
    ///
    /// // Dice-rolling:
    /// let die_range = Uniform::new_inclusive(1, 6);
    /// let mut roll_die = die_range.sample_iter(rng);
    /// while roll_die.next().unwrap() != 6 {
    ///     println!("Not a 6; rolling again!");
    /// }
    /// ```
    fn sample_iter<R>(self, rng: R) -> DistIter<Self, R, T>
    where
        R: Rng,
        Self: Sized,
    {
        DistIter {
            distr: self,
            rng,
            phantom: ::core::marker::PhantomData,
        }
    }
}

impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T {
        (*self).sample(rng)
    }
}

/// An iterator that generates random values of `T` with distribution `D`,
/// using `R` as the source of randomness.
///
/// This `struct` is created by the [`sample_iter`] method on [`Distribution`].
/// See its documentation for more.
///
/// [`sample_iter`]: Distribution::sample_iter
#[derive(Debug)]
pub struct DistIter<D, R, T> {
    distr: D,
    rng: R,
    phantom: ::core::marker::PhantomData<T>,
}

impl<D, R, T> Iterator for DistIter<D, R, T>
where
    D: Distribution<T>,
    R: Rng,
{
    type Item = T;

    #[inline(always)]
    fn next(&mut self) -> Option<T> {
        // Here, self.rng may be a reference, but we must take &mut anyway.
        // Even if sample could take an R: Rng by value, we would need to do this
        // since Rng is not copyable and we cannot enforce that this is "reborrowable".
        Some(self.distr.sample(&mut self.rng))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (usize::max_value(), None)
    }
}

impl<D, R, T> iter::FusedIterator for DistIter<D, R, T>
where
    D: Distribution<T>,
    R: Rng,
{
}

#[cfg(features = "nightly")]
impl<D, R, T> iter::TrustedLen for DistIter<D, R, T>
where
    D: Distribution<T>,
    R: Rng,
{
}

/// A generic random value distribution, implemented for many primitive types.
/// Usually generates values with a numerically uniform distribution, and with a
/// range appropriate to the type.
///
/// ## Provided implementations
///
/// Assuming the provided `Rng` is well-behaved, these implementations
/// generate values with the following ranges and distributions:
///
/// * Integers (`i32`, `u32`, `isize`, `usize`, etc.): Uniformly distributed
///   over all values of the type.
/// * `char`: Uniformly distributed over all Unicode scalar values, i.e. all
///   code points in the range `0...0x10_FFFF`, except for the range
///   `0xD800...0xDFFF` (the surrogate code points). This includes
///   unassigned/reserved code points.
/// * `bool`: Generates `false` or `true`, each with probability 0.5.
/// * Floating point types (`f32` and `f64`): Uniformly distributed in the
///   half-open range `[0, 1)`. See notes below.
/// * Wrapping integers (`Wrapping<T>`), besides the type identical to their
///   normal integer variants.
///
/// The `Standard` distribution also supports generation of the following
/// compound types where all component types are supported:
///
/// *   Tuples (up to 12 elements): each element is generated sequentially.
/// *   Arrays (up to 32 elements): each element is generated sequentially;
///     see also [`Rng::fill`] which supports arbitrary array length for integer
///     types and tends to be faster for `u32` and smaller types.
/// *   `Option<T>` first generates a `bool`, and if true generates and returns
///     `Some(value)` where `value: T`, otherwise returning `None`.
///
/// ## Custom implementations
///
/// The [`Standard`] distribution may be implemented for user types as follows:
///
/// ```
/// # #![allow(dead_code)]
/// use rand::Rng;
/// use rand::distributions::{Distribution, Standard};
///
/// struct MyF32 {
///     x: f32,
/// }
///
/// impl Distribution<MyF32> for Standard {
///     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> MyF32 {
///         MyF32 { x: rng.gen() }
///     }
/// }
/// ```
///
/// ## Example usage
/// ```
/// use rand::prelude::*;
/// use rand::distributions::Standard;
///
/// let val: f32 = StdRng::from_entropy().sample(Standard);
/// println!("f32 from [0, 1): {}", val);
/// ```
///
/// # Floating point implementation
/// The floating point implementations for `Standard` generate a random value in
/// the half-open interval `[0, 1)`, i.e. including 0 but not 1.
///
/// All values that can be generated are of the form `n * ε/2`. For `f32`
/// the 24 most significant random bits of a `u32` are used and for `f64` the
/// 53 most significant bits of a `u64` are used. The conversion uses the
/// multiplicative method: `(rng.gen::<$uty>() >> N) as $ty * (ε/2)`.
///
/// See also: [`Open01`] which samples from `(0, 1)`, [`OpenClosed01`] which
/// samples from `(0, 1]` and `Rng::gen_range(0..1)` which also samples from
/// `[0, 1)`. Note that `Open01` uses transmute-based methods which yield 1 bit
/// less precision but may perform faster on some architectures (on modern Intel
/// CPUs all methods have approximately equal performance).
///
/// [`Uniform`]: uniform::Uniform
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Standard;

#[cfg(test)]
mod tests {
    use super::{Distribution, Uniform};
    use crate::Rng;

    #[test]
    fn test_distributions_iter() {
        use crate::distributions::Open01;
        let mut rng = crate::test::rng(210);
        let distr = Open01;
        let mut iter = Distribution::<f32>::sample_iter(distr, &mut rng);
        let mut sum: f32 = 0.;
        for _ in 0..100 {
            sum += iter.next().unwrap();
        }
        assert!(0. < sum && sum < 100.);
    }

    #[test]
    fn test_make_an_iter() {
        fn ten_dice_rolls_other_than_five<'a, R: Rng>(
            rng: &'a mut R,
        ) -> impl Iterator<Item = i32> + 'a {
            Uniform::new_inclusive(1, 6)
                .sample_iter(rng)
                .filter(|x| *x != 5)
                .take(10)
        }

        let mut rng = crate::test::rng(211);
        let mut count = 0;
        for val in ten_dice_rolls_other_than_five(&mut rng) {
            assert!(val >= 1 && val <= 6 && val != 5);
            count += 1;
        }
        assert_eq!(count, 10);
    }
}
<|endoftext|>


<commit_before>fn merge<T>(l1: Vec<T>, l2: Vec<T>) -> Vec<T> {}
<commit_msg>finish rust version<commit_after>fn merge(l1: Vec<i32>, l2: Vec<i32>) -> Vec<i32> {
    //println!("{:?} \n {:?} \n\n", l1, l2);
    if l1.len() == 0 {
        l2
    } else if l1[0] < l2[0] {
        let mut a = vec![l1[0]];
        let b = l1[1..].to_vec();
        a.extend(merge(b, l2));
        a
    } else {
        let mut a = vec![l2[0]];
        let b = l2[1..].to_vec();
        a.extend(merge(b, l1));
        a
    }
}

fn merege_out(l: Vec<i32>) -> Vec<i32> {
    let half = l.len() / 2;
    if l.len() >= 3 {
        return merge(
            merege_out(l[0..half].to_vec()),
            merege_out(l[half..].to_vec()),
        );
    } else {
        return merge(l[0..half].to_vec(), l[half..].to_vec());
    }
}

fn main() {
    let a = vec![
        1,
        2,
        3,
        2,
        4,
        3,
        2,
        4,
        2,
        1,
        3,
        4,
        3,
        2,
        1,
        2,
        4,
        5,
        6,
        7,
        7,
        5,
        4,
        5,
        4,
        2,
        2,
    ];
    println!("{:?}", merege_out(a));
}
<|endoftext|>


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

use anyhow::Context;
use anyhow::Result;
use aptos_node_checker_lib::EvaluationSummary;
use aptos_sdk::rest_client::Client as AptosClient;
use aptos_sdk::types::account_address::AccountAddress;
use aptos_sdk::types::account_config::CORE_CODE_ADDRESS;
use aptos_sdk::types::network_address::NetworkAddress;
use aptos_sdk::types::on_chain_config::ValidatorSet;
use aptos_sdk::types::validator_info::ValidatorInfo;
use clap::Parser;
use log::{debug, info};
use reqwest::Client as ReqwestClient;
use reqwest::Url;
use serde::Serialize;
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
use std::time::SystemTime;
use std::time::UNIX_EPOCH;
use tokio::sync::Semaphore;

use crate::helpers::extract_network_address;

// Unfortunately we don't have any way, on chain or not, to know what the API
// port is, so we just assume it is one of these. If their VFN is inaccessible at,
// any of these ports, e.g. because it runs on 7777 and they have an LB not registered
// on chain in front of it that listens at 80 just for the API, we're just out of luck.
// If we get this kind of information from elsewhere at some point, we could look at
// joining it here.
pub const API_PORTS: &[u16] = &[80, 8080, 443];

#[derive(Debug, Parser)]
pub struct CheckArgs {
    /// Address of any node (of any type) connected to the network you want
    /// to evaluate.
    #[clap(long)]
    pub node_address: Url,

    /// Address where NHC is running.
    #[clap(long)]
    pub nhc_address: Url,

    /// Baseline config to use when talking to NHC.
    #[clap(long)]
    pub nhc_baseline_config_name: String,

    /// How long to wait when talking to NHC. The check should be quick unless
    /// we're using the TPS evaluator.
    #[clap(long, default_value_t = 60)]
    pub nhc_timeout_secs: u64,

    /// Max number of requests to NHC we can have running concurrently.
    #[clap(long, default_value_t = 4)]
    pub max_concurrent_nhc_requests: u16,

    /// Only run against these account addresses.
    #[clap(long)]
    pub account_address_allowlist: Vec<String>,
}

#[derive(Debug, Serialize)]
pub struct SingleCheck {
    pub result: SingleCheckResult,
    pub timestamp: Duration,
    pub vfn_address: Option<NetworkAddress>,
}

impl SingleCheck {
    pub fn new(result: SingleCheckResult, vfn_address: Option<NetworkAddress>) -> Self {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .expect("Failed to get current time");
        Self {
            result,
            timestamp: now,
            vfn_address,
        }
    }
}

/// We use this struct to capture the result of checking a node, or the lack thereof.
#[derive(Debug, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum SingleCheckResult {
    /// The node was successfully checked. Note: The evaulation itself could
    /// indicate, a problem with the node, this just states that we were able
    /// to check the node sucessfully with NHC.
    Success(EvaluationSummary),

    /// Something went wrong with checking the node.
    Failure(SingleCheckFailure),

    /// The account does not have a VFN registered on chain.
    NoVfnRegistered(NoVfnRegistered),
}

#[derive(Debug, Serialize)]
pub struct SingleCheckFailure {
    pub message: String,
    pub code: SingleCheckFailureCode,
}

impl SingleCheckFailure {
    pub fn new(message: String, code: SingleCheckFailureCode) -> Self {
        Self { message, code }
    }
}

#[derive(Debug, PartialEq, Serialize)]
pub enum SingleCheckFailureCode {
    // The network address in the validator set config cannot be used for
    // querying NHC.
    UnsupportedNetworkAddressType,

    // Something went wrong when sending / receiving the request.
    RequestFlowError,

    // The response from NHC was not a 200, implying a problem with NHC.
    ResponseNot200,

    // The response from NHC couldn't be deserialized.
    CouldNotDeserializeResponse,

    // NHC returned an evaluation that indicates that the API port is closed.
    ApiPortClosed,
}

// This is necessary because we can't just use a unit type for this enum variant.
#[derive(Debug, Serialize)]
pub struct NoVfnRegistered;

/// Get all the on chain validator info.
pub async fn get_validator_info(node_address: Url) -> Result<Vec<ValidatorInfo>> {
    let client = AptosClient::new(node_address.clone());
    let response = client
        .get_account_resource_bcs::<ValidatorSet>(CORE_CODE_ADDRESS, "0x1::stake::ValidatorSet")
        .await?;
    let active_validators = response.into_inner().active_validators;
    info!(
        "Pulled {} active validators. First: {}. Last: {}",
        active_validators.len(),
        active_validators.first().unwrap().account_address(),
        active_validators.last().unwrap().account_address()
    );
    Ok(active_validators)
}

/// Check all VFNs from the validator set.
pub async fn check_vfns(
    nhc_client: &ReqwestClient,
    check_args: &CheckArgs,
    validator_infos: Vec<ValidatorInfo>,
) -> Result<HashMap<AccountAddress, Vec<SingleCheck>>> {
    let mut nhc_address = check_args.nhc_address.clone();
    nhc_address.set_path("/check_node");

    let semaphore = Arc::new(Semaphore::new(
        check_args.max_concurrent_nhc_requests as usize,
    ));

    let mut nhc_responses = HashMap::new();
    let mut futures = vec![];
    for validator_info in validator_infos {
        let account_address = validator_info.account_address();
        if !check_args.account_address_allowlist.is_empty()
            && !check_args
                .account_address_allowlist
                .contains(&account_address.to_string())
        {
            continue;
        }
        let vfn_addresses = validator_info
            .config()
            .fullnode_network_addresses()
            .context("Failed to deserialize VFN network addresses")?;
        if vfn_addresses.is_empty() {
            nhc_responses
                .entry(*account_address)
                .or_insert_with(Vec::new)
                .push(SingleCheck::new(
                    SingleCheckResult::NoVfnRegistered(NoVfnRegistered),
                    None,
                ));
            continue;
        }
        for vfn_address in vfn_addresses.into_iter() {
            let single_check_future = check_single_vfn_wrapper(
                *account_address,
                nhc_client,
                &nhc_address,
                &check_args.nhc_baseline_config_name,
                vfn_address,
                semaphore.clone(),
            );
            futures.push(single_check_future);
        }
    }
    let checks = futures::future::join_all(futures).await;
    for (account_address, vfn_address, single_check_result) in checks {
        match single_check_result {
            SingleCheckResult::Success(_) => {
                info!("NHC returned a 200 for {}", vfn_address);
            }
            SingleCheckResult::Failure(_) => {
                info!("NHC returned a non 200 for {}", vfn_address);
            }
            SingleCheckResult::NoVfnRegistered(_) => panic!("Shouldn't be possible"),
        }
        nhc_responses
            .entry(account_address)
            .or_insert_with(Vec::new)
            .push(SingleCheck::new(single_check_result, Some(vfn_address)));
    }
    Ok(nhc_responses)
}

// This just exists to make joining futures easy.
async fn check_single_vfn_wrapper(
    account_address: AccountAddress,
    nhc_client: &ReqwestClient,
    nhc_address: &Url,
    nhc_baseline_config_name: &str,
    vfn_address: NetworkAddress,
    semaphore: Arc<Semaphore>,
) -> (AccountAddress, NetworkAddress, SingleCheckResult) {
    let _permit = semaphore.acquire().await.unwrap();
    info!("Checking VFNs for account {}", account_address,);
    (
        account_address,
        vfn_address.clone(),
        check_single_vfn(
            nhc_client,
            nhc_address,
            nhc_baseline_config_name,
            vfn_address,
        )
        .await,
    )
}

/// Make a query to NHC for a single VFN. This may result in multiple queries to
/// NHC as we try different API ports.
async fn check_single_vfn(
    nhc_client: &ReqwestClient,
    nhc_address: &Url,
    nhc_baseline_config_name: &str,
    vfn_address: NetworkAddress,
) -> SingleCheckResult {
    // Get a string representation of the vfn address if possible.
    let vfn_url_string = match extract_network_address(&vfn_address) {
        Ok(vfn_url_string) => vfn_url_string,
        Err(e) => {
            return SingleCheckResult::Failure(SingleCheckFailure::new(
                format!("Network address was an unsupported type: {}", e),
                SingleCheckFailureCode::UnsupportedNetworkAddressType,
            ));
        }
    };

    info!("Checking VFN {}", vfn_url_string);

    let mut index = 0;
    loop {
        let single_check_result = check_single_vfn_one_api_port(
            nhc_client,
            nhc_address,
            nhc_baseline_config_name,
            &vfn_url_string,
            API_PORTS[index],
        )
        .await;
        // If the response was a success, return.
        if let SingleCheckResult::Success(_) = &single_check_result {
            break single_check_result;
        }
        // If the response was a failure, return unless it was because it
        // seems like the API wasn't open, in which case we keep looping
        // to try another port.
        if let SingleCheckResult::Failure(failure) = &single_check_result {
            if failure.code != SingleCheckFailureCode::ApiPortClosed {
                break single_check_result;
            }
        }
        // We've tried every port, return the last result.
        if index == API_PORTS.len() - 1 {
            break single_check_result;
        }
        index += 1;
    }
}

/// Check NHC just once, with a single VFN for a single API port.
async fn check_single_vfn_one_api_port(
    nhc_client: &ReqwestClient,
    nhc_address: &Url,
    nhc_baseline_config_name: &str,
    vfn_url_string: &str,
    api_port: u16,
) -> SingleCheckResult {
    // Build up query params.
    let mut params = HashMap::new();
    let api_port_string = api_port.to_string();
    params.insert("node_url", vfn_url_string);
    params.insert("api_port", &api_port_string);
    params.insert("baseline_configuration_name", nhc_baseline_config_name);

    debug!(
        "Querying NHC at address: {}:{}",
        vfn_url_string, api_port_string
    );

    // Send the request and parse the response.
    let response = match nhc_client
        .get(nhc_address.clone())
        .query(&params)
        .send()
        .await
    {
        Ok(response) => response,
        Err(e) => {
            return SingleCheckResult::Failure(SingleCheckFailure::new(
                format!("Error with request flow to NHC: {:#}", e),
                SingleCheckFailureCode::RequestFlowError,
            ));
        }
    };

    // Handle the case where NHC itself throws an error (as opposed to a success
    // response from NHC indicating evaluation where the node performed poorly).
    if let Err(e) = response.error_for_status_ref() {
        return SingleCheckResult::Failure(SingleCheckFailure::new(
            format!("{:#}: {:?}", e, response.text().await),
            SingleCheckFailureCode::ResponseNot200,
        ));
    };

    // Confirm the response is valid JSON.
    let evaluation_summary = match response.json::<EvaluationSummary>().await {
        Ok(evaluation_summary) => evaluation_summary,
        Err(e) => {
            return SingleCheckResult::Failure(SingleCheckFailure::new(
                format!("{:#}", e),
                SingleCheckFailureCode::CouldNotDeserializeResponse,
            ))
        }
    };

    // Check specifically if the API port is closed.
    if evaluation_summary
        .evaluation_results
        .iter()
        .any(|evaluation_result| {
            evaluation_result.evaluator_name == "index_response" && evaluation_result.score == 0
        })
    {
        return SingleCheckResult::Failure(SingleCheckFailure::new(
            format!(
                "Couldn't talk to API on any of the expected ports {:?}: {:?}",
                API_PORTS, evaluation_summary
            ),
            SingleCheckFailureCode::ApiPortClosed,
        ));
    }

    SingleCheckResult::Success(evaluation_summary)
}
<commit_msg>[vfn-check-client] Output address of node in success case (#3652)<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use anyhow::Context;
use anyhow::Result;
use aptos_node_checker_lib::EvaluationSummary;
use aptos_sdk::rest_client::Client as AptosClient;
use aptos_sdk::types::account_address::AccountAddress;
use aptos_sdk::types::account_config::CORE_CODE_ADDRESS;
use aptos_sdk::types::network_address::NetworkAddress;
use aptos_sdk::types::on_chain_config::ValidatorSet;
use aptos_sdk::types::validator_info::ValidatorInfo;
use clap::Parser;
use log::{debug, info};
use reqwest::Client as ReqwestClient;
use reqwest::Url;
use serde::Serialize;
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
use std::time::SystemTime;
use std::time::UNIX_EPOCH;
use tokio::sync::Semaphore;

use crate::helpers::extract_network_address;

// Unfortunately we don't have any way, on chain or not, to know what the API
// port is, so we just assume it is one of these. If their VFN is inaccessible at,
// any of these ports, e.g. because it runs on 7777 and they have an LB not registered
// on chain in front of it that listens at 80 just for the API, we're just out of luck.
// If we get this kind of information from elsewhere at some point, we could look at
// joining it here.
pub const API_PORTS: &[u16] = &[80, 8080, 443];

#[derive(Debug, Parser)]
pub struct CheckArgs {
    /// Address of any node (of any type) connected to the network you want
    /// to evaluate.
    #[clap(long)]
    pub node_address: Url,

    /// Address where NHC is running.
    #[clap(long)]
    pub nhc_address: Url,

    /// Baseline config to use when talking to NHC.
    #[clap(long)]
    pub nhc_baseline_config_name: String,

    /// How long to wait when talking to NHC. The check should be quick unless
    /// we're using the TPS evaluator.
    #[clap(long, default_value_t = 60)]
    pub nhc_timeout_secs: u64,

    /// Max number of requests to NHC we can have running concurrently.
    #[clap(long, default_value_t = 4)]
    pub max_concurrent_nhc_requests: u16,

    /// Only run against these account addresses.
    #[clap(long)]
    pub account_address_allowlist: Vec<String>,
}

#[derive(Debug, Serialize)]
pub struct SingleCheck {
    pub result: SingleCheckResult,
    pub timestamp: Duration,
    pub vfn_address: Option<NetworkAddress>,
}

impl SingleCheck {
    pub fn new(result: SingleCheckResult, vfn_address: Option<NetworkAddress>) -> Self {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .expect("Failed to get current time");
        Self {
            result,
            timestamp: now,
            vfn_address,
        }
    }
}

/// We use this struct to capture the result of checking a node, or the lack thereof.
#[derive(Debug, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum SingleCheckResult {
    /// The node was successfully checked. Note: The evaulation itself could
    /// indicate, a problem with the node, this just states that we were able
    /// to check the node sucessfully with NHC.
    Success(SingleCheckSuccess),

    /// Something went wrong with checking the node.
    Failure(SingleCheckFailure),

    /// The account does not have a VFN registered on chain.
    NoVfnRegistered(NoVfnRegistered),
}

#[derive(Debug, Serialize)]
pub struct SingleCheckSuccess {
    /// The evaluation summary returned by NHC. This doesn't necessarily imply
    /// that the node passed the evaluation, just that an evaluation was returned
    /// successfully and it passed the API available check.
    pub evaluation_summary: EvaluationSummary,

    /// This is the address that we used to get this successful evaluation.
    /// This is presented in a normal URL format, not the NetworkAddress
    /// representation. Example value for this field: http://65.109.17.29:8080.
    /// Note, sometimes the address we started with was a DNS name, and we resolved
    /// it to an IP address. As such, this IP address may become incorrect down
    /// the line. In that case, refer to vfn_address in SingleCheck, or just
    /// run this tool again.
    pub vfn_address_url: String,
}

impl SingleCheckSuccess {
    pub fn new(evaluation_summary: EvaluationSummary, vfn_address_url: String) -> Self {
        Self {
            evaluation_summary,
            vfn_address_url,
        }
    }
}

#[derive(Debug, Serialize)]
pub struct SingleCheckFailure {
    pub message: String,
    pub code: SingleCheckFailureCode,
}

impl SingleCheckFailure {
    pub fn new(message: String, code: SingleCheckFailureCode) -> Self {
        Self { message, code }
    }
}

#[derive(Debug, PartialEq, Serialize)]
pub enum SingleCheckFailureCode {
    // The network address in the validator set config cannot be used for
    // querying NHC.
    UnsupportedNetworkAddressType,

    // Something went wrong when sending / receiving the request.
    RequestFlowError,

    // The response from NHC was not a 200, implying a problem with NHC.
    ResponseNot200,

    // The response from NHC couldn't be deserialized.
    CouldNotDeserializeResponse,

    // NHC returned an evaluation that indicates that the API port is closed.
    ApiPortClosed,
}

// This is necessary because we can't just use a unit type for this enum variant.
#[derive(Debug, Serialize)]
pub struct NoVfnRegistered;

/// Get all the on chain validator info.
pub async fn get_validator_info(node_address: Url) -> Result<Vec<ValidatorInfo>> {
    let client = AptosClient::new(node_address.clone());
    let response = client
        .get_account_resource_bcs::<ValidatorSet>(CORE_CODE_ADDRESS, "0x1::stake::ValidatorSet")
        .await?;
    let active_validators = response.into_inner().active_validators;
    info!(
        "Pulled {} active validators. First: {}. Last: {}",
        active_validators.len(),
        active_validators.first().unwrap().account_address(),
        active_validators.last().unwrap().account_address()
    );
    Ok(active_validators)
}

/// Check all VFNs from the validator set.
pub async fn check_vfns(
    nhc_client: &ReqwestClient,
    check_args: &CheckArgs,
    validator_infos: Vec<ValidatorInfo>,
) -> Result<HashMap<AccountAddress, Vec<SingleCheck>>> {
    let mut nhc_address = check_args.nhc_address.clone();
    nhc_address.set_path("/check_node");

    let semaphore = Arc::new(Semaphore::new(
        check_args.max_concurrent_nhc_requests as usize,
    ));

    let mut nhc_responses = HashMap::new();
    let mut futures = vec![];
    for validator_info in validator_infos {
        let account_address = validator_info.account_address();
        if !check_args.account_address_allowlist.is_empty()
            && !check_args
                .account_address_allowlist
                .contains(&account_address.to_string())
        {
            continue;
        }
        let vfn_addresses = validator_info
            .config()
            .fullnode_network_addresses()
            .context("Failed to deserialize VFN network addresses")?;
        if vfn_addresses.is_empty() {
            nhc_responses
                .entry(*account_address)
                .or_insert_with(Vec::new)
                .push(SingleCheck::new(
                    SingleCheckResult::NoVfnRegistered(NoVfnRegistered),
                    None,
                ));
            continue;
        }
        for vfn_address in vfn_addresses.into_iter() {
            let single_check_future = check_single_vfn_wrapper(
                *account_address,
                nhc_client,
                &nhc_address,
                &check_args.nhc_baseline_config_name,
                vfn_address,
                semaphore.clone(),
            );
            futures.push(single_check_future);
        }
    }
    let checks = futures::future::join_all(futures).await;
    for (account_address, vfn_address, single_check_result) in checks {
        match single_check_result {
            SingleCheckResult::Success(_) => {
                info!("NHC returned a 200 for {}", vfn_address);
            }
            SingleCheckResult::Failure(_) => {
                info!("NHC returned a non 200 for {}", vfn_address);
            }
            SingleCheckResult::NoVfnRegistered(_) => panic!("Shouldn't be possible"),
        }
        nhc_responses
            .entry(account_address)
            .or_insert_with(Vec::new)
            .push(SingleCheck::new(single_check_result, Some(vfn_address)));
    }
    Ok(nhc_responses)
}

// This just exists to make joining futures easy.
async fn check_single_vfn_wrapper(
    account_address: AccountAddress,
    nhc_client: &ReqwestClient,
    nhc_address: &Url,
    nhc_baseline_config_name: &str,
    vfn_address: NetworkAddress,
    semaphore: Arc<Semaphore>,
) -> (AccountAddress, NetworkAddress, SingleCheckResult) {
    let _permit = semaphore.acquire().await.unwrap();
    info!("Checking VFNs for account {}", account_address,);
    (
        account_address,
        vfn_address.clone(),
        check_single_vfn(
            nhc_client,
            nhc_address,
            nhc_baseline_config_name,
            vfn_address,
        )
        .await,
    )
}

/// Make a query to NHC for a single VFN. This may result in multiple queries to
/// NHC as we try different API ports.
async fn check_single_vfn(
    nhc_client: &ReqwestClient,
    nhc_address: &Url,
    nhc_baseline_config_name: &str,
    vfn_address: NetworkAddress,
) -> SingleCheckResult {
    // Get a string representation of the vfn address if possible.
    let vfn_url_string = match extract_network_address(&vfn_address) {
        Ok(vfn_url_string) => vfn_url_string,
        Err(e) => {
            return SingleCheckResult::Failure(SingleCheckFailure::new(
                format!("Network address was an unsupported type: {}", e),
                SingleCheckFailureCode::UnsupportedNetworkAddressType,
            ));
        }
    };

    info!("Checking VFN {}", vfn_url_string);

    let mut index = 0;
    loop {
        let single_check_result = check_single_vfn_one_api_port(
            nhc_client,
            nhc_address,
            nhc_baseline_config_name,
            &vfn_url_string,
            API_PORTS[index],
        )
        .await;
        // If the response was a success, return.
        if let SingleCheckResult::Success(_) = &single_check_result {
            break single_check_result;
        }
        // If the response was a failure, return unless it was because it
        // seems like the API wasn't open, in which case we keep looping
        // to try another port.
        if let SingleCheckResult::Failure(failure) = &single_check_result {
            if failure.code != SingleCheckFailureCode::ApiPortClosed {
                break single_check_result;
            }
        }
        // We've tried every port, return the last result.
        if index == API_PORTS.len() - 1 {
            break single_check_result;
        }
        index += 1;
    }
}

/// Check NHC just once, with a single VFN for a single API port.
async fn check_single_vfn_one_api_port(
    nhc_client: &ReqwestClient,
    nhc_address: &Url,
    nhc_baseline_config_name: &str,
    vfn_url_string: &str,
    api_port: u16,
) -> SingleCheckResult {
    // Build up query params.
    let mut params = HashMap::new();
    let api_port_string = api_port.to_string();
    params.insert("node_url", vfn_url_string);
    params.insert("api_port", &api_port_string);
    params.insert("baseline_configuration_name", nhc_baseline_config_name);

    let address_single_string = format!("{}:{}", vfn_url_string, api_port_string);
    debug!("Querying NHC at address: {}", address_single_string);

    // Send the request and parse the response.
    let response = match nhc_client
        .get(nhc_address.clone())
        .query(&params)
        .send()
        .await
    {
        Ok(response) => response,
        Err(e) => {
            return SingleCheckResult::Failure(SingleCheckFailure::new(
                format!("Error with request flow to NHC: {:#}", e),
                SingleCheckFailureCode::RequestFlowError,
            ));
        }
    };

    // Handle the case where NHC itself throws an error (as opposed to a success
    // response from NHC indicating evaluation where the node performed poorly).
    if let Err(e) = response.error_for_status_ref() {
        return SingleCheckResult::Failure(SingleCheckFailure::new(
            format!("{:#}: {:?}", e, response.text().await),
            SingleCheckFailureCode::ResponseNot200,
        ));
    };

    // Confirm the response is valid JSON.
    let evaluation_summary = match response.json::<EvaluationSummary>().await {
        Ok(evaluation_summary) => evaluation_summary,
        Err(e) => {
            return SingleCheckResult::Failure(SingleCheckFailure::new(
                format!("{:#}", e),
                SingleCheckFailureCode::CouldNotDeserializeResponse,
            ))
        }
    };

    // Check specifically if the API port is closed.
    if evaluation_summary
        .evaluation_results
        .iter()
        .any(|evaluation_result| {
            evaluation_result.evaluator_name == "index_response" && evaluation_result.score == 0
        })
    {
        return SingleCheckResult::Failure(SingleCheckFailure::new(
            format!(
                "Couldn't talk to API on any of the expected ports {:?}: {:?}",
                API_PORTS, evaluation_summary
            ),
            SingleCheckFailureCode::ApiPortClosed,
        ));
    }

    SingleCheckResult::Success(SingleCheckSuccess::new(
        evaluation_summary,
        address_single_string,
    ))
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Taxicab_numbers
use std::collections::PriorityQueue;
use std::num::pow;

/// A type to represent a pair-sum of cubes.
/// value = a^3 + b^3
#[deriving(PartialEq, Eq)]
struct SumCubes {
    a: u64,
    b: u64,
    value: u64,
}

impl SumCubes {
    fn new(a: u64, b: u64) -> SumCubes {
        SumCubes{ value: pow(a, 3) + pow(b, 3), a: a, b: b }
    }
}

impl PartialOrd for SumCubes {
    fn partial_cmp(&self, other: &SumCubes) -> Option<Ordering> {
        // Comparison is reversed to make PriorityQueue behave like a min-heap
        (other.value, other.a, other.b).partial_cmp(&(self.value, self.a, self.b))
    }
}

impl Ord for SumCubes {
    fn cmp(&self, other: &SumCubes) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

/// An iterator through all Taxicab numbers
struct TaxicabNumbers {
    // Use a priority queue to iterate through sums
    // of cubes efficiently in increasing order
    pq: PriorityQueue<SumCubes>,
}

impl TaxicabNumbers {
    fn new() -> TaxicabNumbers {
        let mut res = TaxicabNumbers{ pq: PriorityQueue::new() };
        res.pq.push(SumCubes::new(1, 1)); // Start with 1^3 + 1^3
        res
    }
}

impl Iterator<Vec<SumCubes>> for TaxicabNumbers {
    fn next(&mut self) -> Option<Vec<SumCubes>> {
        let mut ways = Vec::new();      // All the ways we can express the current
                                        // value as a sum of cubes
        ways.push(SumCubes::new(0, 0)); // Just a sentinel value

        loop {
            let nxt = self.pq.pop().unwrap();
            if nxt.value == ways[0].value {
                // If the next sum is the same as the current one,
                // then we found another way to express the current value
                ways.push(nxt);
            } else if ways.len() > 1 {
                // If we can express the current value in more than one ways,
                // then it's a Taxicab number
                self.pq.push(nxt);
                return Some(ways);
            } else {
                ways.clear();
                ways.push(nxt);
            }

            // Populate the priority queue with more sums
            self.pq.push(SumCubes::new(nxt.a+1, nxt.b));
            if nxt.a == nxt.b {
                self.pq.push(SumCubes::new(nxt.a+1, nxt.b+1));
            }
        }
    }
}

#[cfg(not(test))]
fn main() {
    use std::iter::count;
    let numbers = TaxicabNumbers::new();
    for (at, ways) in count(1u, 1).zip(numbers.take(2006))
                                  .filter(|&(at, _)| at <= 25 || at >= 2000) {
        print!("{:>4u}:{:>10u}", at, ways[0].value);
        for &SumCubes{ a, b, value } in ways.iter() {
            print!(" = {:>4u}^3 + {:>4u}^3", a, b);
        }
        print!("\n");
    }
}

#[test]
fn test_taxicab_numbers() {
    // A001235 on OEIS
    let seq = [1729u64,4104,13832,20683,32832,39312,40033,46683,
               64232,65728,110656,110808,134379,149389,165464,
               171288,195841,216027,216125,262656,314496,320264,
               327763,373464,402597,439101,443889,513000,513856,
               515375,525824,558441,593047,684019,704977];

    for (&expected, ways) in seq.iter().zip(TaxicabNumbers::new()) {
        assert!(ways.len() > 1);
        for &SumCubes{value, ..} in ways.iter() {
            assert_eq!(value, expected);
        }
    }
}

<commit_msg>Use enumerate instead of count/zip in Taxicab numbers<commit_after>// http://rosettacode.org/wiki/Taxicab_numbers
use std::collections::PriorityQueue;
use std::num::pow;

/// A type to represent a pair-sum of cubes.
/// value = a^3 + b^3
#[deriving(PartialEq, Eq)]
struct SumCubes {
    a: u64,
    b: u64,
    value: u64,
}

impl SumCubes {
    fn new(a: u64, b: u64) -> SumCubes {
        SumCubes{ value: pow(a, 3) + pow(b, 3), a: a, b: b }
    }
}

impl PartialOrd for SumCubes {
    fn partial_cmp(&self, other: &SumCubes) -> Option<Ordering> {
        // Comparison is reversed to make PriorityQueue behave like a min-heap
        (other.value, other.a, other.b).partial_cmp(&(self.value, self.a, self.b))
    }
}

impl Ord for SumCubes {
    fn cmp(&self, other: &SumCubes) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

/// An iterator through all Taxicab numbers
struct TaxicabNumbers {
    // Use a priority queue to iterate through sums
    // of cubes efficiently in increasing order
    pq: PriorityQueue<SumCubes>,
}

impl TaxicabNumbers {
    fn new() -> TaxicabNumbers {
        let mut res = TaxicabNumbers{ pq: PriorityQueue::new() };
        res.pq.push(SumCubes::new(1, 1)); // Start with 1^3 + 1^3
        res
    }
}

impl Iterator<Vec<SumCubes>> for TaxicabNumbers {
    fn next(&mut self) -> Option<Vec<SumCubes>> {
        let mut ways = Vec::new();      // All the ways we can express the current
                                        // value as a sum of cubes
        ways.push(SumCubes::new(0, 0)); // Just a sentinel value

        loop {
            let nxt = self.pq.pop().unwrap();
            if nxt.value == ways[0].value {
                // If the next sum is the same as the current one,
                // then we found another way to express the current value
                ways.push(nxt);
            } else if ways.len() > 1 {
                // If we can express the current value in more than one ways,
                // then it's a Taxicab number
                self.pq.push(nxt);
                return Some(ways);
            } else {
                ways.clear();
                ways.push(nxt);
            }

            // Populate the priority queue with more sums
            self.pq.push(SumCubes::new(nxt.a+1, nxt.b));
            if nxt.a == nxt.b {
                self.pq.push(SumCubes::new(nxt.a+1, nxt.b+1));
            }
        }
    }
}

#[cfg(not(test))]
fn main() {
    let numbers = TaxicabNumbers::new();
    for (at, ways) in numbers.take(2006).enumerate()
                             .filter(|&(at, _)| at + 1 <= 25 || at + 1 >= 2000) {
        print!("{:>4u}:{:>10u}", at + 1, ways[0].value);
        for &SumCubes{ a, b, value } in ways.iter() {
            print!(" = {:>4u}^3 + {:>4u}^3", a, b);
        }
        print!("\n");
    }
}

#[test]
fn test_taxicab_numbers() {
    // A001235 on OEIS
    let seq = [1729u64,4104,13832,20683,32832,39312,40033,46683,
               64232,65728,110656,110808,134379,149389,165464,
               171288,195841,216027,216125,262656,314496,320264,
               327763,373464,402597,439101,443889,513000,513856,
               515375,525824,558441,593047,684019,704977];

    for (&expected, ways) in seq.iter().zip(TaxicabNumbers::new()) {
        assert!(ways.len() > 1);
        for &SumCubes{value, ..} in ways.iter() {
            assert_eq!(value, expected);
        }
    }
}

<|endoftext|>


<commit_before>//! A macro for writing HTML templates.
//!
//! This documentation only describes the runtime API. For a general
//! guide, check out the [book] instead.
//!
//! [book]: http://lfairy.gitbooks.io/maud/content/

#![feature(io)]

use std::fmt;
use std::io;

/// Escapes an HTML value.
pub fn escape(s: &str) -> String {
    use std::fmt::Write;
    let mut buf = String::new();
    rt::Escaper { inner: &mut buf }.write_str(s).unwrap();
    buf
}

/// A block of HTML markup, as returned by the `html!` macro.
///
/// Use `.to_string()` to convert it to a `String`, or `.render()` to
/// write it directly to a handle.
pub struct Markup<F> {
    callback: F,
}

impl<F> Markup<F> where F: Fn(&mut fmt::Write) -> fmt::Result {
    /// Renders the markup to a `std::io::Write`.
    pub fn render<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
        struct Adaptor<'a, W: ?Sized + 'a> {
            inner: &'a mut W,
            error: io::Result<()>,
        }

        impl<'a, W: ?Sized + io::Write> fmt::Write for Adaptor<'a, W> {
            fn write_str(&mut self, s: &str) -> fmt::Result {
                match self.inner.write_all(s.as_bytes()) {
                    Ok(()) => Ok(()),
                    Err(e) => {
                        self.error = Err(e);
                        Err(fmt::Error)
                    },
                }
            }
        }

        let mut output = Adaptor { inner: w, error: Ok(()) };
        match self.render_fmt(&mut output) {
            Ok(()) => Ok(()),
            Err(_) => output.error,
        }
    }

    /// Renders the markup to a `std::fmt::Write`.
    pub fn render_fmt(&self, w: &mut fmt::Write) -> fmt::Result {
        (self.callback)(w)
    }
}

impl<F> ToString for Markup<F> where F: Fn(&mut fmt::Write) -> fmt::Result {
    fn to_string(&self) -> String {
        let mut buf = String::new();
        self.render_fmt(&mut buf).unwrap();
        buf
    }
}

/// Internal functions used by the `maud_macros` package. You should
/// never need to call these directly.
#[doc(hidden)]
pub mod rt {
    use std::fmt;
    use super::Markup;

    #[inline]
    pub fn make_markup<F>(f: F) -> Markup<F>
        where F: Fn(&mut fmt::Write) -> fmt::Result
    {
        Markup { callback: f }
    }

    /// rustc is a butt and doesn't let us quote macro invocations
    /// directly. So we factor the `write!` call into a separate
    /// function and use that instead.
    ///
    /// See <https://github.com/rust-lang/rust/issues/16617>
    #[inline]
    pub fn write_fmt<T: fmt::Display>(w: &mut fmt::Write, value: T) -> fmt::Result {
        write!(w, "{}", value)
    }

    pub struct Escaper<'a, 'b: 'a> {
        pub inner: &'a mut (fmt::Write + 'b),
    }

    impl<'a, 'b> fmt::Write for Escaper<'a, 'b> {
        fn write_str(&mut self, s: &str) -> fmt::Result {
            for c in s.chars() {
                try!(match c {
                    '&' => self.inner.write_str("&"),
                    '<' => self.inner.write_str("<"),
                    '>' => self.inner.write_str(">"),
                    '"' => self.inner.write_str("""),
                    '\'' => self.inner.write_str("'"),
                    _ => write!(self.inner, "{}", c),
                });
            }
            Ok(())
        }
    }
}
<commit_msg>Remove #[feature(io)]<commit_after>//! A macro for writing HTML templates.
//!
//! This documentation only describes the runtime API. For a general
//! guide, check out the [book] instead.
//!
//! [book]: http://lfairy.gitbooks.io/maud/content/

use std::fmt;
use std::io;

/// Escapes an HTML value.
pub fn escape(s: &str) -> String {
    use std::fmt::Write;
    let mut buf = String::new();
    rt::Escaper { inner: &mut buf }.write_str(s).unwrap();
    buf
}

/// A block of HTML markup, as returned by the `html!` macro.
///
/// Use `.to_string()` to convert it to a `String`, or `.render()` to
/// write it directly to a handle.
pub struct Markup<F> {
    callback: F,
}

impl<F> Markup<F> where F: Fn(&mut fmt::Write) -> fmt::Result {
    /// Renders the markup to a `std::io::Write`.
    pub fn render<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
        struct Adaptor<'a, W: ?Sized + 'a> {
            inner: &'a mut W,
            error: io::Result<()>,
        }

        impl<'a, W: ?Sized + io::Write> fmt::Write for Adaptor<'a, W> {
            fn write_str(&mut self, s: &str) -> fmt::Result {
                match self.inner.write_all(s.as_bytes()) {
                    Ok(()) => Ok(()),
                    Err(e) => {
                        self.error = Err(e);
                        Err(fmt::Error)
                    },
                }
            }
        }

        let mut output = Adaptor { inner: w, error: Ok(()) };
        match self.render_fmt(&mut output) {
            Ok(()) => Ok(()),
            Err(_) => output.error,
        }
    }

    /// Renders the markup to a `std::fmt::Write`.
    pub fn render_fmt(&self, w: &mut fmt::Write) -> fmt::Result {
        (self.callback)(w)
    }
}

impl<F> ToString for Markup<F> where F: Fn(&mut fmt::Write) -> fmt::Result {
    fn to_string(&self) -> String {
        let mut buf = String::new();
        self.render_fmt(&mut buf).unwrap();
        buf
    }
}

/// Internal functions used by the `maud_macros` package. You should
/// never need to call these directly.
#[doc(hidden)]
pub mod rt {
    use std::fmt;
    use super::Markup;

    #[inline]
    pub fn make_markup<F>(f: F) -> Markup<F>
        where F: Fn(&mut fmt::Write) -> fmt::Result
    {
        Markup { callback: f }
    }

    /// rustc is a butt and doesn't let us quote macro invocations
    /// directly. So we factor the `write!` call into a separate
    /// function and use that instead.
    ///
    /// See <https://github.com/rust-lang/rust/issues/16617>
    #[inline]
    pub fn write_fmt<T: fmt::Display>(w: &mut fmt::Write, value: T) -> fmt::Result {
        write!(w, "{}", value)
    }

    pub struct Escaper<'a, 'b: 'a> {
        pub inner: &'a mut (fmt::Write + 'b),
    }

    impl<'a, 'b> fmt::Write for Escaper<'a, 'b> {
        fn write_str(&mut self, s: &str) -> fmt::Result {
            for c in s.chars() {
                try!(match c {
                    '&' => self.inner.write_str("&"),
                    '<' => self.inner.write_str("<"),
                    '>' => self.inner.write_str(">"),
                    '"' => self.inner.write_str("""),
                    '\'' => self.inner.write_str("'"),
                    _ => write!(self.inner, "{}", c),
                });
            }
            Ok(())
        }
    }
}
<|endoftext|>


<commit_before>//! [PLY](https://en.wikipedia.org/wiki/PLY_(file_format)) encoding.
//!
//! This module provides support for the PLY format via the `FromPly` and
//! `ToPly` traits. These traits can be used with a decoder and encoder to read
//! and write mesh data structures to and from the PLY format.
//!
//! PLY support is implemented using the
//! [`ply-rs`](https://crates.io/crates/ply-rs) crate.
//!
//! # Examples
//!
//! Reading a PLY file into a `MeshGraph`:
//!
//! ```rust
//! # extern crate nalgebra;
//! # extern crate plexus;
//! #
//! use nalgebra::Point3;
//! use plexus::encoding::ply::{FromPly, PointEncoding};
//! use plexus::graph::MeshGraph;
//! use std::io::Read;
//!
//! // Read from a file, network, etc.
//! fn read() -> impl Read {
//!     // ...
//!     # include_bytes!("../../data/cube.ply")
//! }
//!
//! # fn main() {
//! let encoding = PointEncoding::default();
//! let (graph, _) = MeshGraph::<Point3<f64>>::from_ply(encoding, read()).unwrap();
//! # }
//! ```

#![cfg(feature = "encoding-ply")]

use num::{NumCast, ToPrimitive};
use ply_rs::parser::Parser;
use ply_rs::ply::KeyMap;
use smallvec::SmallVec;
use std::io::{self, Read, Write};
use std::iter::FromIterator;
use std::marker::PhantomData;
use theon::space::{EuclideanSpace, FiniteDimensional};
use typenum::U3;

use crate::buffer::BufferError;
use crate::encoding::{FaceDecoder, FromEncoding, VertexDecoder};
use crate::graph::GraphError;

pub use ply_rs::ply::{
    ElementDef as ElementDefinition, Property, PropertyDef as PropertyDefinition, PropertyType,
};

// TODO: These traits only allow a single element to be read for each topology
//       (vertices, faces, etc.). It may be useful to allow code to aggregate
//       various elements to produce an output for a single topology.
// TODO: Consider using the new-type pattern to hide underlying types and
//       expose a smaller and more tailored API surface.

pub type Header = KeyMap<ElementDefinition>;
pub type Payload = KeyMap<Vec<Element>>;
pub type Element = KeyMap<Property>;

#[derive(Debug)]
pub enum PlyError {
    ElementNotFound,
    PropertyNotFound,
    Encoding,
    Io(io::Error),
}

impl From<BufferError> for PlyError {
    fn from(_: BufferError) -> Self {
        PlyError::Encoding
    }
}

impl From<io::Error> for PlyError {
    fn from(error: io::Error) -> Self {
        PlyError::Io(error)
    }
}

impl From<GraphError> for PlyError {
    fn from(_: GraphError) -> Self {
        PlyError::Encoding
    }
}

pub trait ElementExt {
    fn read_scalar<T>(&self, key: &str) -> Result<T, PlyError>
    where
        T: NumCast;

    fn read_list<T, I>(&self, key: &str) -> Result<I, PlyError>
    where
        T: NumCast,
        I: FromIterator<T>;
}

impl ElementExt for Element {
    fn read_scalar<T>(&self, key: &str) -> Result<T, PlyError>
    where
        T: NumCast,
    {
        self.get(key)
            .ok_or_else(|| PlyError::PropertyNotFound)?
            .clone()
            .into_scalar()
    }

    fn read_list<T, I>(&self, key: &str) -> Result<I, PlyError>
    where
        T: NumCast,
        I: FromIterator<T>,
    {
        self.get(key)
            .ok_or_else(|| PlyError::PropertyNotFound)?
            .clone()
            .into_list()
    }
}

pub trait PropertyExt {
    fn into_scalar<T>(self) -> Result<T, PlyError>
    where
        T: NumCast;

    fn into_list<T, I>(self) -> Result<I, PlyError>
    where
        T: NumCast,
        I: FromIterator<T>;
}

impl PropertyExt for Property {
    fn into_scalar<T>(self) -> Result<T, PlyError>
    where
        T: NumCast,
    {
        match self {
            Property::Char(value) => num_cast_scalar(value),
            Property::UChar(value) => num_cast_scalar(value),
            Property::Short(value) => num_cast_scalar(value),
            Property::UShort(value) => num_cast_scalar(value),
            Property::Int(value) => num_cast_scalar(value),
            Property::UInt(value) => num_cast_scalar(value),
            Property::Float(value) => num_cast_scalar(value),
            Property::Double(value) => num_cast_scalar(value),
            _ => Err(PlyError::Encoding),
        }
    }

    fn into_list<T, I>(self) -> Result<I, PlyError>
    where
        T: NumCast,
        I: FromIterator<T>,
    {
        match self {
            Property::ListChar(values) => num_cast_list(values),
            Property::ListUChar(values) => num_cast_list(values),
            Property::ListShort(values) => num_cast_list(values),
            Property::ListUShort(values) => num_cast_list(values),
            Property::ListInt(values) => num_cast_list(values),
            Property::ListUInt(values) => num_cast_list(values),
            Property::ListFloat(values) => num_cast_list(values),
            Property::ListDouble(values) => num_cast_list(values),
            _ => Err(PlyError::Encoding),
        }
    }
}

pub trait VertexElementDecoder {
    fn decode_vertex_elements<'a>(
        &self,
        definitions: &'a Header,
        elements: &'a Payload,
    ) -> Result<(&'a ElementDefinition, &'a Vec<Element>), PlyError> {
        definitions
            .get("vertex")
            .ok_or_else(|| PlyError::ElementNotFound)
            .map(|definition| (definition, elements.get(&definition.name).unwrap()))
    }
}

pub trait VertexPropertyDecoder: VertexDecoder {
    fn decode_vertex_properties<'a, I>(
        &self,
        definition: &'a ElementDefinition,
        elements: I,
    ) -> Result<Self::Output, PlyError>
    where
        I: IntoIterator<Item = &'a Element>;
}

pub trait FaceElementDecoder {
    fn decode_face_elements<'a>(
        &self,
        definitions: &'a Header,
        elements: &'a Payload,
    ) -> Result<(&'a ElementDefinition, &'a Vec<Element>), PlyError> {
        definitions
            .get("face")
            .ok_or_else(|| PlyError::ElementNotFound)
            .map(|definition| (definition, elements.get(&definition.name).unwrap()))
    }
}

pub trait FacePropertyDecoder: FaceDecoder {
    fn decode_face_properties<'a, I>(
        &self,
        definition: &'a ElementDefinition,
        elements: I,
    ) -> Result<Self::Output, PlyError>
    where
        I: IntoIterator<Item = &'a Element>;
}

pub trait FromPly<E>: Sized {
    fn from_ply<R>(decoder: E, read: R) -> Result<(Self, Header), PlyError>
    where
        R: Read;
}

impl<T, E> FromPly<E> for T
where
    T: FromEncoding<E>,
    PlyError: From<<T as FromEncoding<E>>::Error>,
    E: FaceElementDecoder + FacePropertyDecoder + VertexPropertyDecoder + VertexElementDecoder,
{
    fn from_ply<R>(decoder: E, mut read: R) -> Result<(Self, Header), PlyError>
    where
        R: Read,
    {
        let ply = Parser::<Element>::new().read_ply(&mut read)?;
        let vertices = decoder
            .decode_vertex_elements(&ply.header.elements, &ply.payload)
            .and_then(|(definition, elements)| {
                decoder.decode_vertex_properties(definition, elements)
            })?;
        let faces = decoder
            .decode_face_elements(&ply.header.elements, &ply.payload)
            .and_then(|(definition, elements)| {
                decoder.decode_face_properties(definition, elements)
            })?;
        let mesh = T::from_encoding(vertices, faces)?;
        Ok((mesh, ply.header.elements))
    }
}

pub trait ToPly<E> {
    fn to_ply<W>(&self, definitions: Header, encoder: E, write: W) -> Result<usize, PlyError>
    where
        W: Write;
}

pub struct PointEncoding<T> {
    phantom: PhantomData<T>,
}

impl<T> Default for PointEncoding<T> {
    fn default() -> Self {
        PointEncoding {
            phantom: PhantomData,
        }
    }
}

impl<T> FaceDecoder for PointEncoding<T> {
    type Output = Vec<(Self::Index, Self::Face)>;
    type Index = SmallVec<[usize; 4]>;
    type Face = ();
}

impl<T> FaceElementDecoder for PointEncoding<T> {}

impl<T> FacePropertyDecoder for PointEncoding<T> {
    fn decode_face_properties<'a, I>(
        &self,
        _: &'a ElementDefinition,
        elements: I,
    ) -> Result<<Self as FaceDecoder>::Output, PlyError>
    where
        I: IntoIterator<Item = &'a Element>,
    {
        elements
            .into_iter()
            .map(|element| {
                let indices = element.read_list("index")?;
                Ok((indices, ()))
            })
            .collect::<Result<_, _>>()
    }
}

impl<T> VertexDecoder for PointEncoding<T> {
    type Output = Vec<Self::Vertex>;
    type Vertex = T;
}

impl<T> VertexElementDecoder for PointEncoding<T> {}

// TODO: Support two-dimensional spaces.
impl<T> VertexPropertyDecoder for PointEncoding<T>
where
    T: EuclideanSpace + FiniteDimensional<N = U3>,
{
    fn decode_vertex_properties<'a, I>(
        &self,
        _: &'a ElementDefinition,
        elements: I,
    ) -> Result<<Self as VertexDecoder>::Output, PlyError>
    where
        I: IntoIterator<Item = &'a Element>,
    {
        elements
            .into_iter()
            .map(|element| {
                let vertex = EuclideanSpace::from_xyz(
                    element.read_scalar("x")?,
                    element.read_scalar("y")?,
                    element.read_scalar("z")?,
                );
                Ok(vertex)
            })
            .collect::<Result<_, _>>()
    }
}

fn num_cast_scalar<T, U>(value: T) -> Result<U, PlyError>
where
    T: ToPrimitive,
    U: NumCast,
{
    NumCast::from(value).ok_or_else(|| PlyError::Encoding)
}

fn num_cast_list<T, U, I>(values: Vec<T>) -> Result<I, PlyError>
where
    T: ToPrimitive,
    U: NumCast,
    I: FromIterator<U>,
{
    values
        .into_iter()
        .map(|value| num_cast_scalar(value))
        .collect::<Result<_, _>>()
}

#[cfg(test)]
mod tests {
    use nalgebra::Point3;

    use crate::encoding::ply::{FromPly, PointEncoding};
    use crate::graph::MeshGraph;

    #[test]
    fn decode() {
        let ply: &[u8] = include_bytes!("../../data/cube.ply");
        let (graph, _) = MeshGraph::<Point3<f64>>::from_ply(PointEncoding::default(), ply).unwrap();
        assert_eq!(8, graph.vertex_count());
        assert_eq!(12, graph.edge_count());
        assert_eq!(6, graph.face_count());
    }
}
<commit_msg>Fix PLY example.<commit_after>//! [PLY](https://en.wikipedia.org/wiki/PLY_(file_format)) encoding.
//!
//! This module provides support for the PLY format via the `FromPly` and
//! `ToPly` traits. These traits can be used with a decoder and encoder to read
//! and write mesh data structures to and from the PLY format.
//!
//! PLY support is implemented using the
//! [`ply-rs`](https://crates.io/crates/ply-rs) crate.
//!
//! # Examples
//!
//! Reading a PLY file into a `MeshGraph`:
//!
//! ```rust
//! # extern crate nalgebra;
//! # extern crate plexus;
//! #
//! use nalgebra::Point3;
//! use plexus::encoding::ply::{FromPly, PointEncoding};
//! use plexus::graph::MeshGraph;
//! use std::io::Read;
//!
//! // Read from a file, network, etc.
//! fn read() -> impl Read {
//!     // ...
//!     # let ply: &[u8] = include_bytes!("../../data/cube.ply");
//!     # ply
//! }
//!
//! # fn main() {
//! let encoding = PointEncoding::default();
//! let (graph, _) = MeshGraph::<Point3<f64>>::from_ply(encoding, read()).unwrap();
//! # }
//! ```

#![cfg(feature = "encoding-ply")]

use num::{NumCast, ToPrimitive};
use ply_rs::parser::Parser;
use ply_rs::ply::KeyMap;
use smallvec::SmallVec;
use std::io::{self, Read, Write};
use std::iter::FromIterator;
use std::marker::PhantomData;
use theon::space::{EuclideanSpace, FiniteDimensional};
use typenum::U3;

use crate::buffer::BufferError;
use crate::encoding::{FaceDecoder, FromEncoding, VertexDecoder};
use crate::graph::GraphError;

pub use ply_rs::ply::{
    ElementDef as ElementDefinition, Property, PropertyDef as PropertyDefinition, PropertyType,
};

// TODO: These traits only allow a single element to be read for each topology
//       (vertices, faces, etc.). It may be useful to allow code to aggregate
//       various elements to produce an output for a single topology.
// TODO: Consider using the new-type pattern to hide underlying types and
//       expose a smaller and more tailored API surface.

pub type Header = KeyMap<ElementDefinition>;
pub type Payload = KeyMap<Vec<Element>>;
pub type Element = KeyMap<Property>;

#[derive(Debug)]
pub enum PlyError {
    ElementNotFound,
    PropertyNotFound,
    Encoding,
    Io(io::Error),
}

impl From<BufferError> for PlyError {
    fn from(_: BufferError) -> Self {
        PlyError::Encoding
    }
}

impl From<io::Error> for PlyError {
    fn from(error: io::Error) -> Self {
        PlyError::Io(error)
    }
}

impl From<GraphError> for PlyError {
    fn from(_: GraphError) -> Self {
        PlyError::Encoding
    }
}

pub trait ElementExt {
    fn read_scalar<T>(&self, key: &str) -> Result<T, PlyError>
    where
        T: NumCast;

    fn read_list<T, I>(&self, key: &str) -> Result<I, PlyError>
    where
        T: NumCast,
        I: FromIterator<T>;
}

impl ElementExt for Element {
    fn read_scalar<T>(&self, key: &str) -> Result<T, PlyError>
    where
        T: NumCast,
    {
        self.get(key)
            .ok_or_else(|| PlyError::PropertyNotFound)?
            .clone()
            .into_scalar()
    }

    fn read_list<T, I>(&self, key: &str) -> Result<I, PlyError>
    where
        T: NumCast,
        I: FromIterator<T>,
    {
        self.get(key)
            .ok_or_else(|| PlyError::PropertyNotFound)?
            .clone()
            .into_list()
    }
}

pub trait PropertyExt {
    fn into_scalar<T>(self) -> Result<T, PlyError>
    where
        T: NumCast;

    fn into_list<T, I>(self) -> Result<I, PlyError>
    where
        T: NumCast,
        I: FromIterator<T>;
}

impl PropertyExt for Property {
    fn into_scalar<T>(self) -> Result<T, PlyError>
    where
        T: NumCast,
    {
        match self {
            Property::Char(value) => num_cast_scalar(value),
            Property::UChar(value) => num_cast_scalar(value),
            Property::Short(value) => num_cast_scalar(value),
            Property::UShort(value) => num_cast_scalar(value),
            Property::Int(value) => num_cast_scalar(value),
            Property::UInt(value) => num_cast_scalar(value),
            Property::Float(value) => num_cast_scalar(value),
            Property::Double(value) => num_cast_scalar(value),
            _ => Err(PlyError::Encoding),
        }
    }

    fn into_list<T, I>(self) -> Result<I, PlyError>
    where
        T: NumCast,
        I: FromIterator<T>,
    {
        match self {
            Property::ListChar(values) => num_cast_list(values),
            Property::ListUChar(values) => num_cast_list(values),
            Property::ListShort(values) => num_cast_list(values),
            Property::ListUShort(values) => num_cast_list(values),
            Property::ListInt(values) => num_cast_list(values),
            Property::ListUInt(values) => num_cast_list(values),
            Property::ListFloat(values) => num_cast_list(values),
            Property::ListDouble(values) => num_cast_list(values),
            _ => Err(PlyError::Encoding),
        }
    }
}

pub trait VertexElementDecoder {
    fn decode_vertex_elements<'a>(
        &self,
        definitions: &'a Header,
        elements: &'a Payload,
    ) -> Result<(&'a ElementDefinition, &'a Vec<Element>), PlyError> {
        definitions
            .get("vertex")
            .ok_or_else(|| PlyError::ElementNotFound)
            .map(|definition| (definition, elements.get(&definition.name).unwrap()))
    }
}

pub trait VertexPropertyDecoder: VertexDecoder {
    fn decode_vertex_properties<'a, I>(
        &self,
        definition: &'a ElementDefinition,
        elements: I,
    ) -> Result<Self::Output, PlyError>
    where
        I: IntoIterator<Item = &'a Element>;
}

pub trait FaceElementDecoder {
    fn decode_face_elements<'a>(
        &self,
        definitions: &'a Header,
        elements: &'a Payload,
    ) -> Result<(&'a ElementDefinition, &'a Vec<Element>), PlyError> {
        definitions
            .get("face")
            .ok_or_else(|| PlyError::ElementNotFound)
            .map(|definition| (definition, elements.get(&definition.name).unwrap()))
    }
}

pub trait FacePropertyDecoder: FaceDecoder {
    fn decode_face_properties<'a, I>(
        &self,
        definition: &'a ElementDefinition,
        elements: I,
    ) -> Result<Self::Output, PlyError>
    where
        I: IntoIterator<Item = &'a Element>;
}

pub trait FromPly<E>: Sized {
    fn from_ply<R>(decoder: E, read: R) -> Result<(Self, Header), PlyError>
    where
        R: Read;
}

impl<T, E> FromPly<E> for T
where
    T: FromEncoding<E>,
    PlyError: From<<T as FromEncoding<E>>::Error>,
    E: FaceElementDecoder + FacePropertyDecoder + VertexPropertyDecoder + VertexElementDecoder,
{
    fn from_ply<R>(decoder: E, mut read: R) -> Result<(Self, Header), PlyError>
    where
        R: Read,
    {
        let ply = Parser::<Element>::new().read_ply(&mut read)?;
        let vertices = decoder
            .decode_vertex_elements(&ply.header.elements, &ply.payload)
            .and_then(|(definition, elements)| {
                decoder.decode_vertex_properties(definition, elements)
            })?;
        let faces = decoder
            .decode_face_elements(&ply.header.elements, &ply.payload)
            .and_then(|(definition, elements)| {
                decoder.decode_face_properties(definition, elements)
            })?;
        let mesh = T::from_encoding(vertices, faces)?;
        Ok((mesh, ply.header.elements))
    }
}

pub trait ToPly<E> {
    fn to_ply<W>(&self, definitions: Header, encoder: E, write: W) -> Result<usize, PlyError>
    where
        W: Write;
}

pub struct PointEncoding<T> {
    phantom: PhantomData<T>,
}

impl<T> Default for PointEncoding<T> {
    fn default() -> Self {
        PointEncoding {
            phantom: PhantomData,
        }
    }
}

impl<T> FaceDecoder for PointEncoding<T> {
    type Output = Vec<(Self::Index, Self::Face)>;
    type Index = SmallVec<[usize; 4]>;
    type Face = ();
}

impl<T> FaceElementDecoder for PointEncoding<T> {}

impl<T> FacePropertyDecoder for PointEncoding<T> {
    fn decode_face_properties<'a, I>(
        &self,
        _: &'a ElementDefinition,
        elements: I,
    ) -> Result<<Self as FaceDecoder>::Output, PlyError>
    where
        I: IntoIterator<Item = &'a Element>,
    {
        elements
            .into_iter()
            .map(|element| {
                let indices = element.read_list("index")?;
                Ok((indices, ()))
            })
            .collect::<Result<_, _>>()
    }
}

impl<T> VertexDecoder for PointEncoding<T> {
    type Output = Vec<Self::Vertex>;
    type Vertex = T;
}

impl<T> VertexElementDecoder for PointEncoding<T> {}

// TODO: Support two-dimensional spaces.
impl<T> VertexPropertyDecoder for PointEncoding<T>
where
    T: EuclideanSpace + FiniteDimensional<N = U3>,
{
    fn decode_vertex_properties<'a, I>(
        &self,
        _: &'a ElementDefinition,
        elements: I,
    ) -> Result<<Self as VertexDecoder>::Output, PlyError>
    where
        I: IntoIterator<Item = &'a Element>,
    {
        elements
            .into_iter()
            .map(|element| {
                let vertex = EuclideanSpace::from_xyz(
                    element.read_scalar("x")?,
                    element.read_scalar("y")?,
                    element.read_scalar("z")?,
                );
                Ok(vertex)
            })
            .collect::<Result<_, _>>()
    }
}

fn num_cast_scalar<T, U>(value: T) -> Result<U, PlyError>
where
    T: ToPrimitive,
    U: NumCast,
{
    NumCast::from(value).ok_or_else(|| PlyError::Encoding)
}

fn num_cast_list<T, U, I>(values: Vec<T>) -> Result<I, PlyError>
where
    T: ToPrimitive,
    U: NumCast,
    I: FromIterator<U>,
{
    values
        .into_iter()
        .map(|value| num_cast_scalar(value))
        .collect::<Result<_, _>>()
}

#[cfg(test)]
mod tests {
    use nalgebra::Point3;

    use crate::encoding::ply::{FromPly, PointEncoding};
    use crate::graph::MeshGraph;

    #[test]
    fn decode() {
        let ply: &[u8] = include_bytes!("../../data/cube.ply");
        let (graph, _) = MeshGraph::<Point3<f64>>::from_ply(PointEncoding::default(), ply).unwrap();
        assert_eq!(8, graph.vertex_count());
        assert_eq!(12, graph.edge_count());
        assert_eq!(6, graph.face_count());
    }
}
<|endoftext|>