<commit_before>//! Geometric traits and primitives.
//!
//! These traits are used to support high-order operations in generators and
//! `Mesh`es. To use types as geometry in a `Mesh` only requires implementing
//! the `Geometry` and `Attribute` traits. Operation and convertion traits are
//! optional, but enable additional features.

use decorum::Finite;
use num::{self, Float, Num, NumCast};

use ordered::HashConjugate;

pub mod convert;
pub mod ops;

// TODO: `Finite` is used as a hash conjugate and is convertible in geometric
//       types. It may also be good to support `NotNan` for geometric
//       conversions. Is there a way to do that generically (without copying
//       the `Finite` implementations)?

pub trait Attribute: Clone {}

pub trait Geometry: Sized {
    type Vertex: Attribute;
    type Edge: Attribute + Default;
    type Face: Attribute + Default;
}

impl Attribute for () {}

impl Geometry for () {
    type Vertex = ();
    type Edge = ();
    type Face = ();
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Duplet<T>(pub T, pub T);

impl<T> HashConjugate for Duplet<T>
where
    T: Float,
{
    type Hash = Duplet<Finite<T>>;

    fn into_hash(self) -> Self::Hash {
        Duplet(
            Finite::from_raw_float(self.0).unwrap(),
            Finite::from_raw_float(self.1).unwrap(),
        )
    }

    fn from_hash(hash: Self::Hash) -> Self {
        Duplet((hash.0).into_raw_float(), (hash.1).into_raw_float())
    }
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Triplet<T>(pub T, pub T, pub T);

impl<T> Attribute for Triplet<T>
where
    T: Clone,
{
}

impl<T> Geometry for Triplet<T>
where
    T: Clone,
{
    type Vertex = Self;
    type Edge = ();
    type Face = ();
}

impl<T> HashConjugate for Triplet<T>
where
    T: Float,
{
    type Hash = Triplet<Finite<T>>;

    fn into_hash(self) -> Self::Hash {
        Triplet(
            Finite::from_raw_float(self.0).unwrap(),
            Finite::from_raw_float(self.1).unwrap(),
            Finite::from_raw_float(self.2).unwrap(),
        )
    }

    fn from_hash(hash: Self::Hash) -> Self {
        Triplet(
            (hash.0).into_raw_float(),
            (hash.1).into_raw_float(),
            (hash.2).into_raw_float(),
        )
    }
}

pub fn lerp<T>(a: T, b: T, f: f64) -> T
where
    T: Num + NumCast,
{
    let f = num::clamp(f, 0.0, 1.0);
    let af = <f64 as NumCast>::from(a).unwrap() * (1.0 - f);
    let bf = <f64 as NumCast>::from(b).unwrap() * f;
    <T as NumCast>::from(af + bf).unwrap()
}

// TODO: `Finite` cannot be used as scalar values with cgmath types. This means
//       cgmath does not support `HashConjugate`.
#[cfg(feature = "geometry-cgmath")]
mod feature_geometry_cgmath {
    use cgmath::{BaseNum, Point2, Point3, Vector2, Vector3};

    use geometry::*;

    impl<T> From<Point2<T>> for Duplet<T> {
        fn from(other: Point2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> From<Vector2<T>> for Duplet<T> {
        fn from(other: Vector2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> Into<Point2<T>> for Duplet<T>
    where
        T: BaseNum,
    {
        fn into(self) -> Point2<T> {
            Point2::new(self.0, self.1)
        }
    }

    impl<T> Into<Vector2<T>> for Duplet<T>
    where
        T: BaseNum,
    {
        fn into(self) -> Vector2<T> {
            Vector2::new(self.0, self.1)
        }
    }

    impl<T> From<Point3<T>> for Triplet<T> {
        fn from(other: Point3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> From<Vector3<T>> for Triplet<T> {
        fn from(other: Vector3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> Into<Point3<T>> for Triplet<T>
    where
        T: BaseNum,
    {
        fn into(self) -> Point3<T> {
            Point3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Into<Vector3<T>> for Triplet<T>
    where
        T: BaseNum,
    {
        fn into(self) -> Vector3<T> {
            Vector3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Attribute for Point3<T>
    where
        T: Clone,
    {
    }

    impl<T> Geometry for Point3<T>
    where
        T: Clone,
    {
        type Vertex = Self;
        type Edge = ();
        type Face = ();
    }
}

#[cfg(feature = "geometry-nalgebra")]
mod feature_geometry_nalgebra {
    use nalgebra::{Point2, Point3, Scalar, Vector2, Vector3};

    use geometry::*;

    impl<T> From<Point2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn from(other: Point2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> From<Vector2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn from(other: Vector2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> Into<Point2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Point2<T> {
            Point2::new(self.0, self.1)
        }
    }

    impl<T> Into<Vector2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Vector2<T> {
            Vector2::new(self.0, self.1)
        }
    }

    impl<T> From<Point3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn from(other: Point3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> From<Vector3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn from(other: Vector3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> Into<Point3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Point3<T> {
            Point3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Into<Vector3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Vector3<T> {
            Vector3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Attribute for Point3<T>
    where
        T: Scalar,
    {
    }

    impl<T> Geometry for Point3<T>
    where
        T: Scalar,
    {
        type Vertex = Self;
        type Edge = ();
        type Face = ();
    }

    impl<T> HashConjugate for Point2<T>
    where
        T: Float + Scalar,
    {
        type Hash = Point2<Finite<T>>;

        fn into_hash(self) -> Self::Hash {
            Point2::new(
                Finite::from_raw_float(self.x).unwrap(),
                Finite::from_raw_float(self.y).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Point2::new(hash.x.into_raw_float(), hash.y.into_raw_float())
        }
    }

    impl<T> HashConjugate for Point3<T>
    where
        T: Float + Scalar,
    {
        type Hash = Point3<Finite<T>>;

        fn into_hash(self) -> Self::Hash {
            Point3::new(
                Finite::from_raw_float(self.x).unwrap(),
                Finite::from_raw_float(self.y).unwrap(),
                Finite::from_raw_float(self.z).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Point3::new(
                hash.x.into_raw_float(),
                hash.y.into_raw_float(),
                hash.z.into_raw_float(),
            )
        }
    }

    impl<T> HashConjugate for Vector2<T>
    where
        T: Float + Scalar,
    {
        type Hash = Vector2<Finite<T>>;

        fn into_hash(self) -> Self::Hash {
            Vector2::new(
                Finite::from_raw_float(self.x).unwrap(),
                Finite::from_raw_float(self.y).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Vector2::new(hash.x.into_raw_float(), hash.y.into_raw_float())
        }
    }

    impl<T> HashConjugate for Vector3<T>
    where
        T: Float + Scalar,
    {
        type Hash = Vector3<Finite<T>>;

        fn into_hash(self) -> Self::Hash {
            Vector3::new(
                Finite::from_raw_float(self.x).unwrap(),
                Finite::from_raw_float(self.y).unwrap(),
                Finite::from_raw_float(self.z).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Vector3::new(
                hash.x.into_raw_float(),
                hash.y.into_raw_float(),
                hash.z.into_raw_float(),
            )
        }
    }
}
<commit_msg>Expand on cgmath hash conjugate comment.<commit_after>//! Geometric traits and primitives.
//!
//! These traits are used to support high-order operations in generators and
//! `Mesh`es. To use types as geometry in a `Mesh` only requires implementing
//! the `Geometry` and `Attribute` traits. Operation and convertion traits are
//! optional, but enable additional features.

use decorum::Finite;
use num::{self, Float, Num, NumCast};

use ordered::HashConjugate;

pub mod convert;
pub mod ops;

// TODO: `Finite` is used as a hash conjugate and is convertible in geometric
//       types. It may also be good to support `NotNan` for geometric
//       conversions. Is there a way to do that generically (without copying
//       the `Finite` implementations)?

pub trait Attribute: Clone {}

pub trait Geometry: Sized {
    type Vertex: Attribute;
    type Edge: Attribute + Default;
    type Face: Attribute + Default;
}

impl Attribute for () {}

impl Geometry for () {
    type Vertex = ();
    type Edge = ();
    type Face = ();
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Duplet<T>(pub T, pub T);

impl<T> HashConjugate for Duplet<T>
where
    T: Float,
{
    type Hash = Duplet<Finite<T>>;

    fn into_hash(self) -> Self::Hash {
        Duplet(
            Finite::from_raw_float(self.0).unwrap(),
            Finite::from_raw_float(self.1).unwrap(),
        )
    }

    fn from_hash(hash: Self::Hash) -> Self {
        Duplet((hash.0).into_raw_float(), (hash.1).into_raw_float())
    }
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Triplet<T>(pub T, pub T, pub T);

impl<T> Attribute for Triplet<T>
where
    T: Clone,
{
}

impl<T> Geometry for Triplet<T>
where
    T: Clone,
{
    type Vertex = Self;
    type Edge = ();
    type Face = ();
}

impl<T> HashConjugate for Triplet<T>
where
    T: Float,
{
    type Hash = Triplet<Finite<T>>;

    fn into_hash(self) -> Self::Hash {
        Triplet(
            Finite::from_raw_float(self.0).unwrap(),
            Finite::from_raw_float(self.1).unwrap(),
            Finite::from_raw_float(self.2).unwrap(),
        )
    }

    fn from_hash(hash: Self::Hash) -> Self {
        Triplet(
            (hash.0).into_raw_float(),
            (hash.1).into_raw_float(),
            (hash.2).into_raw_float(),
        )
    }
}

pub fn lerp<T>(a: T, b: T, f: f64) -> T
where
    T: Num + NumCast,
{
    let f = num::clamp(f, 0.0, 1.0);
    let af = <f64 as NumCast>::from(a).unwrap() * (1.0 - f);
    let bf = <f64 as NumCast>::from(b).unwrap() * f;
    <T as NumCast>::from(af + bf).unwrap()
}

// TODO: `Finite` cannot be used as scalar values with cgmath types, because it
//       does not implement `Float` and therefore cannot implement `BaseFloat`.
//       This means cgmath does not support `HashConjugate`.
//
//       The decorum crate could probably provide a hashable type that has no
//       constraints on its value.
#[cfg(feature = "geometry-cgmath")]
mod feature_geometry_cgmath {
    use cgmath::{BaseNum, Point2, Point3, Vector2, Vector3};

    use geometry::*;

    impl<T> From<Point2<T>> for Duplet<T> {
        fn from(other: Point2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> From<Vector2<T>> for Duplet<T> {
        fn from(other: Vector2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> Into<Point2<T>> for Duplet<T>
    where
        T: BaseNum,
    {
        fn into(self) -> Point2<T> {
            Point2::new(self.0, self.1)
        }
    }

    impl<T> Into<Vector2<T>> for Duplet<T>
    where
        T: BaseNum,
    {
        fn into(self) -> Vector2<T> {
            Vector2::new(self.0, self.1)
        }
    }

    impl<T> From<Point3<T>> for Triplet<T> {
        fn from(other: Point3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> From<Vector3<T>> for Triplet<T> {
        fn from(other: Vector3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> Into<Point3<T>> for Triplet<T>
    where
        T: BaseNum,
    {
        fn into(self) -> Point3<T> {
            Point3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Into<Vector3<T>> for Triplet<T>
    where
        T: BaseNum,
    {
        fn into(self) -> Vector3<T> {
            Vector3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Attribute for Point3<T>
    where
        T: Clone,
    {
    }

    impl<T> Geometry for Point3<T>
    where
        T: Clone,
    {
        type Vertex = Self;
        type Edge = ();
        type Face = ();
    }
}

#[cfg(feature = "geometry-nalgebra")]
mod feature_geometry_nalgebra {
    use nalgebra::{Point2, Point3, Scalar, Vector2, Vector3};

    use geometry::*;

    impl<T> From<Point2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn from(other: Point2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> From<Vector2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn from(other: Vector2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> Into<Point2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Point2<T> {
            Point2::new(self.0, self.1)
        }
    }

    impl<T> Into<Vector2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Vector2<T> {
            Vector2::new(self.0, self.1)
        }
    }

    impl<T> From<Point3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn from(other: Point3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> From<Vector3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn from(other: Vector3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> Into<Point3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Point3<T> {
            Point3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Into<Vector3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Vector3<T> {
            Vector3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Attribute for Point3<T>
    where
        T: Scalar,
    {
    }

    impl<T> Geometry for Point3<T>
    where
        T: Scalar,
    {
        type Vertex = Self;
        type Edge = ();
        type Face = ();
    }

    impl<T> HashConjugate for Point2<T>
    where
        T: Float + Scalar,
    {
        type Hash = Point2<Finite<T>>;

        fn into_hash(self) -> Self::Hash {
            Point2::new(
                Finite::from_raw_float(self.x).unwrap(),
                Finite::from_raw_float(self.y).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Point2::new(hash.x.into_raw_float(), hash.y.into_raw_float())
        }
    }

    impl<T> HashConjugate for Point3<T>
    where
        T: Float + Scalar,
    {
        type Hash = Point3<Finite<T>>;

        fn into_hash(self) -> Self::Hash {
            Point3::new(
                Finite::from_raw_float(self.x).unwrap(),
                Finite::from_raw_float(self.y).unwrap(),
                Finite::from_raw_float(self.z).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Point3::new(
                hash.x.into_raw_float(),
                hash.y.into_raw_float(),
                hash.z.into_raw_float(),
            )
        }
    }

    impl<T> HashConjugate for Vector2<T>
    where
        T: Float + Scalar,
    {
        type Hash = Vector2<Finite<T>>;

        fn into_hash(self) -> Self::Hash {
            Vector2::new(
                Finite::from_raw_float(self.x).unwrap(),
                Finite::from_raw_float(self.y).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Vector2::new(hash.x.into_raw_float(), hash.y.into_raw_float())
        }
    }

    impl<T> HashConjugate for Vector3<T>
    where
        T: Float + Scalar,
    {
        type Hash = Vector3<Finite<T>>;

        fn into_hash(self) -> Self::Hash {
            Vector3::new(
                Finite::from_raw_float(self.x).unwrap(),
                Finite::from_raw_float(self.y).unwrap(),
                Finite::from_raw_float(self.z).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Vector3::new(
                hash.x.into_raw_float(),
                hash.y.into_raw_float(),
                hash.z.into_raw_float(),
            )
        }
    }
}
<|endoftext|>


<commit_before>extern crate lcm;

// mod exlcm;
mod exlcm {
    include!(concat!(env!("OUT_DIR"), "/exlcm/example_t.rs"));
}

// mod exlcm_backup;
// use exlcm_backup as exlcm;

fn main() {
    let mut lcm = lcm::Lcm::new();

    let mut my_data = exlcm::ExampleT::new();
    // let mut my_data = exlcm::Example::new();
    my_data.timestamp = 0;

    my_data.position[0] = 1.0;
    my_data.position[1] = 2.0;
    my_data.position[2] = 3.0;

    my_data.orientation[0] = 1.0;
    my_data.orientation[1] = 0.0;
    my_data.orientation[2] = 0.0;
    my_data.orientation[3] = 0.0;

    my_data.num_ranges = 15;
    my_data.ranges = (0..15).collect();

    my_data.name = "example string".to_string();
    my_data.enabled = true;

    lcm.publish("EXAMPLE", &my_data);
}
<commit_msg>Handle return value in example.<commit_after>extern crate lcm;

// mod exlcm;
mod exlcm {
    include!(concat!(env!("OUT_DIR"), "/exlcm/example_t.rs"));
}

// mod exlcm_backup;
// use exlcm_backup as exlcm;

fn main() {
    let mut lcm = lcm::Lcm::new();

    let mut my_data = exlcm::ExampleT::new();
    // let mut my_data = exlcm::Example::new();
    my_data.timestamp = 0;

    my_data.position[0] = 1.0;
    my_data.position[1] = 2.0;
    my_data.position[2] = 3.0;

    my_data.orientation[0] = 1.0;
    my_data.orientation[1] = 0.0;
    my_data.orientation[2] = 0.0;
    my_data.orientation[3] = 0.0;

    my_data.num_ranges = 15;
    my_data.ranges = (0..15).collect();

    my_data.name = "example string".to_string();
    my_data.enabled = true;

    match lcm.publish("EXAMPLE", &my_data) {
        Ok(()) => println!("Sent message."),
        Err(e) => println!("Failed to send message: {}", e)
    }
}
<|endoftext|>


<commit_before>//! An example that determines the time stamp counter frequency (RDTSC, RDTSCP) .
extern crate raw_cpuid;
extern crate x86;

use std::time;
use x86::time::rdtscp;

const MHZ_TO_HZ: u64 = 1000000;
const KHZ_TO_HZ: u64 = 1000;

fn main() {
    let cpuid = raw_cpuid::CpuId::new();
    let has_tsc = cpuid
        .get_feature_info()
        .map_or(false, |finfo| finfo.has_tsc());

    let has_invariant_tsc = cpuid
        .get_extended_function_info()
        .map_or(false, |efinfo| efinfo.has_invariant_tsc());

    let tsc_frequency_hz = cpuid.get_tsc_info().map(|tinfo| {
        if tinfo.nominal_frequency() != 0 {
            Some(tinfo.tsc_frequency())
        } else if tinfo.numerator() != 0 && tinfo.denominator() != 0 {
            // Skylake and Kabylake don't report the crystal clock, approximate with base frequency:
            cpuid
                .get_processor_frequency_info()
                .map(|pinfo| pinfo.processor_base_frequency() as u64 * MHZ_TO_HZ)
                .map(|cpu_base_freq_hz| {
                    let crystal_hz =
                        cpu_base_freq_hz * tinfo.denominator() as u64 / tinfo.numerator() as u64;
                    crystal_hz * tinfo.numerator() as u64 / tinfo.denominator() as u64
                })
        } else {
            None
        }
    });

    if has_tsc {
        println!(
            "TSC Frequency is: {} ({})",
            match tsc_frequency_hz {
                Some(x) => format!("{} Hz", x.unwrap_or(0)),
                None => String::from("unknown"),
            },
            if has_invariant_tsc {
                "invariant"
            } else {
                "TSC frequency varies with speed-stepping"
            }
        );
    }

    cpuid.get_hypervisor_info().map(|hv| {
        hv.tsc_frequency().map(|tsc_khz| {
            let virtual_tsc_frequency_hz = tsc_khz as u64 * KHZ_TO_HZ;
            println!(
                "Hypervisor reports TSC Frequency at: {} Hz",
                virtual_tsc_frequency_hz
            );
        })
    });

    let one_second = time::Duration::from_secs(1);
    let now = time::Instant::now();
    let start = unsafe { rdtscp() };
    loop {
        if now.elapsed() >= one_second {
            break;
        }
    }
    let end = unsafe { rdtscp() };
    println!(
        "Empirical measurement of TSC frequency was: {} Hz",
        (end - start)
    );
}
<commit_msg>Add comments.<commit_after>//! An example that determines the time stamp counter frequency (RDTSC, RDTSCP) .
extern crate raw_cpuid;
extern crate x86;

use std::time;
use x86::time::rdtscp;

const MHZ_TO_HZ: u64 = 1000000;
const KHZ_TO_HZ: u64 = 1000;

fn main() {
    let cpuid = raw_cpuid::CpuId::new();
    let has_tsc = cpuid
        .get_feature_info()
        .map_or(false, |finfo| finfo.has_tsc());

    let has_invariant_tsc = cpuid
        .get_extended_function_info()
        .map_or(false, |efinfo| efinfo.has_invariant_tsc());

    let tsc_frequency_hz = cpuid.get_tsc_info().map(|tinfo| {
        if tinfo.nominal_frequency() != 0 {
            Some(tinfo.tsc_frequency())
        } else if tinfo.numerator() != 0 && tinfo.denominator() != 0 {
            // Skylake and Kabylake don't report the crystal clock, approximate with base frequency:
            cpuid
                .get_processor_frequency_info()
                .map(|pinfo| pinfo.processor_base_frequency() as u64 * MHZ_TO_HZ)
                .map(|cpu_base_freq_hz| {
                    let crystal_hz =
                        cpu_base_freq_hz * tinfo.denominator() as u64 / tinfo.numerator() as u64;
                    crystal_hz * tinfo.numerator() as u64 / tinfo.denominator() as u64
                })
        } else {
            None
        }
    });

    if has_tsc {
        // Try to figure out TSC frequency with CPUID
        println!(
            "TSC Frequency is: {} ({})",
            match tsc_frequency_hz {
                Some(x) => format!("{} Hz", x.unwrap_or(0)),
                None => String::from("unknown"),
            },
            if has_invariant_tsc {
                "invariant"
            } else {
                "TSC frequency varies with speed-stepping"
            }
        );

        // Check if we run in a VM and the hypervisor can give us the TSC frequency
        cpuid.get_hypervisor_info().map(|hv| {
            hv.tsc_frequency().map(|tsc_khz| {
                let virtual_tsc_frequency_hz = tsc_khz as u64 * KHZ_TO_HZ;
                println!(
                    "Hypervisor reports TSC Frequency at: {} Hz",
                    virtual_tsc_frequency_hz
                );
            })
        });

        // Determine TSC frequency by measuring it (loop for a second, record ticks)
        let one_second = time::Duration::from_secs(1);
        let now = time::Instant::now();
        let start = unsafe { rdtscp() };
        loop {
            if now.elapsed() >= one_second {
                break;
            }
        }
        let end = unsafe { rdtscp() };
        println!(
            "Empirical measurement of TSC frequency was: {} Hz",
            (end - start)
        );
    } else {
        println!("System does not have a TSC.")
    }
}
<|endoftext|>


<commit_before>use serde::{
    de::DeserializeOwned,
    Deserialize,
    Serialize,
};

use std::{
    cmp::Ordering::{
        Equal,
        Greater,
        Less,
    },
    path::Path,
};

use anyhow::{
    anyhow,
    Result,
};
use itertools::Itertools;

use crate::psql::JsonlIterator;
use rnc_utils;

pub trait HasIndex {
    fn index(&self) -> usize;
}

pub enum Criteria {
    AnyNumber,
    AtleastOne,
    ExactlyOne,
    ZeroOrOne,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum Grouped<T> {
    Multiple {
        id: usize,
        data: Vec<T>,
    },
    Optional {
        id: usize,
        data: Option<T>,
    },
    Required {
        id: usize,
        data: T,
    },
}

impl<T> Grouped<T>
where
    T: Serialize + DeserializeOwned,
{
    fn empty(criteria: &Criteria, id: usize) -> Result<Grouped<T>> {
        match criteria {
            Criteria::AnyNumber => Ok(Self::Multiple {
                id,
                data: Vec::new(),
            }),
            Criteria::AtleastOne => Err(anyhow!("Missing data for id: {}", id)),
            Criteria::ExactlyOne => Err(anyhow!("Missing data for id: {}", id)),
            Criteria::ZeroOrOne => Ok(Self::Optional {
                id,
                data: None,
            }),
        }
    }

    pub fn is_empty(&self) -> bool {
        match self {
            Self::Multiple { id: _id, data } => data.len() > 0,
            Self::Optional { id: _id, data } => data.is_none(),
            Self::Required { id: _id, data: _data } => false,
        }
    }

    fn build(criteria: &Criteria, id: usize, items: Vec<T>) -> Result<Grouped<T>> {
        match (criteria, items.len()) {
            (Criteria::AnyNumber, 0) => Ok(Self::Multiple {
                id,
                data: Vec::new(),
            }),
            (Criteria::AnyNumber, _) => Ok(Self::Multiple {
                id,
                data: items,
            }),
            (Criteria::AtleastOne, 0) => Err(anyhow!("Missing at least one item for {}", id)),
            (Criteria::AtleastOne, _) => Ok(Self::Multiple {
                id,
                data: items,
            }),
            (Criteria::ExactlyOne, 0) => Err(anyhow!("Missing required items for {}", id)),
            (Criteria::ExactlyOne, 1) => Ok(Self::Required {
                id,
                data: items.into_iter().next().unwrap(),
            }),
            (Criteria::ExactlyOne, l) => {
                Err(anyhow!("Too many items ({}) for id: {}, expected 1", l, id))
            },
            (Criteria::ZeroOrOne, 0) => Ok(Self::Optional {
                id,
                data: None,
            }),
            (Criteria::ZeroOrOne, 1) => Ok(Self::Optional {
                id,
                data: items.into_iter().next(),
            }),
            (Criteria::ZeroOrOne, l) => {
                Err(anyhow!("Too many items ({}) for {}, expected 0 or 1", l, id))
            },
        }
    }
}

pub fn group<T>(
    criteria: Criteria,
    path: &Path,
    min: usize,
    max: usize,
    output: &Path,
) -> Result<()>
where
    T: DeserializeOwned + HasIndex + Serialize,
{
    let reader = rnc_utils::buf_reader(path)?;
    let mut writer = rnc_utils::buf_writer(output)?;

    let data = JsonlIterator::from_read(reader);
    let data = data.group_by(T::index);

    let mut expected = min;
    for (id, entries) in &data {
        match (&expected).cmp(&id) {
            Less => {
                while expected < id {
                    let empty: Grouped<T> = Grouped::empty(&criteria, expected)?;
                    serde_json::to_writer(&mut writer, &empty)?;
                    writeln!(&mut writer)?;
                    expected += 1;
                }
                assert!(expected == id);
                let group = Grouped::build(&criteria, expected, entries.collect())?;
                serde_json::to_writer(&mut writer, &group)?;
                writeln!(&mut writer)?;
                expected += 1;
            },
            Equal => {
                let data: Vec<T> = entries.collect();
                let grouped = Grouped::build(&criteria, id, data)?;
                serde_json::to_writer(&mut writer, &grouped)?;
                writeln!(&mut writer)?;
                expected += 1;
            },
            Greater => {
                return Err(anyhow!(
                    "Somehow got too small index {}, expected, {}",
                    &id,
                    &expected
                ));
            },
        }

        if expected != id + 1 {
            return Err(anyhow!("Current out of sync with expected {} {}", expected, id));
        }
    }

    match expected.cmp(&max) {
        Less => {
            while expected < max {
                let empty: Grouped<T> = Grouped::empty(&criteria, expected)?;
                serde_json::to_writer(&mut writer, &empty)?;
                writeln!(&mut writer)?;
                expected += 1;
            }
        },
        Equal => (),
        Greater => {
            return Err(anyhow!("Got more items {} than expected {}", &expected, &max));
        },
    }

    assert!(expected == max, "Did not reach {}, at {}", &max, &expected);

    Ok(())
}
<commit_msg>Correct is_empty logic<commit_after>use serde::{
    de::DeserializeOwned,
    Deserialize,
    Serialize,
};

use std::{
    cmp::Ordering::{
        Equal,
        Greater,
        Less,
    },
    path::Path,
};

use anyhow::{
    anyhow,
    Result,
};
use itertools::Itertools;

use crate::psql::JsonlIterator;
use rnc_utils;

pub trait HasIndex {
    fn index(&self) -> usize;
}

pub enum Criteria {
    AnyNumber,
    AtleastOne,
    ExactlyOne,
    ZeroOrOne,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum Grouped<T> {
    Multiple {
        id: usize,
        data: Vec<T>,
    },
    Optional {
        id: usize,
        data: Option<T>,
    },
    Required {
        id: usize,
        data: T,
    },
}

impl<T> Grouped<T>
where
    T: Serialize + DeserializeOwned,
{
    fn empty(criteria: &Criteria, id: usize) -> Result<Grouped<T>> {
        match criteria {
            Criteria::AnyNumber => Ok(Self::Multiple {
                id,
                data: Vec::new(),
            }),
            Criteria::AtleastOne => Err(anyhow!("Missing data for id: {}", id)),
            Criteria::ExactlyOne => Err(anyhow!("Missing data for id: {}", id)),
            Criteria::ZeroOrOne => Ok(Self::Optional {
                id,
                data: None,
            }),
        }
    }

    pub fn is_empty(&self) -> bool {
        match self {
            Self::Multiple { id: _id, data } => data.len() == 0,
            Self::Optional { id: _id, data } => data.is_none(),
            Self::Required { id: _id, data: _data } => false,
        }
    }

    fn build(criteria: &Criteria, id: usize, items: Vec<T>) -> Result<Grouped<T>> {
        match (criteria, items.len()) {
            (Criteria::AnyNumber, 0) => Ok(Self::Multiple {
                id,
                data: Vec::new(),
            }),
            (Criteria::AnyNumber, _) => Ok(Self::Multiple {
                id,
                data: items,
            }),
            (Criteria::AtleastOne, 0) => Err(anyhow!("Missing at least one item for {}", id)),
            (Criteria::AtleastOne, _) => Ok(Self::Multiple {
                id,
                data: items,
            }),
            (Criteria::ExactlyOne, 0) => Err(anyhow!("Missing required items for {}", id)),
            (Criteria::ExactlyOne, 1) => Ok(Self::Required {
                id,
                data: items.into_iter().next().unwrap(),
            }),
            (Criteria::ExactlyOne, l) => {
                Err(anyhow!("Too many items ({}) for id: {}, expected 1", l, id))
            },
            (Criteria::ZeroOrOne, 0) => Ok(Self::Optional {
                id,
                data: None,
            }),
            (Criteria::ZeroOrOne, 1) => Ok(Self::Optional {
                id,
                data: items.into_iter().next(),
            }),
            (Criteria::ZeroOrOne, l) => {
                Err(anyhow!("Too many items ({}) for {}, expected 0 or 1", l, id))
            },
        }
    }
}

pub fn group<T>(
    criteria: Criteria,
    path: &Path,
    min: usize,
    max: usize,
    output: &Path,
) -> Result<()>
where
    T: DeserializeOwned + HasIndex + Serialize,
{
    let reader = rnc_utils::buf_reader(path)?;
    let mut writer = rnc_utils::buf_writer(output)?;

    let data = JsonlIterator::from_read(reader);
    let data = data.group_by(T::index);

    let mut expected = min;
    for (id, entries) in &data {
        match (&expected).cmp(&id) {
            Less => {
                while expected < id {
                    let empty: Grouped<T> = Grouped::empty(&criteria, expected)?;
                    serde_json::to_writer(&mut writer, &empty)?;
                    writeln!(&mut writer)?;
                    expected += 1;
                }
                assert!(expected == id);
                let group = Grouped::build(&criteria, expected, entries.collect())?;
                serde_json::to_writer(&mut writer, &group)?;
                writeln!(&mut writer)?;
                expected += 1;
            },
            Equal => {
                let data: Vec<T> = entries.collect();
                let grouped = Grouped::build(&criteria, id, data)?;
                serde_json::to_writer(&mut writer, &grouped)?;
                writeln!(&mut writer)?;
                expected += 1;
            },
            Greater => {
                return Err(anyhow!(
                    "Somehow got too small index {}, expected, {}",
                    &id,
                    &expected
                ));
            },
        }

        if expected != id + 1 {
            return Err(anyhow!("Current out of sync with expected {} {}", expected, id));
        }
    }

    match expected.cmp(&max) {
        Less => {
            while expected < max {
                let empty: Grouped<T> = Grouped::empty(&criteria, expected)?;
                serde_json::to_writer(&mut writer, &empty)?;
                writeln!(&mut writer)?;
                expected += 1;
            }
        },
        Equal => (),
        Greater => {
            return Err(anyhow!("Got more items {} than expected {}", &expected, &max));
        },
    }

    assert!(expected == max, "Did not reach {}, at {}", &max, &expected);

    Ok(())
}
<|endoftext|>


<commit_before>// This module defines a unified error type used across zakocmp.

use std::string::String;

#[derive(Debug)]
pub enum ZakocmpError {
    // Propagates I/O errors (e.g. from reading actual files).
    Io(std::io::Error),
    // Describes problems with zakocmp configuration files.
    Config(String),
    // Describes problems with zakocmp snapshot files.
    Snapshot(String),
    // Describes unknown or unspecified errors.
    Unknown(String),
}

impl std::fmt::Display for ZakocmpError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ZakocmpError::Io(io_error) => write!(f, "{}", io_error.to_string()),
            ZakocmpError::Config(message) | ZakocmpError::Snapshot(message) | ZakocmpError::Unknown(message) => write!(f, "{}", message),
        }
    }
}
<commit_msg>errors: pass through rustfmt<commit_after>// This module defines a unified error type used across zakocmp.

use std::string::String;

#[derive(Debug)]
pub enum ZakocmpError {
    // Propagates I/O errors (e.g. from reading actual files).
    Io(std::io::Error),
    // Describes problems with zakocmp configuration files.
    Config(String),
    // Describes problems with zakocmp snapshot files.
    Snapshot(String),
    // Describes unknown or unspecified errors.
    Unknown(String),
}

impl std::fmt::Display for ZakocmpError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ZakocmpError::Io(io_error) => write!(f, "{}", io_error.to_string()),
            ZakocmpError::Config(message)
            | ZakocmpError::Snapshot(message)
            | ZakocmpError::Unknown(message) => write!(f, "{}", message),
        }
    }
}
<|endoftext|>


<commit_before>/* automatically generated by rust-bindgen */

use libc::*;
use xlib::{Display, Drawable, Visual, Screen, Pixmap};
use cairo::cairo_surface_t;

#[link_name="cairo"]
extern mod bindgen {

fn cairo_xlib_surface_create(++arg0: *Display, ++arg1: Drawable, ++arg2: *Visual, ++arg3: c_int, ++arg4: c_int) -> *cairo_surface_t;

fn cairo_xlib_surface_create_for_bitmap(++arg0: *Display, ++arg1: Pixmap, ++arg2: *Screen, ++arg3: c_int, ++arg4: c_int) -> *cairo_surface_t;

fn cairo_xlib_surface_set_size(++arg0: *cairo_surface_t, ++arg1: c_int, ++arg2: c_int);

fn cairo_xlib_surface_set_drawable(++arg0: *cairo_surface_t, ++arg1: Drawable, ++arg2: c_int, ++arg3: c_int);

fn cairo_xlib_surface_get_display(++arg0: *cairo_surface_t) -> *Display;

fn cairo_xlib_surface_get_drawable(++arg0: *cairo_surface_t) -> Drawable;

fn cairo_xlib_surface_get_screen(++arg0: *cairo_surface_t) -> *Screen;

fn cairo_xlib_surface_get_visual(++arg0: *cairo_surface_t) -> *Visual;

fn cairo_xlib_surface_get_depth(++arg0: *cairo_surface_t) -> c_int;

fn cairo_xlib_surface_get_width(++arg0: *cairo_surface_t) -> c_int;

fn cairo_xlib_surface_get_height(++arg0: *cairo_surface_t) -> c_int;

}
<commit_msg>Fix visibility of cairo::bindgen.<commit_after>/* automatically generated by rust-bindgen */

extern mod xlib;

use libc::*;
use xlib::{Display, Drawable, Visual, Screen, Pixmap};
use cairo::cairo_surface_t;

#[link_name="cairo"]
pub extern mod bindgen {

fn cairo_xlib_surface_create(++arg0: *Display, ++arg1: Drawable, ++arg2: *Visual, ++arg3: c_int, ++arg4: c_int) -> *cairo_surface_t;

fn cairo_xlib_surface_create_for_bitmap(++arg0: *Display, ++arg1: Pixmap, ++arg2: *Screen, ++arg3: c_int, ++arg4: c_int) -> *cairo_surface_t;

fn cairo_xlib_surface_set_size(++arg0: *cairo_surface_t, ++arg1: c_int, ++arg2: c_int);

fn cairo_xlib_surface_set_drawable(++arg0: *cairo_surface_t, ++arg1: Drawable, ++arg2: c_int, ++arg3: c_int);

fn cairo_xlib_surface_get_display(++arg0: *cairo_surface_t) -> *Display;

fn cairo_xlib_surface_get_drawable(++arg0: *cairo_surface_t) -> Drawable;

fn cairo_xlib_surface_get_screen(++arg0: *cairo_surface_t) -> *Screen;

fn cairo_xlib_surface_get_visual(++arg0: *cairo_surface_t) -> *Visual;

fn cairo_xlib_surface_get_depth(++arg0: *cairo_surface_t) -> c_int;

fn cairo_xlib_surface_get_width(++arg0: *cairo_surface_t) -> c_int;

fn cairo_xlib_surface_get_height(++arg0: *cairo_surface_t) -> c_int;

}
<|endoftext|>


<commit_before># Rust solution via @jrick

use std::cmp;
use std::num::{Int, NumCast};

fn percents<T: Int>(input: &Vec<T>) -> Vec<f64> {
    let mul = f64::from(input.iter().fold(T::zero(), |m, &e| cmp::max(m, e))).unwrap();
    input.iter().map(|elem| mul * f64::from(*elem).unwrap()).collect()
}

fn main() {
    let input = vec![99334, 1, 2, 3, 4, 5, 6, 7, 8, 9, 99991];
    let out = percents(&input);
    println!("{:?}", out);
}
<commit_msg>Print minimum value as 0%<commit_after>// Rust solution via @jrick

use std::cmp;
use std::num::{Int, NumCast};

fn percents<T: Int>(input: &Vec<T>) -> Vec<f64> {
    let (min, max) = input.iter().fold((T::max_value(), T::min_value()),
        |m, &e| (cmp::min(m.0, e), cmp::max(m.1, e))
    );
    let diff = f64::from(max - min).unwrap();
    input.iter().map(|elem| f64::from(*elem - min).unwrap() / diff).collect()
}

fn main() {
    let input = vec![99334, 100, 200, 300, 99991];
    let out = percents(&input);
    println!("{:?}", out);
}
<|endoftext|>


<commit_before>extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use structopt::StructOpt;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

type Position = usize;
type Name = char;

enum Operation {
    Spin(Position),
    Exchange(Position, Position),
    Partner(Name, Name),
}

impl std::str::FromStr for Operation {
    type Err = String;
    fn from_str(input: &str) -> Result<Self, Self::Err> {
        let mut chars = input.trim().chars();
        match chars.next() {
            Some('s') => chars.as_str().parse().map(Operation::Spin).map_err(
                |_| format!("Could not parse position from {}", chars.as_str()),
            ),
            Some('x') => {
                let mut split = chars.as_str().split('/');
                match (split.next(), split.next()) {
                    (Some(a), Some(b)) => Ok(Operation::Exchange(
                        a.parse().map_err(|_| {
                            format!("Could not parse {} as position", a)
                        })?,
                        b.parse().map_err(|_| {
                            format!("Could not parse {} as position", b)
                        })?,
                    )),
                    _ => Err(format!("Could not parse {} as Operation", input)),
                }
            },
            Some('p') => {
                let mut split = chars.as_str().split('/');
                match (split.next(), split.next()) {
                    (Some(a), Some(b)) => Ok(Operation::Partner(
                        a.parse().map_err(|_| {
                            format!("Could not parse {} as name", a)
                        })?,
                        b.parse().map_err(|_| {
                            format!("Could not parse {} as name", b)
                        })?,
                    )),
                    _ => Err(format!("Could not parse {} as Operation", input)),
                }
            }
            _ => Err(format!("Could not parse {} as Operation", input)),
        }
    }
}

fn part1(initial: &str, input: &str) -> String {
    let mut result = initial.to_owned();
    let instructions: Vec<Operation> =
        input.split(',').map(|s| s.parse().unwrap()).collect();
    for instr in instructions {
        match instr {
            Operation::Spin(p) => {
                result = {
                    let split = result.split_at(result.len() - p);
                    let mut swapped = split.1.to_owned();
                    swapped.push_str(split.0);
                    swapped
                }
            }
            Operation::Exchange(a, b) => {
                unsafe { result.as_bytes_mut() }.swap(a, b);
            }
            Operation::Partner(a, b) => {
                let loc_a =
                    result.find(a).expect(&format!("Could not find {}", a));
                let loc_b =
                    result.find(b).expect(&format!("Could not find {}", b));
                unsafe { result.as_bytes_mut() }.swap(loc_a, loc_b);
            }
        }
    }
    result
}

fn main() {
    let opt = Opt::from_args();
    let mut contents = String::new();
    if opt.input.to_str() == Some("-") {
        std::io::stdin()
            .read_to_string(&mut contents)
            .expect("could not read stdin");
    } else {
        let mut file = File::open(&opt.input)
            .expect(&format!("file {} not found", opt.input.display()));
        file.read_to_string(&mut contents)
            .expect(&format!("could not read file {}", opt.input.display()));
    }
    println!("Part 1: {}", part1("abcdefghijklmnop", &contents));
}

#[derive(StructOpt, Debug)]
#[structopt(name = "day13", about = "Advent of code 2017 day 13")]
struct Opt {
    #[structopt(help = "Input file", parse(from_os_str))] input: PathBuf,
}

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

    #[test]
    fn part1_test() {
        assert_eq!(part1("abcde", "s1,x3/4,pe/b"), "baedc");
    }
}
<commit_msg>2017 day 16 part 02<commit_after>extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use structopt::StructOpt;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

type Position = usize;
type Name = char;

enum Operation {
    Spin(Position),
    Exchange(Position, Position),
    Partner(Name, Name),
}

impl std::str::FromStr for Operation {
    type Err = String;
    fn from_str(input: &str) -> Result<Self, Self::Err> {
        let mut chars = input.trim().chars();
        match chars.next() {
            Some('s') => chars.as_str().parse().map(Operation::Spin).map_err(
                |_| format!("Could not parse position from {}", chars.as_str()),
            ),
            Some('x') => {
                let mut split = chars.as_str().split('/');
                match (split.next(), split.next()) {
                    (Some(a), Some(b)) => Ok(Operation::Exchange(
                        a.parse().map_err(|_| {
                            format!("Could not parse {} as position", a)
                        })?,
                        b.parse().map_err(|_| {
                            format!("Could not parse {} as position", b)
                        })?,
                    )),
                    _ => Err(format!("Could not parse {} as Operation", input)),
                }
            },
            Some('p') => {
                let mut split = chars.as_str().split('/');
                match (split.next(), split.next()) {
                    (Some(a), Some(b)) => Ok(Operation::Partner(
                        a.parse().map_err(|_| {
                            format!("Could not parse {} as name", a)
                        })?,
                        b.parse().map_err(|_| {
                            format!("Could not parse {} as name", b)
                        })?,
                    )),
                    _ => Err(format!("Could not parse {} as Operation", input)),
                }
            }
            _ => Err(format!("Could not parse {} as Operation", input)),
        }
    }
}

fn cycle_len(initial: &str, input: &str) -> usize {
    let mut cycle_len = 1;
    let mut changed = part1(initial, input);
    while changed != initial {
        changed = part1(&changed, input);
        cycle_len += 1;
    }
    cycle_len
}

fn part1(initial: &str, input: &str) -> String {
    let mut result = initial.to_owned();
    let instructions: Vec<Operation> =
        input.split(',').map(|s| s.parse().unwrap()).collect();
    for instr in instructions {
        match instr {
            Operation::Spin(p) => {
                result = {
                    let split = result.split_at(result.len() - p);
                    let mut swapped = split.1.to_owned();
                    swapped.push_str(split.0);
                    swapped
                }
            }
            Operation::Exchange(a, b) => {
                unsafe { result.as_bytes_mut() }.swap(a, b);
            }
            Operation::Partner(a, b) => {
                let loc_a =
                    result.find(a).expect(&format!("Could not find {}", a));
                let loc_b =
                    result.find(b).expect(&format!("Could not find {}", b));
                unsafe { result.as_bytes_mut() }.swap(loc_a, loc_b);
            }
        }
    }
    result
}

fn part2(initial: &str, input: &str, count: usize) -> String {
    let cycle = cycle_len(initial, input);
    let mut result = initial.to_owned();
    for _ in 0..(count % cycle) {
        result = part1(&result, input);
    }
    result
}

fn main() {
    let opt = Opt::from_args();
    let mut contents = String::new();
    if opt.input.to_str() == Some("-") {
        std::io::stdin()
            .read_to_string(&mut contents)
            .expect("could not read stdin");
    } else {
        let mut file = File::open(&opt.input)
            .expect(&format!("file {} not found", opt.input.display()));
        file.read_to_string(&mut contents)
            .expect(&format!("could not read file {}", opt.input.display()));
    }
    println!("Part 1: {}", part1("abcdefghijklmnop", &contents));
    println!("Part 2: {}", part2("abcdefghijklmnop", &contents, 1_000_000_000));
}

#[derive(StructOpt, Debug)]
#[structopt(name = "day13", about = "Advent of code 2017 day 13")]
struct Opt {
    #[structopt(help = "Input file", parse(from_os_str))] input: PathBuf,
}

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

    #[test]
    fn part1_test() {
        assert_eq!(part1("abcde", "s1,x3/4,pe/b"), "baedc");
    }

    #[test]
    fn part4_test() {
        assert_eq!(part2("abcde", "s1,x3/4,pe/b", 2), "ceadb");
    }
}
<|endoftext|>


<commit_before>use std::ptr;
use std::cmp::{min, max};

use geom::point::Point;
use renderer::Renderer;
use frame::Frame;
use draw::RGB;
use raster::create_default_vec;

use super::Scene;
use super::Poly;

pub struct DevelRenderer {
   scene: Scene,
   aliased: Vec<RGB>,
}

pub const SUBDIVISIONS: usize = 3;

impl DevelRenderer {
   #[inline]
   pub fn new(scene: Scene) -> Self {
      DevelRenderer {
         scene: scene,

         aliased: vec!(),
      }
   }

   fn check_resize(&mut self, width: u32, height: u32) {
      if self.aliased.len() == (width * height) as usize * SUBDIVISIONS * SUBDIVISIONS {
         return;
      }

      self.aliased.resize((width * height) as usize * SUBDIVISIONS * SUBDIVISIONS, RGB::new(0, 0, 0));
   }

   #[inline]
   fn clear(&mut self) {
      let len = self.aliased.len();
      let vp = self.aliased.as_mut_ptr();

      unsafe {
         ptr::write_bytes(vp, 0, len);
      }
   }

   #[inline]
   fn render_aliased(&mut self, frame: &mut Frame) {
      let mut aliased: &mut Vec<RGB> = self.aliased.as_mut();

      let aliased_width = frame.width as i64 * SUBDIVISIONS as i64;
      let aliased_height = frame.height as i64 * SUBDIVISIONS as i64;

      for poly in &self.scene.polys {
         let edges = get_poly_edges(poly);

         let mut sorted_y = create_default_vec(edges.len());

         sorted_edges(&edges, &mut sorted_y);

         let mut advancers = Vec::new();

         for edge in &*edges {
            let advancer = YAxisAdvancer::new(edge);
            advancers.push(advancer);
         }

         let mut y = edges[sorted_y[0]].p1.y;

         if y >= 0 && y < aliased_height {
            for i in 0..sorted_y.len() {
               let edge_index: usize = sorted_y[i];

               if edges[edge_index].p1.y != y {
                  break;
               }

               let x = edges[edge_index].p1.x;

               if x >= 0 && x < aliased_width {
                  aliased[y as usize * aliased_width as usize + x as usize] = poly.color;
               }
            }
         }

         let mut next_y_index = 0;

         let mut active = Vec::new();

         let mut sorted_end_y = create_default_vec(sorted_y.len());

         for i in 0..sorted_y.len() {
            sorted_end_y[i] = i;
         }

         loop {
            let mut removed = 0;

            loop {
               if removed == active.len() {
                  break;
               }

               let edge_index: usize = active[removed];

               if edges[edge_index].p2.y != y {
                  break;
               }

               removed += 1;
            }

            if removed != 0 {
               active.drain(0..removed);
            }

            loop {
               if next_y_index >= sorted_y.len() {
                  break;
               }

               let edge_index = sorted_y[next_y_index];

               if edges[edge_index].p1.y != y {
                  break;
               }

               active.push(edge_index);

               active.sort_by(|a, b| {
                  edges[*a].p2.y.cmp(&edges[*b].p2.y)
               });

               next_y_index += 1;
            }

            if active.len() == 0 {
               break;
            }

            y += 1;

            let mut xs = Vec::new();

            for i in 0..active.len() {
               let edge_index = active[i];
               xs.push(
                  advancers[edge_index].advance()
               );
            }

            if y < 0 {
               continue;
            }

            if y >= aliased_height {
               break;
            }

            xs.sort();

            assert!(xs.len() % 2 == 0);

            for i in 0..xs.len() / 2 {
               let left_x = max(xs[i * 2], 0);
               let right_x = min(xs[i * 2 + 1], aliased_width);

               if left_x >= aliased_width || right_x < 0 {
                  continue;
               }

               for x in left_x..right_x {
                  aliased[y as usize * aliased_width as usize + x as usize] = poly.color;
               }
            }
         }
      }
   }

   #[inline]
   fn downsample(&mut self, frame: &mut Frame) {
      let aliased: &mut Vec<RGB> = self.aliased.as_mut();

      let (width, height) = (frame.width as usize, frame.height as usize);

      for y in 0..height {
         for x in 0..width {
            let color = calc_pixel_color(aliased, width, x, y);

            frame.put_pixel(x as i32, y as i32, &color);
         }
      }
   }
}

impl Renderer for DevelRenderer {
   #[inline]
   fn init(&mut self, width: u32, height: u32) {
      self.check_resize(width, height);
   }

   #[inline]
   fn render(&mut self, frame: &mut Frame) {
      self.check_resize(frame.width, frame.height);

      self.clear();

      self.render_aliased(frame);

      self.downsample(frame);
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Edge {
   p1: Point,
   p2: Point,
}

impl Edge {
   #[inline]
   fn new(p1: Point, p2: Point) -> Self {
      Edge {
         p1: p1,
         p2: p2,
      }
   }
}

struct YAxisAdvancer {
   delta: f64,
   f64x: f64,
}

impl YAxisAdvancer {
   #[inline]
   fn new(edge: &Edge) -> Self {
      let dx = edge.p2.x - edge.p1.x;
      let dy = edge.p2.y - edge.p1.y;

      let delta = dx as f64 / dy as f64;
      let f64x = edge.p1.x as f64;

      YAxisAdvancer {
         delta: delta,
         f64x: f64x,
      }
   }

   #[inline]
   fn advance(&mut self) -> i64 {
      self.f64x += self.delta;
      self.f64x.round() as i64
   }
}

#[inline]
fn calc_pixel_color(aliased: &mut Vec<RGB>, width: usize, x: usize, y: usize) -> RGB {
   let mut r: u16 = 0;
   let mut g: u16 = 0;
   let mut b: u16 = 0;
   for box_y in 0..SUBDIVISIONS {
      for box_x in 0..SUBDIVISIONS {
         let pos = (box_y + y * SUBDIVISIONS) * width * SUBDIVISIONS + box_x + x * SUBDIVISIONS;
         let color = &aliased[pos];
         r += color.r as u16;
         g += color.g as u16;
         b += color.b as u16;
      }
   }

   let divisor = (SUBDIVISIONS * SUBDIVISIONS) as u16;

   r /= divisor;
   g /= divisor;
   b /= divisor;

   RGB::new(r as u8, g as u8, b as u8)
}

fn get_poly_edges(poly: &Poly) -> Vec<Edge> {
   let mut edges = Vec::new();

   fill_edges_from_points(&mut edges, &poly.points);

   for points in &poly.holes {
      fill_edges_from_points(&mut edges, points);
   }

   edges
}

#[inline]
fn fill_edges_from_points(edges: &mut Vec<Edge>, points: &Vec<Point>) {
   if points.len() < 2 {
      return;
   }

   for slice in points.windows(2) {
      match to_renderable_edge(slice[0], slice[1]) {
         Some(edge) => edges.push(edge),
         _ => {}
      }
   }

   match to_renderable_edge(points[points.len() - 1], points[0]) {
      Some(edge) => edges.push(edge),
      _ => {}
   }
}

#[inline]
fn to_renderable_edge(p1: Point, p2: Point) -> Option<Edge> {
   if p1.y == p2.y {
      None
   } else if p2.y > p1.y {
      Some(Edge::new(p1, p2))
   } else {
      Some(Edge::new(p2, p1))
   }
}

#[inline]
fn sorted_edges(edges: &Vec<Edge>, sorted: &mut Vec<usize>) {
   for i in 0..edges.len() {
      sorted[i] = i;
   }

   sorted.sort_by(|a, b| {
      edges[*a].p1.y.cmp(&edges[*b].p1.y)
   });
}

<commit_msg>All dev rasterizer vecs as members<commit_after>use std::ptr;
use std::cmp::{min, max};

use geom::point::Point;
use renderer::Renderer;
use frame::Frame;
use draw::RGB;
use raster::create_default_vec;

use super::Scene;
use super::Poly;

pub struct DevelRenderer {
   scene: Scene,
   aliased: Vec<RGB>,
   advancers: Vec<YAxisAdvancer>,
   active: Vec<usize>,
   xs: Vec<i64>,
}

pub const SUBDIVISIONS: usize = 3;

impl DevelRenderer {
   #[inline]
   pub fn new(scene: Scene) -> Self {
      DevelRenderer {
         scene: scene,

         aliased: Vec::new(),

         advancers: Vec::new(),

         active: Vec::new(),

         xs: Vec::new(),
      }
   }

   fn check_resize(&mut self, width: u32, height: u32) {
      if self.aliased.len() == (width * height) as usize * SUBDIVISIONS * SUBDIVISIONS {
         return;
      }

      self.aliased.resize((width * height) as usize * SUBDIVISIONS * SUBDIVISIONS, RGB::new(0, 0, 0));
   }

   #[inline]
   fn clear(&mut self) {
      let len = self.aliased.len();
      let vp = self.aliased.as_mut_ptr();

      unsafe {
         ptr::write_bytes(vp, 0, len);
      }
   }

   #[inline]
   fn render_aliased(&mut self, frame: &mut Frame) {
      let aliased_width = frame.width as i64 * SUBDIVISIONS as i64;
      let aliased_height = frame.height as i64 * SUBDIVISIONS as i64;

      for poly in &self.scene.polys {
         let edges = get_poly_edges(poly);

         let mut sorted_y = create_default_vec(edges.len());

         sorted_edges(&edges, &mut sorted_y);

         for edge in &*edges {
            let advancer = YAxisAdvancer::new(edge);
            self.advancers.push(advancer);
         }

         let mut y = edges[sorted_y[0]].p1.y;

         if y >= 0 && y < aliased_height {
            for i in 0..sorted_y.len() {
               let edge_index: usize = sorted_y[i];

               if edges[edge_index].p1.y != y {
                  break;
               }

               let x = edges[edge_index].p1.x;

               if x >= 0 && x < aliased_width {
                  self.aliased[y as usize * aliased_width as usize + x as usize] = poly.color;
               }
            }
         }

         let mut next_y_index = 0;

         let mut sorted_end_y = create_default_vec(sorted_y.len());

         for i in 0..sorted_y.len() {
            sorted_end_y[i] = i;
         }

         loop {
            let mut removed = 0;

            loop {
               if removed == self.active.len() {
                  break;
               }

               let edge_index: usize = self.active[removed];

               if edges[edge_index].p2.y != y {
                  break;
               }

               removed += 1;
            }

            if removed != 0 {
               self.active.drain(0..removed);
            }

            loop {
               if next_y_index >= sorted_y.len() {
                  break;
               }

               let edge_index = sorted_y[next_y_index];

               if edges[edge_index].p1.y != y {
                  break;
               }

               self.active.push(edge_index);

               self.active.sort_by(|a, b| {
                  edges[*a].p2.y.cmp(&edges[*b].p2.y)
               });

               next_y_index += 1;
            }

            if self.active.len() == 0 {
               break;
            }

            y += 1;

            self.xs.truncate(0);

            for i in 0..self.active.len() {
               let edge_index = self.active[i];
               self.xs.push(
                  self.advancers[edge_index].advance()
               );
            }

            if y < 0 {
               continue;
            }

            if y >= aliased_height {
               break;
            }

            self.xs.sort();

            assert!(self.xs.len() % 2 == 0);

            for i in 0..self.xs.len() / 2 {
               let left_x = max(self.xs[i * 2], 0);
               let right_x = min(self.xs[i * 2 + 1], aliased_width);

               if left_x >= aliased_width || right_x < 0 {
                  continue;
               }

               for x in left_x..right_x {
                  self.aliased[y as usize * aliased_width as usize + x as usize] = poly.color;
               }
            }
         }

         self.advancers.truncate(0);
         self.active.truncate(0);
      }
   }

   #[inline]
   fn downsample(&mut self, frame: &mut Frame) {
      let aliased: &mut Vec<RGB> = self.aliased.as_mut();

      let (width, height) = (frame.width as usize, frame.height as usize);

      for y in 0..height {
         for x in 0..width {
            let color = calc_pixel_color(aliased, width, x, y);

            frame.put_pixel(x as i32, y as i32, &color);
         }
      }
   }
}

impl Renderer for DevelRenderer {
   #[inline]
   fn init(&mut self, width: u32, height: u32) {
      self.check_resize(width, height);
   }

   #[inline]
   fn render(&mut self, frame: &mut Frame) {
      self.check_resize(frame.width, frame.height);

      self.clear();

      self.render_aliased(frame);

      self.downsample(frame);
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Edge {
   p1: Point,
   p2: Point,
}

impl Edge {
   #[inline]
   fn new(p1: Point, p2: Point) -> Self {
      Edge {
         p1: p1,
         p2: p2,
      }
   }
}

struct YAxisAdvancer {
   delta: f64,
   f64x: f64,
}

impl YAxisAdvancer {
   #[inline]
   fn new(edge: &Edge) -> Self {
      let dx = edge.p2.x - edge.p1.x;
      let dy = edge.p2.y - edge.p1.y;

      let delta = dx as f64 / dy as f64;
      let f64x = edge.p1.x as f64;

      YAxisAdvancer {
         delta: delta,
         f64x: f64x,
      }
   }

   #[inline]
   fn advance(&mut self) -> i64 {
      self.f64x += self.delta;
      self.f64x.round() as i64
   }
}

#[inline]
fn calc_pixel_color(aliased: &mut Vec<RGB>, width: usize, x: usize, y: usize) -> RGB {
   let mut r: u16 = 0;
   let mut g: u16 = 0;
   let mut b: u16 = 0;
   for box_y in 0..SUBDIVISIONS {
      for box_x in 0..SUBDIVISIONS {
         let pos = (box_y + y * SUBDIVISIONS) * width * SUBDIVISIONS + box_x + x * SUBDIVISIONS;
         let color = &aliased[pos];
         r += color.r as u16;
         g += color.g as u16;
         b += color.b as u16;
      }
   }

   let divisor = (SUBDIVISIONS * SUBDIVISIONS) as u16;

   r /= divisor;
   g /= divisor;
   b /= divisor;

   RGB::new(r as u8, g as u8, b as u8)
}

fn get_poly_edges(poly: &Poly) -> Vec<Edge> {
   let mut edges = Vec::new();

   fill_edges_from_points(&mut edges, &poly.points);

   for points in &poly.holes {
      fill_edges_from_points(&mut edges, points);
   }

   edges
}

#[inline]
fn fill_edges_from_points(edges: &mut Vec<Edge>, points: &Vec<Point>) {
   if points.len() < 2 {
      return;
   }

   for slice in points.windows(2) {
      match to_renderable_edge(slice[0], slice[1]) {
         Some(edge) => edges.push(edge),
         _ => {}
      }
   }

   match to_renderable_edge(points[points.len() - 1], points[0]) {
      Some(edge) => edges.push(edge),
      _ => {}
   }
}

#[inline]
fn to_renderable_edge(p1: Point, p2: Point) -> Option<Edge> {
   if p1.y == p2.y {
      None
   } else if p2.y > p1.y {
      Some(Edge::new(p1, p2))
   } else {
      Some(Edge::new(p2, p1))
   }
}

#[inline]
fn sorted_edges(edges: &Vec<Edge>, sorted: &mut Vec<usize>) {
   for i in 0..edges.len() {
      sorted[i] = i;
   }

   sorted.sort_by(|a, b| {
      edges[*a].p1.y.cmp(&edges[*b].p1.y)
   });
}

<|endoftext|>


<commit_before>// Copyright (C) 2020 Christian Amsüss
//
// This file is subject to the terms and conditions of the GNU Lesser
// General Public License v2.1. See the file LICENSE in the top level
// directory for more details.
#![no_std]

use riot_wrappers::{riot_main, println};
use riot_wrappers::{gcoap, thread, ztimer, gnrc};

use coap_handler_implementations::{ReportingHandlerBuilder, HandlerBuilder};

riot_main!(main);

fn main() {
    extern "C" {
        fn do_vfs_init();
    }

    unsafe { do_vfs_init() };

    let handler = coap_message_demos::full_application_tree(None)
        .below(&["ps"], riot_coap_handler_demos::ps::ps_tree())
        .below(&["vfs"], riot_coap_handler_demos::vfs::vfs("/const"))
        .with_wkc()
        ;
    let mut handler = riot_wrappers::coap_handler::GcoapHandler(handler);

    let mut listener = gcoap::SingleHandlerListener::new_catch_all(&mut handler);

    gcoap::scope(|greg| {
        greg.register(&mut listener);

        println!("CoAP server ready; waiting for interfaces to settle before reporting addresses...");

        let sectimer = ztimer::ZTimer::sec();
        sectimer.sleep_ticks(2);

        for netif in gnrc::Netif::all() {
            println!("Active interface from PID {:?} ({:?})", netif.pid(), netif.pid().get_name().unwrap_or("unnamed"));
            match netif.ipv6_addrs() {
                Ok(addrs) => {
                    for a in addrs.addresses() {
                        println!("    Address {:?}", a);
                    }
                }
                _ => {
                    println!("    Does not support IPv6.");
                }
            }
        }

        // Sending main thread to sleep; can't return or the Gcoap handler would need to be
        // deregistered (which it can't).
        loop { thread::sleep(); }
    })
}
<commit_msg>examples/rust-gcoap: Follow renames / deprecations of riot-wrappers<commit_after>// Copyright (C) 2020 Christian Amsüss
//
// This file is subject to the terms and conditions of the GNU Lesser
// General Public License v2.1. See the file LICENSE in the top level
// directory for more details.
#![no_std]

use riot_wrappers::{riot_main, println};
use riot_wrappers::{gcoap, thread, ztimer, gnrc};

use coap_handler_implementations::{ReportingHandlerBuilder, HandlerBuilder};

riot_main!(main);

fn main() {
    extern "C" {
        fn do_vfs_init();
    }

    unsafe { do_vfs_init() };

    let handler = coap_message_demos::full_application_tree(None)
        .below(&["ps"], riot_coap_handler_demos::ps::ps_tree())
        .below(&["vfs"], riot_coap_handler_demos::vfs::vfs("/const"))
        .with_wkc()
        ;
    let mut handler = riot_wrappers::coap_handler::GcoapHandler(handler);

    let mut listener = gcoap::SingleHandlerListener::new_catch_all(&mut handler);

    gcoap::scope(|greg| {
        greg.register(&mut listener);

        println!("CoAP server ready; waiting for interfaces to settle before reporting addresses...");

        let sectimer = ztimer::Clock::sec();
        sectimer.sleep_ticks(2);

        for netif in gnrc::Netif::all() {
            println!("Active interface from PID {:?} ({:?})", netif.pid(), netif.pid().get_name().unwrap_or("unnamed"));
            match netif.ipv6_addrs() {
                Ok(addrs) => {
                    for a in &addrs {
                        println!("    Address {:?}", a);
                    }
                }
                _ => {
                    println!("    Does not support IPv6.");
                }
            }
        }

        // Sending main thread to sleep; can't return or the Gcoap handler would need to be
        // deregistered (which it can't).
        loop { thread::sleep(); }
    })
}
<|endoftext|>


<commit_before>use glib::IsA;
use glib::translate::{ToGlibPtr, from_glib_full, from_glib_none};

use super::{DOMCSSStyleDeclaration, DOMDOMWindow, DOMElement};
use dom_dom_selection::DOMDOMSelection;

pub trait DOMDOMWindowExtManual {
    fn get_computed_style<T: IsA<DOMElement>>(&self, element: &T, pseudo_element: Option<&str>) -> Option<DOMCSSStyleDeclaration>;
    fn get_selection(&self) -> Option<DOMDOMSelection>;
}

impl DOMDOMWindowExtManual for DOMDOMWindow {
    fn get_computed_style<T: IsA<DOMElement>>(&self, element: &T, pseudo_element: Option<&str>) -> Option<DOMCSSStyleDeclaration> {
        unsafe {
            from_glib_full(sys::webkit_dom_dom_window_get_computed_style(self.to_glib_none().0, element.to_glib_none().0, pseudo_element.to_glib_none().0))
        }
    }

    fn get_selection(&self) -> Option<DOMDOMSelection> {
        unsafe { from_glib_none(sys::webkit_dom_dom_window_get_selection(self.to_glib_none().0)) }
    }
}

mod sys {
    use ffi;

    use libc::c_char;
    use dom_dom_selection::sys::WebKitDOMDOMSelection;

    extern "C" {
        pub fn webkit_dom_dom_window_get_computed_style(window: *mut ffi::WebKitDOMDOMWindow, element: *mut ffi::WebKitDOMElement, pseudo_element: *const c_char) -> *mut ffi::WebKitDOMCSSStyleDeclaration;
        pub fn webkit_dom_dom_window_get_selection(window: *mut ffi::WebKitDOMDOMWindow) -> *mut WebKitDOMDOMSelection;
    }
}
<commit_msg>Added DOMDOMWindow::get_frame_element().<commit_after>use std::ffi::CString;
use std::ptr::null_mut;

use ffi;
use glib::IsA;
use glib::translate::{ToGlibPtr, from_glib_full, from_glib_none};
use gobject_sys::g_object_get;
use libc::c_void;

use super::{DOMCSSStyleDeclaration, DOMDOMWindow, DOMElement};
use dom_dom_selection::DOMDOMSelection;

pub trait DOMDOMWindowExtManual {
    fn get_computed_style<T: IsA<DOMElement>>(&self, element: &T, pseudo_element: Option<&str>) -> Option<DOMCSSStyleDeclaration>;
    fn get_frame_element(&self) -> Option<DOMElement>;
    fn get_selection(&self) -> Option<DOMDOMSelection>;
}

impl DOMDOMWindowExtManual for DOMDOMWindow {
    fn get_computed_style<T: IsA<DOMElement>>(&self, element: &T, pseudo_element: Option<&str>) -> Option<DOMCSSStyleDeclaration> {
        unsafe {
            from_glib_full(sys::webkit_dom_dom_window_get_computed_style(self.to_glib_none().0, element.to_glib_none().0, pseudo_element.to_glib_none().0))
        }
    }

    fn get_frame_element(&self) -> Option<DOMElement> {
        let property_name = CString::new("frame-element").unwrap();
        let mut value: *mut ffi::WebKitDOMElement = null_mut();;
        let window: *mut ffi::WebKitDOMDOMWindow = self.to_glib_none().0;
        unsafe {
            g_object_get(window as *mut _, property_name.as_ptr(), &mut value as *mut _, null_mut() as *mut c_void);
        }
        let frame_element = unsafe { from_glib_none(value) };
        frame_element
    }

    fn get_selection(&self) -> Option<DOMDOMSelection> {
        unsafe { from_glib_none(sys::webkit_dom_dom_window_get_selection(self.to_glib_none().0)) }
    }
}

mod sys {
    use ffi;

    use libc::c_char;
    use dom_dom_selection::sys::WebKitDOMDOMSelection;

    extern "C" {
        pub fn webkit_dom_dom_window_get_computed_style(window: *mut ffi::WebKitDOMDOMWindow, element: *mut ffi::WebKitDOMElement, pseudo_element: *const c_char) -> *mut ffi::WebKitDOMCSSStyleDeclaration;
        pub fn webkit_dom_dom_window_get_selection(window: *mut ffi::WebKitDOMDOMWindow) -> *mut WebKitDOMDOMSelection;
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Serial port driver
//!
//! Create new serial ports by calling `PortNum::new()`. If the system supports
//! that port, `Some(Port)` will be returned. Otherwise, if the system
//! does not have that port number (such as `COM3` and `COM4`) on many machines,
//! `PortNum::new()` returns `None`.
//!
//! See [the OS Dev wiki](http://wiki.osdev.org/Serial_Ports) for more
//! information.

use spin::Mutex;

use ::arch::bda;

use ::io::{Read, Write, Port};
use ::util;
//
// /// Address of the BIOS Data Area (BDA)
// /// where the serial port addresses are stored.
// const BDA_ADDR: usize = 0x400;

lazy_static! {
    // static ref BDA_SERIAL_INFO: [u16; 4]
    //     = unsafe { *(BDA_ADDR as *const [u16; 4]) };
    // TODO: serial ports are currently behind a mutex; can they be read-write
    //       locked instead? I think multiple threads should be able to read
    //       from a serial port at the same time without causing trouble?
    //          - eliza, 10/9/2016
    pub static ref COM1: Option<Mutex<SerialPort>>
        = bda::ports::com1().map(SerialPort::new).map(Mutex::new);

    pub static ref COM2: Option<Mutex<SerialPort>>
        = bda::ports::com2().map(SerialPort::new).map(Mutex::new);

    pub static ref COM3: Option<Mutex<SerialPort>>
        = bda::ports::com3().map(SerialPort::new).map(Mutex::new);

    pub static ref COM4: Option<Mutex<SerialPort>>
        = bda::ports::com4().map(SerialPort::new).map(Mutex::new);
}

/// A serial port
pub struct SerialPort { data_port: Port<u8>
                      , status_port: Port<u8>
                      }

impl SerialPort {

    fn new(port: u16) -> SerialPort {
         // Disable all interrupts
        Port::<u8>::new(port + 1).write(0x00);
        // Enable DLAB (set baud rate divisor)
        Port::<u8>::new(port + 3).write(0x80);
        // Set divisor to 38400 baud
        Port::<u8>::new(port + 0).write(0x03); // divisor hi byte
        Port::<u8>::new(port + 1).write(0x00); // divisor lo byte
        // 8 bits, no parity, one stop bit
        Port::<u8>::new(port + 3).write(0x03);
        // Enable FIFO, clear them, with 14-byte threshold
        Port::<u8>::new(port + 2).write(0xC7);
        // IRQs enabled, RTS/DSR set
        Port::<u8>::new(port + 4).write(0x0B);
        Port::<u8>::new(port + 1).write(0x01);

        SerialPort { data_port: Port::<u8>::new(port)
                   , status_port: Port::<u8>::new(port + 5)
                   }
    }

    /// Returns true if the serial port has recieved data
    #[inline]
    pub fn has_byte(&self) -> bool {
        self.status_port.read() & 1 != 0
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.status_port.read() & 0x20 == 0x20
    }

    #[inline]
    pub fn read_byte(&self) -> u8 {
        while !self.has_byte() {};
        self.data_port.read()
    }

    #[inline]
    pub fn write_byte(&self, byte: u8) {
        while !self.is_empty() {};
        self.data_port.write(byte)
    }
}

impl Read for SerialPort {
    type Error = util::Void;

    /// Reads a single byte into the given buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        Ok(match &mut *buf {
            // if the length of the buffer is 0, then obviously
            // no bytes were read
            &mut []                  => 0
            // otherwise, read one byte into the head of the buffer
          , &mut [ref mut head, _..] => { *head = self.read_byte(); 1 }
        })
    }

    /// Reads a new byte into each position in the buffer.
    fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        let mut read_bytes = 0;
        for idx in buf.iter_mut() {
            // for each index in the buffer, read another byte from the port
            *idx = self.read_byte();
            // and increment the number of bytes read (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            read_bytes += 1;
        }
        Ok(read_bytes)
    }
}

impl Write for SerialPort {
    type Error = util::Void;

    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
        let mut written_bytes = 0;
        for byte in buf {
            // write each byte in the buffer to the port
            self.write_byte(*byte);
            // and increment the number of bytes written (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            written_bytes += 1;
        }
        Ok(written_bytes)
    }
}
<commit_msg>[x86_all] implemented core::fmt::Write for SerialPort<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Serial port driver
//!
//! Create new serial ports by calling `PortNum::new()`. If the system supports
//! that port, `Some(Port)` will be returned. Otherwise, if the system
//! does not have that port number (such as `COM3` and `COM4`) on many machines,
//! `PortNum::new()` returns `None`.
//!
//! See [the OS Dev wiki](http://wiki.osdev.org/Serial_Ports) for more
//! information.

use spin::Mutex;

use core::fmt;

use ::arch::bda;
use ::io::Port;
use ::io;
use ::util;
//
// /// Address of the BIOS Data Area (BDA)
// /// where the serial port addresses are stored.
// const BDA_ADDR: usize = 0x400;

lazy_static! {
    // static ref BDA_SERIAL_INFO: [u16; 4]
    //     = unsafe { *(BDA_ADDR as *const [u16; 4]) };
    // TODO: serial ports are currently behind a mutex; can they be read-write
    //       locked instead? I think multiple threads should be able to read
    //       from a serial port at the same time without causing trouble?
    //          - eliza, 10/9/2016
    pub static ref COM1: Option<Mutex<SerialPort>>
        = bda::ports::com1().map(SerialPort::new).map(Mutex::new);

    pub static ref COM2: Option<Mutex<SerialPort>>
        = bda::ports::com2().map(SerialPort::new).map(Mutex::new);

    pub static ref COM3: Option<Mutex<SerialPort>>
        = bda::ports::com3().map(SerialPort::new).map(Mutex::new);

    pub static ref COM4: Option<Mutex<SerialPort>>
        = bda::ports::com4().map(SerialPort::new).map(Mutex::new);
}

/// A serial port
pub struct SerialPort { data_port: Port<u8>
                      , status_port: Port<u8>
                      }

impl SerialPort {

    fn new(port: u16) -> SerialPort {
         // Disable all interrupts
        Port::<u8>::new(port + 1).write(0x00);
        // Enable DLAB (set baud rate divisor)
        Port::<u8>::new(port + 3).write(0x80);
        // Set divisor to 38400 baud
        Port::<u8>::new(port + 0).write(0x03); // divisor hi byte
        Port::<u8>::new(port + 1).write(0x00); // divisor lo byte
        // 8 bits, no parity, one stop bit
        Port::<u8>::new(port + 3).write(0x03);
        // Enable FIFO, clear them, with 14-byte threshold
        Port::<u8>::new(port + 2).write(0xC7);
        // IRQs enabled, RTS/DSR set
        Port::<u8>::new(port + 4).write(0x0B);
        Port::<u8>::new(port + 1).write(0x01);

        SerialPort { data_port: Port::<u8>::new(port)
                   , status_port: Port::<u8>::new(port + 5)
                   }
    }

    /// Returns true if the serial port has recieved data
    #[inline]
    pub fn has_byte(&self) -> bool {
        self.status_port.read() & 1 != 0
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.status_port.read() & 0x20 == 0x20
    }

    #[inline]
    pub fn read_byte(&self) -> u8 {
        while !self.has_byte() {};
        self.data_port.read()
    }

    #[inline]
    pub fn write_byte(&self, byte: u8) {
        while !self.is_empty() {};
        self.data_port.write(byte)
    }
}

impl io::Read for SerialPort {
    type Error = util::Void;

    /// Reads a single byte into the given buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        Ok(match &mut *buf {
            // if the length of the buffer is 0, then obviously
            // no bytes were read
            &mut []                  => 0
            // otherwise, read one byte into the head of the buffer
          , &mut [ref mut head, _..] => { *head = self.read_byte(); 1 }
        })
    }

    /// Reads a new byte into each position in the buffer.
    fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        let mut read_bytes = 0;
        for idx in buf.iter_mut() {
            // for each index in the buffer, read another byte from the port
            *idx = self.read_byte();
            // and increment the number of bytes read (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            read_bytes += 1;
        }
        Ok(read_bytes)
    }
}

impl io::Write for SerialPort {
    type Error = util::Void;

    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
        let mut written_bytes = 0;
        for byte in buf {
            // write each byte in the buffer to the port
            self.write_byte(*byte);
            // and increment the number of bytes written (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            written_bytes += 1;
        }
        Ok(written_bytes)
    }
}

impl fmt::Write for SerialPort {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        for byte in s.bytes() {
            // TODO: more robust error handling here
            self.write_byte(byte);
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use crate::{
    api::{ColorProxy, Error, LilaVariant},
    indexer::IndexerOpt,
    model::{GameId, Speed, UserName},
};
use futures_util::stream::{Stream, StreamExt as _, TryStreamExt as _};
use serde::Deserialize;
use serde_with::{serde_as, DisplayFromStr, FromInto, SpaceSeparator, StringWithSeparator};
use shakmaty::fen::Fen;
use shakmaty::san::San;
use shakmaty::Color;
use std::io;
use tokio::io::AsyncBufReadExt as _;
use tokio_stream::wrappers::LinesStream;
use tokio_util::io::StreamReader;

pub struct Lila {
    client: reqwest::Client,
    opt: IndexerOpt,
}

impl Lila {
    pub fn new(opt: IndexerOpt) -> Lila {
        Lila {
            client: reqwest::Client::builder().build().expect("reqwest client"),
            opt,
        }
    }

    pub async fn user_games(
        &self,
        user: &UserName,
    ) -> Result<impl Stream<Item = Result<Game, Error>>, Error> {
        let stream = self
            .client
            .get(format!("{}/api/games/user/{}", self.opt.lila, user))
            .header("Accept", "application/x-ndjson")
            .send()
            .await
            .and_then(|r| r.error_for_status())
            .map_err(|err| Error::IndexerRequestError(err))?
            .bytes_stream()
            .map_err(|err| io::Error::new(io::ErrorKind::Other, err));

        Ok(Box::pin(
            LinesStream::new(StreamReader::new(stream).lines()).filter_map(|line| async move {
                match line {
                    Ok(line) if line.is_empty() => None,
                    Ok(line) => Some(
                        serde_json::from_str::<Game>(&line)
                            .map_err(|err| Error::IndexerStreamError(err.into())),
                    ),
                    Err(err) => Some(Err(Error::IndexerStreamError(err))),
                }
            }),
        ))
    }
}

#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Game {
    #[serde_as(as = "DisplayFromStr")]
    pub id: GameId,
    pub rated: bool,
    pub created_at: u64,
    pub status: Status,
    pub variant: LilaVariant,
    pub players: Players,
    pub speed: Speed,
    #[serde_as(as = "StringWithSeparator::<SpaceSeparator, San>")]
    pub moves: Vec<San>,
    #[serde_as(as = "Option<FromInto<ColorProxy>>")]
    #[serde(default)]
    pub winner: Option<Color>,
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default)]
    pub initial_fen: Option<Fen>,
}

impl Game {
    pub fn user_name(&self, color: Color) -> Option<&UserName> {
        self.players.by_color(color).user.as_ref().map(|u| &u.name)
    }
}

#[derive(Debug, Deserialize)]
pub struct Players {
    pub white: Player,
    pub black: Player,
}

impl Players {
    fn by_color(&self, color: Color) -> &Player {
        match color {
            Color::White => &self.white,
            Color::Black => &self.black,
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Player {
    #[serde(default)]
    user: Option<User>,
    #[serde(default)]
    rating: Option<u16>,
}

#[serde_as]
#[derive(Debug, Deserialize)]
pub struct User {
    #[serde_as(as = "DisplayFromStr")]
    name: UserName,
}

#[derive(Debug, Deserialize, Copy, Clone)]
#[serde(rename_all = "camelCase")]
pub enum Status {
    Created,
    Started,
    Aborted,
    Mate,
    Resign,
    Stalemate,
    Timeout,
    Draw,
    #[serde(rename = "outoftime")]
    OutOfTime,
    Cheat,
    NoStart,
    UnknownFinish,
    VariantEnd,
}

impl Status {
    pub fn is_ongoing(self) -> bool {
        matches!(self, Status::Created | Status::Started)
    }

    pub fn is_unindexable(self) -> bool {
        matches!(
            self,
            Status::UnknownFinish | Status::NoStart | Status::Aborted
        )
    }
}
<commit_msg>use dateAsc and include ongoing games<commit_after>use crate::{
    api::{ColorProxy, Error, LilaVariant},
    indexer::IndexerOpt,
    model::{GameId, Speed, UserName},
};
use futures_util::stream::{Stream, StreamExt as _, TryStreamExt as _};
use serde::Deserialize;
use serde_with::{serde_as, DisplayFromStr, FromInto, SpaceSeparator, StringWithSeparator};
use shakmaty::fen::Fen;
use shakmaty::san::San;
use shakmaty::Color;
use std::io;
use tokio::io::AsyncBufReadExt as _;
use tokio_stream::wrappers::LinesStream;
use tokio_util::io::StreamReader;

pub struct Lila {
    client: reqwest::Client,
    opt: IndexerOpt,
}

impl Lila {
    pub fn new(opt: IndexerOpt) -> Lila {
        Lila {
            client: reqwest::Client::builder().build().expect("reqwest client"),
            opt,
        }
    }

    pub async fn user_games(
        &self,
        user: &UserName,
    ) -> Result<impl Stream<Item = Result<Game, Error>>, Error> {
        let stream = self
            .client
            .get(format!("{}/api/games/user/{}?sort=dateAsc&ongoing=true", self.opt.lila, user))
            .header("Accept", "application/x-ndjson")
            .send()
            .await
            .and_then(|r| r.error_for_status())
            .map_err(|err| Error::IndexerRequestError(err))?
            .bytes_stream()
            .map_err(|err| io::Error::new(io::ErrorKind::Other, err));

        Ok(Box::pin(
            LinesStream::new(StreamReader::new(stream).lines()).filter_map(|line| async move {
                match line {
                    Ok(line) if line.is_empty() => None,
                    Ok(line) => Some(
                        serde_json::from_str::<Game>(&line)
                            .map_err(|err| Error::IndexerStreamError(err.into())),
                    ),
                    Err(err) => Some(Err(Error::IndexerStreamError(err))),
                }
            }),
        ))
    }
}

#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Game {
    #[serde_as(as = "DisplayFromStr")]
    pub id: GameId,
    pub rated: bool,
    pub created_at: u64,
    pub status: Status,
    pub variant: LilaVariant,
    pub players: Players,
    pub speed: Speed,
    #[serde_as(as = "StringWithSeparator::<SpaceSeparator, San>")]
    pub moves: Vec<San>,
    #[serde_as(as = "Option<FromInto<ColorProxy>>")]
    #[serde(default)]
    pub winner: Option<Color>,
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default)]
    pub initial_fen: Option<Fen>,
}

impl Game {
    pub fn user_name(&self, color: Color) -> Option<&UserName> {
        self.players.by_color(color).user.as_ref().map(|u| &u.name)
    }
}

#[derive(Debug, Deserialize)]
pub struct Players {
    pub white: Player,
    pub black: Player,
}

impl Players {
    fn by_color(&self, color: Color) -> &Player {
        match color {
            Color::White => &self.white,
            Color::Black => &self.black,
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Player {
    #[serde(default)]
    user: Option<User>,
    #[serde(default)]
    rating: Option<u16>,
}

#[serde_as]
#[derive(Debug, Deserialize)]
pub struct User {
    #[serde_as(as = "DisplayFromStr")]
    name: UserName,
}

#[derive(Debug, Deserialize, Copy, Clone)]
#[serde(rename_all = "camelCase")]
pub enum Status {
    Created,
    Started,
    Aborted,
    Mate,
    Resign,
    Stalemate,
    Timeout,
    Draw,
    #[serde(rename = "outoftime")]
    OutOfTime,
    Cheat,
    NoStart,
    UnknownFinish,
    VariantEnd,
}

impl Status {
    pub fn is_ongoing(self) -> bool {
        matches!(self, Status::Created | Status::Started)
    }

    pub fn is_unindexable(self) -> bool {
        matches!(
            self,
            Status::UnknownFinish | Status::NoStart | Status::Aborted
        )
    }
}
<|endoftext|>


<commit_before>use criterion::{black_box, criterion_group, criterion_main, Criterion};
use std::fs::File;
use wasmbin::io::{WasmbinDecode, WasmbinEncode};

macro_rules! bench_group {
    ($namespace:ident as $name:ident) => {
        mod $name {
            use super::*;
            use wasmbin::$namespace::Module;

            fn deep_module() -> Module {
                use wasmbin::builtins::Blob;
                use wasmbin::instructions::{BlockBody, Expression, Instruction};
                use wasmbin::sections::FuncBody;
                use wasmbin::types::BlockType;

                let mut expr = Expression::default();
                for _ in 0..100_000 {
                    let old_expr = std::mem::take(&mut expr);
                    expr.push(Instruction::Block(BlockBody {
                        return_type: BlockType::Empty,
                        expr: old_expr,
                    }));
                }
                let raw = wasmbin::module::Module {
                    sections: vec![vec![Blob::from(FuncBody {
                        locals: Default::default(),
                        expr,
                    })]
                    .into()],
                    ..Default::default()
                };
                std::convert::TryFrom::try_from(raw).unwrap()
            }

            fn bench_parse(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_parse"), |b| {
                    b.iter(|| {
                        let mut f = File::open("temp.wasm").unwrap();
                        Module::decode(&mut f).unwrap()
                    })
                });
            }

            fn bench_parse_buf(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_parse_buf"), |b| {
                    b.iter(|| {
                        let f = File::open("temp.wasm").unwrap();
                        let mut f = std::io::BufReader::new(f);
                        Module::decode(&mut f).unwrap()
                    })
                });
            }

            fn bench_parse_vec(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_parse_vec"), |b| {
                    let f = std::fs::read("temp.wasm").unwrap();
                    b.iter(|| {
                        let mut f = black_box(f.as_slice());
                        Module::decode(&mut f).unwrap()
                    })
                });
            }

            fn bench_parse_deep_module(c: &mut Criterion) {
                c.bench_function(
                    concat!(stringify!($name), "::bench_parse_deep_module"),
                    |b| {
                        let mut f = Vec::new();
                        deep_module().encode(&mut f).unwrap();
                        b.iter(|| {
                            let mut f = black_box(f.as_slice());
                            Module::decode(&mut f).unwrap()
                        })
                    },
                );
            }

            fn read_module() -> Module {
                let f = std::fs::read("temp.wasm").unwrap();
                let mut f = f.as_slice();
                Module::decode(&mut f).unwrap()
            }

            fn bench_write(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_write"), |b| {
                    let m = read_module();
                    b.iter(|| {
                        let mut f = File::create("temp.out.wasm").unwrap();
                        black_box(&m).encode(&mut f).unwrap();
                        f
                    })
                });
            }

            fn bench_write_buf(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_write_buf"), |b| {
                    let m = read_module();
                    b.iter(|| {
                        let f = File::create("temp.out.wasm").unwrap();
                        let mut f = std::io::BufWriter::new(f);
                        black_box(&m).encode(&mut f).unwrap();
                        f
                    })
                });
            }

            fn bench_write_vec(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_write_vec"), |b| {
                    let m = read_module();
                    b.iter(|| {
                        let mut f = Vec::new();
                        black_box(&m).encode(&mut f).unwrap();
                        f
                    })
                });
            }

            fn bench_write_deep_module(c: &mut Criterion) {
                c.bench_function(
                    concat!(stringify!($name), "::bench_write_deep_module"),
                    |b| {
                        let m = deep_module();
                        b.iter(|| {
                            let mut f = Vec::new();
                            black_box(&m).encode(&mut f).unwrap();
                            f
                        })
                    },
                );
            }

            criterion_group! {
                name = benches;
                config = Criterion::default().sample_size(20);
                targets =
                    bench_parse,
                    bench_parse_buf,
                    bench_parse_vec,
                    bench_parse_deep_module,
                    bench_write,
                    bench_write_buf,
                    bench_write_vec,
                    bench_write_deep_module,
            }
        }
    };
}

bench_group!(module as raw);
bench_group!(typed_module as typed);
criterion_main!(raw::benches, typed::benches);
<commit_msg>Disallow deep benchmarks with lazy-blob<commit_after>use criterion::{black_box, criterion_group, criterion_main, Criterion};
use std::fs::File;
use wasmbin::io::{WasmbinDecode, WasmbinEncode};

macro_rules! bench_group {
    ($namespace:ident as $name:ident) => {
        mod $name {
            use super::*;
            use wasmbin::$namespace::Module;

            fn deep_module() -> Module {
                use wasmbin::builtins::Blob;
                use wasmbin::instructions::{BlockBody, Expression, Instruction};
                use wasmbin::sections::FuncBody;
                use wasmbin::types::BlockType;

                let mut expr = Expression::default();
                for _ in 0..100_000 {
                    let old_expr = std::mem::take(&mut expr);
                    expr.push(Instruction::Block(BlockBody {
                        return_type: BlockType::Empty,
                        expr: old_expr,
                    }));
                }
                let raw = wasmbin::module::Module {
                    sections: vec![vec![Blob::from(FuncBody {
                        locals: Default::default(),
                        expr,
                    })]
                    .into()],
                    ..Default::default()
                };
                std::convert::TryFrom::try_from(raw).unwrap()
            }

            fn bench_parse(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_parse"), |b| {
                    b.iter(|| {
                        let mut f = File::open("temp.wasm").unwrap();
                        Module::decode(&mut f).unwrap()
                    })
                });
            }

            fn bench_parse_buf(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_parse_buf"), |b| {
                    b.iter(|| {
                        let f = File::open("temp.wasm").unwrap();
                        let mut f = std::io::BufReader::new(f);
                        Module::decode(&mut f).unwrap()
                    })
                });
            }

            fn bench_parse_vec(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_parse_vec"), |b| {
                    let f = std::fs::read("temp.wasm").unwrap();
                    b.iter(|| {
                        let mut f = black_box(f.as_slice());
                        Module::decode(&mut f).unwrap()
                    })
                });
            }

            fn bench_parse_deep_module(c: &mut Criterion) {
                c.bench_function(
                    concat!(stringify!($name), "::bench_parse_deep_module"),
                    |b| {
                        assert!(cfg!(not(feature = "lazy-blob")));
                        let mut f = Vec::new();
                        deep_module().encode(&mut f).unwrap();
                        b.iter(|| {
                            let mut f = black_box(f.as_slice());
                            Module::decode(&mut f).unwrap()
                        })
                    },
                );
            }

            fn read_module() -> Module {
                let f = std::fs::read("temp.wasm").unwrap();
                let mut f = f.as_slice();
                Module::decode(&mut f).unwrap()
            }

            fn bench_write(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_write"), |b| {
                    let m = read_module();
                    b.iter(|| {
                        let mut f = File::create("temp.out.wasm").unwrap();
                        black_box(&m).encode(&mut f).unwrap();
                        f
                    })
                });
            }

            fn bench_write_buf(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_write_buf"), |b| {
                    let m = read_module();
                    b.iter(|| {
                        let f = File::create("temp.out.wasm").unwrap();
                        let mut f = std::io::BufWriter::new(f);
                        black_box(&m).encode(&mut f).unwrap();
                        f
                    })
                });
            }

            fn bench_write_vec(c: &mut Criterion) {
                c.bench_function(concat!(stringify!($name), "::bench_write_vec"), |b| {
                    let m = read_module();
                    b.iter(|| {
                        let mut f = Vec::new();
                        black_box(&m).encode(&mut f).unwrap();
                        f
                    })
                });
            }

            fn bench_write_deep_module(c: &mut Criterion) {
                c.bench_function(
                    concat!(stringify!($name), "::bench_write_deep_module"),
                    |b| {
                        assert!(cfg!(not(feature = "lazy-blob")));
                        let m = deep_module();
                        b.iter(|| {
                            let mut f = Vec::new();
                            black_box(&m).encode(&mut f).unwrap();
                            f
                        })
                    },
                );
            }

            criterion_group! {
                name = benches;
                config = Criterion::default().sample_size(20);
                targets =
                    bench_parse,
                    bench_parse_buf,
                    bench_parse_vec,
                    bench_parse_deep_module,
                    bench_write,
                    bench_write_buf,
                    bench_write_vec,
                    bench_write_deep_module,
            }
        }
    };
}

bench_group!(module as raw);
bench_group!(typed_module as typed);
criterion_main!(raw::benches, typed::benches);
<|endoftext|>