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

#![unstable(feature = "collections_range",
            reason = "waiting for dust to settle on inclusive ranges",
            issue = "30877")]

//! Range syntax.

use core::ops::{RangeFull, Range, RangeTo, RangeFrom};
use Bound::{self, Excluded, Included, Unbounded};

/// **RangeArgument** is implemented by Rust's built-in range types, produced
/// by range syntax like `..`, `a..`, `..b` or `c..d`.
pub trait RangeArgument<T: ?Sized> {
    /// Start index bound
    ///
    /// Return start value as a `Bound`
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(collections)]
    /// #![feature(collections_range)]
    /// #![feature(collections_bound)]
    ///
    /// extern crate collections;
    ///
    /// # fn main() {
    /// use collections::range::RangeArgument;
    /// use collections::Bound::*;
    ///
    /// assert_eq!((..10).start(), Unbounded);
    /// assert_eq!((3..10).start(), Included(&3));
    /// # }
    /// ```
    fn start(&self) -> Bound<&T> {
        Unbounded
    }

    /// End index bound
    ///
    /// Return end value as a `Bound`
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(collections)]
    /// #![feature(collections_range)]
    /// #![feature(collections_bound)]
    ///
    /// extern crate collections;
    ///
    /// # fn main() {
    /// use collections::range::RangeArgument;
    /// use collections::Bound::*;
    ///
    /// assert_eq!((3..).end(), Unbounded);
    /// assert_eq!((3..10).end(), Excluded(&10));
    /// # }
    /// ```
    fn end(&self) -> Bound<&T> {
        Unbounded
    }
}

// FIXME add inclusive ranges to RangeArgument

impl<T> RangeArgument<T> for RangeFull {}

impl<T> RangeArgument<T> for RangeFrom<T> {
    fn start(&self) -> Bound<&T> {
        Included(&self.start)
    }
}

impl<T> RangeArgument<T> for RangeTo<T> {
    fn end(&self) -> Bound<&T> {
        Excluded(&self.end)
    }
}

impl<T> RangeArgument<T> for Range<T> {
    fn start(&self) -> Bound<&T> {
        Included(&self.start)
    }
    fn end(&self) -> Bound<&T> {
        Excluded(&self.end)
    }
}

impl<T> RangeArgument<T> for (Bound<T>, Bound<T>) {
    fn start(&self) -> Bound<&T> {
        match *self {
            (Included(ref start), _) => Included(start),
            (Excluded(ref start), _) => Excluded(start),
            (Unbounded, _)           => Unbounded,
        }
    }

    fn end(&self) -> Bound<&T> {
        match *self {
            (_, Included(ref end)) => Included(end),
            (_, Excluded(ref end)) => Excluded(end),
            (_, Unbounded)         => Unbounded,
        }
    }
}
<commit_msg>allow unsized types in `RangeArgument`<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "collections_range",
            reason = "waiting for dust to settle on inclusive ranges",
            issue = "30877")]

//! Range syntax.

use core::ops::{RangeFull, Range, RangeTo, RangeFrom};
use Bound::{self, Excluded, Included, Unbounded};

/// **RangeArgument** is implemented by Rust's built-in range types, produced
/// by range syntax like `..`, `a..`, `..b` or `c..d`.
pub trait RangeArgument<T: ?Sized> {
    /// Start index bound
    ///
    /// Return start value as a `Bound`
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(collections)]
    /// #![feature(collections_range)]
    /// #![feature(collections_bound)]
    ///
    /// extern crate collections;
    ///
    /// # fn main() {
    /// use collections::range::RangeArgument;
    /// use collections::Bound::*;
    ///
    /// assert_eq!((..10).start(), Unbounded);
    /// assert_eq!((3..10).start(), Included(&3));
    /// # }
    /// ```
    fn start(&self) -> Bound<&T> {
        Unbounded
    }

    /// End index bound
    ///
    /// Return end value as a `Bound`
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(collections)]
    /// #![feature(collections_range)]
    /// #![feature(collections_bound)]
    ///
    /// extern crate collections;
    ///
    /// # fn main() {
    /// use collections::range::RangeArgument;
    /// use collections::Bound::*;
    ///
    /// assert_eq!((3..).end(), Unbounded);
    /// assert_eq!((3..10).end(), Excluded(&10));
    /// # }
    /// ```
    fn end(&self) -> Bound<&T> {
        Unbounded
    }
}

// FIXME add inclusive ranges to RangeArgument

impl<T: ?Sized> RangeArgument<T> for RangeFull {}

impl<T> RangeArgument<T> for RangeFrom<T> {
    fn start(&self) -> Bound<&T> {
        Included(&self.start)
    }
}

impl<T> RangeArgument<T> for RangeTo<T> {
    fn end(&self) -> Bound<&T> {
        Excluded(&self.end)
    }
}

impl<T> RangeArgument<T> for Range<T> {
    fn start(&self) -> Bound<&T> {
        Included(&self.start)
    }
    fn end(&self) -> Bound<&T> {
        Excluded(&self.end)
    }
}

impl<T> RangeArgument<T> for (Bound<T>, Bound<T>) {
    fn start(&self) -> Bound<&T> {
        match *self {
            (Included(ref start), _) => Included(start),
            (Excluded(ref start), _) => Excluded(start),
            (Unbounded, _)           => Unbounded,
        }
    }

    fn end(&self) -> Bound<&T> {
        match *self {
            (_, Included(ref end)) => Included(end),
            (_, Excluded(ref end)) => Excluded(end),
            (_, Unbounded)         => Unbounded,
        }
    }
}

impl<'a, T: ?Sized + 'a> RangeArgument<T> for (Bound<&'a T>, Bound<&'a T>) {
    fn start(&self) -> Bound<&T> {
        match *self {
            (Included(start), _) => Included(start),
            (Excluded(start), _) => Excluded(start),
            (Unbounded, _)       => Unbounded,
        }
    }

    fn end(&self) -> Bound<&T> {
        match *self {
            (_, Included(end)) => Included(end),
            (_, Excluded(end)) => Excluded(end),
            (_, Unbounded)     => Unbounded,
        }
    }
}
<|endoftext|>


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

use ops::*;

use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul};

use intrinsics::{i8_add_with_overflow, u8_add_with_overflow};
use intrinsics::{i16_add_with_overflow, u16_add_with_overflow};
use intrinsics::{i32_add_with_overflow, u32_add_with_overflow};
use intrinsics::{i64_add_with_overflow, u64_add_with_overflow};
use intrinsics::{i8_sub_with_overflow, u8_sub_with_overflow};
use intrinsics::{i16_sub_with_overflow, u16_sub_with_overflow};
use intrinsics::{i32_sub_with_overflow, u32_sub_with_overflow};
use intrinsics::{i64_sub_with_overflow, u64_sub_with_overflow};
use intrinsics::{i8_mul_with_overflow, u8_mul_with_overflow};
use intrinsics::{i16_mul_with_overflow, u16_mul_with_overflow};
use intrinsics::{i32_mul_with_overflow, u32_mul_with_overflow};
use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};

pub trait WrappingOps {
    fn wrapping_add(self, rhs: Self) -> Self;
    fn wrapping_sub(self, rhs: Self) -> Self;
    fn wrapping_mul(self, rhs: Self) -> Self;
}

#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
pub trait OverflowingOps {
    fn overflowing_add(self, rhs: Self) -> (Self, bool);
    fn overflowing_sub(self, rhs: Self) -> (Self, bool);
    fn overflowing_mul(self, rhs: Self) -> (Self, bool);
}

macro_rules! wrapping_impl {
    ($($t:ty)*) => ($(
        impl WrappingOps for $t {
            #[inline(always)]
            fn wrapping_add(self, rhs: $t) -> $t {
                unsafe {
                    overflowing_add(self, rhs)
                }
            }
            #[inline(always)]
            fn wrapping_sub(self, rhs: $t) -> $t {
                unsafe {
                    overflowing_sub(self, rhs)
                }
            }
            #[inline(always)]
            fn wrapping_mul(self, rhs: $t) -> $t {
                unsafe {
                    overflowing_mul(self, rhs)
                }
            }
        }
    )*)
}

wrapping_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }

#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
#[derive(PartialEq,Eq,PartialOrd,Ord,Clone,Copy)]
pub struct Wrapping<T>(pub T);

impl<T:WrappingOps> Add for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn add(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0.wrapping_add(other.0))
    }
}

impl<T:WrappingOps> Sub for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn sub(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0.wrapping_sub(other.0))
    }
}

impl<T:WrappingOps> Mul for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn mul(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0.wrapping_mul(other.0))
    }
}

impl<T:WrappingOps+Not<Output=T>> Not for Wrapping<T> {
    type Output = Wrapping<T>;

    fn not(self) -> Wrapping<T> {
        Wrapping(!self.0)
    }
}

impl<T:WrappingOps+BitXor<Output=T>> BitXor for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn bitxor(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0 ^ other.0)
    }
}

impl<T:WrappingOps+BitOr<Output=T>> BitOr for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn bitor(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0 | other.0)
    }
}

impl<T:WrappingOps+BitAnd<Output=T>> BitAnd for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn bitand(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0 & other.0)
    }
}

impl<T:WrappingOps+Shl<uint,Output=T>> Shl<uint> for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn shl(self, other: uint) -> Wrapping<T> {
        Wrapping(self.0 << other)
    }
}

impl<T:WrappingOps+Shr<uint,Output=T>> Shr<uint> for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn shr(self, other: uint) -> Wrapping<T> {
        Wrapping(self.0 >> other)
    }
}

macro_rules! overflowing_impl {
    ($($t:ident)*) => ($(
        impl OverflowingOps for $t {
            #[inline(always)]
            fn overflowing_add(self, rhs: $t) -> ($t, bool) {
                unsafe {
                    concat_idents!($t, _add_with_overflow)(self, rhs)
                }
            }
            #[inline(always)]
            fn overflowing_sub(self, rhs: $t) -> ($t, bool) {
                unsafe {
                    concat_idents!($t, _sub_with_overflow)(self, rhs)
                }
            }
            #[inline(always)]
            fn overflowing_mul(self, rhs: $t) -> ($t, bool) {
                unsafe {
                    concat_idents!($t, _mul_with_overflow)(self, rhs)
                }
            }
        }
    )*)
}

overflowing_impl! { u8 u16 u32 u64 i8 i16 i32 i64 }

#[cfg(target_pointer_width = "64")]
impl OverflowingOps for usize {
    #[inline(always)]
    fn overflowing_add(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u64_add_with_overflow(self as u64, rhs as u64);
            (res.0 as usize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_sub(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u64_sub_with_overflow(self as u64, rhs as u64);
            (res.0 as usize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_mul(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u64_mul_with_overflow(self as u64, rhs as u64);
            (res.0 as usize, res.1)
        }
    }
}

#[cfg(target_pointer_width = "32")]
impl OverflowingOps for usize {
    #[inline(always)]
    fn overflowing_add(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u32_add_with_overflow(self as u32, rhs as u32);
            (res.0 as usize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_sub(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u32_sub_with_overflow(self as u32, rhs as u32);
            (res.0 as usize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_mul(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u32_mul_with_overflow(self as u32, rhs as u32);
            (res.0 as usize, res.1)
        }
    }
}

#[cfg(target_pointer_width = "64")]
impl OverflowingOps for isize {
    #[inline(always)]
    fn overflowing_add(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i64_add_with_overflow(self as i64, rhs as i64);
            (res.0 as isize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_sub(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i64_sub_with_overflow(self as i64, rhs as i64);
            (res.0 as isize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_mul(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i64_mul_with_overflow(self as i64, rhs as i64);
            (res.0 as isize, res.1)
        }
    }
}

#[cfg(target_pointer_width = "32")]
impl OverflowingOps for isize {
    #[inline(always)]
    fn overflowing_add(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i32_add_with_overflow(self as i32, rhs as i32);
            (res.0 as isize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_sub(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i32_sub_with_overflow(self as i32, rhs as i32);
            (res.0 as isize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_mul(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i32_mul_with_overflow(self as i32, rhs as i32);
            (res.0 as isize, res.1)
        }
    }
}
<commit_msg>num: Derive Debug for Wrapping<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(missing_docs)]

use ops::*;

use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul};

use intrinsics::{i8_add_with_overflow, u8_add_with_overflow};
use intrinsics::{i16_add_with_overflow, u16_add_with_overflow};
use intrinsics::{i32_add_with_overflow, u32_add_with_overflow};
use intrinsics::{i64_add_with_overflow, u64_add_with_overflow};
use intrinsics::{i8_sub_with_overflow, u8_sub_with_overflow};
use intrinsics::{i16_sub_with_overflow, u16_sub_with_overflow};
use intrinsics::{i32_sub_with_overflow, u32_sub_with_overflow};
use intrinsics::{i64_sub_with_overflow, u64_sub_with_overflow};
use intrinsics::{i8_mul_with_overflow, u8_mul_with_overflow};
use intrinsics::{i16_mul_with_overflow, u16_mul_with_overflow};
use intrinsics::{i32_mul_with_overflow, u32_mul_with_overflow};
use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};

pub trait WrappingOps {
    fn wrapping_add(self, rhs: Self) -> Self;
    fn wrapping_sub(self, rhs: Self) -> Self;
    fn wrapping_mul(self, rhs: Self) -> Self;
}

#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
pub trait OverflowingOps {
    fn overflowing_add(self, rhs: Self) -> (Self, bool);
    fn overflowing_sub(self, rhs: Self) -> (Self, bool);
    fn overflowing_mul(self, rhs: Self) -> (Self, bool);
}

macro_rules! wrapping_impl {
    ($($t:ty)*) => ($(
        impl WrappingOps for $t {
            #[inline(always)]
            fn wrapping_add(self, rhs: $t) -> $t {
                unsafe {
                    overflowing_add(self, rhs)
                }
            }
            #[inline(always)]
            fn wrapping_sub(self, rhs: $t) -> $t {
                unsafe {
                    overflowing_sub(self, rhs)
                }
            }
            #[inline(always)]
            fn wrapping_mul(self, rhs: $t) -> $t {
                unsafe {
                    overflowing_mul(self, rhs)
                }
            }
        }
    )*)
}

wrapping_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }

#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub struct Wrapping<T>(pub T);

impl<T:WrappingOps> Add for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn add(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0.wrapping_add(other.0))
    }
}

impl<T:WrappingOps> Sub for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn sub(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0.wrapping_sub(other.0))
    }
}

impl<T:WrappingOps> Mul for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn mul(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0.wrapping_mul(other.0))
    }
}

impl<T:WrappingOps+Not<Output=T>> Not for Wrapping<T> {
    type Output = Wrapping<T>;

    fn not(self) -> Wrapping<T> {
        Wrapping(!self.0)
    }
}

impl<T:WrappingOps+BitXor<Output=T>> BitXor for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn bitxor(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0 ^ other.0)
    }
}

impl<T:WrappingOps+BitOr<Output=T>> BitOr for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn bitor(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0 | other.0)
    }
}

impl<T:WrappingOps+BitAnd<Output=T>> BitAnd for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn bitand(self, other: Wrapping<T>) -> Wrapping<T> {
        Wrapping(self.0 & other.0)
    }
}

impl<T:WrappingOps+Shl<uint,Output=T>> Shl<uint> for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn shl(self, other: uint) -> Wrapping<T> {
        Wrapping(self.0 << other)
    }
}

impl<T:WrappingOps+Shr<uint,Output=T>> Shr<uint> for Wrapping<T> {
    type Output = Wrapping<T>;

    #[inline(always)]
    fn shr(self, other: uint) -> Wrapping<T> {
        Wrapping(self.0 >> other)
    }
}

macro_rules! overflowing_impl {
    ($($t:ident)*) => ($(
        impl OverflowingOps for $t {
            #[inline(always)]
            fn overflowing_add(self, rhs: $t) -> ($t, bool) {
                unsafe {
                    concat_idents!($t, _add_with_overflow)(self, rhs)
                }
            }
            #[inline(always)]
            fn overflowing_sub(self, rhs: $t) -> ($t, bool) {
                unsafe {
                    concat_idents!($t, _sub_with_overflow)(self, rhs)
                }
            }
            #[inline(always)]
            fn overflowing_mul(self, rhs: $t) -> ($t, bool) {
                unsafe {
                    concat_idents!($t, _mul_with_overflow)(self, rhs)
                }
            }
        }
    )*)
}

overflowing_impl! { u8 u16 u32 u64 i8 i16 i32 i64 }

#[cfg(target_pointer_width = "64")]
impl OverflowingOps for usize {
    #[inline(always)]
    fn overflowing_add(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u64_add_with_overflow(self as u64, rhs as u64);
            (res.0 as usize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_sub(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u64_sub_with_overflow(self as u64, rhs as u64);
            (res.0 as usize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_mul(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u64_mul_with_overflow(self as u64, rhs as u64);
            (res.0 as usize, res.1)
        }
    }
}

#[cfg(target_pointer_width = "32")]
impl OverflowingOps for usize {
    #[inline(always)]
    fn overflowing_add(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u32_add_with_overflow(self as u32, rhs as u32);
            (res.0 as usize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_sub(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u32_sub_with_overflow(self as u32, rhs as u32);
            (res.0 as usize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_mul(self, rhs: usize) -> (usize, bool) {
        unsafe {
            let res = u32_mul_with_overflow(self as u32, rhs as u32);
            (res.0 as usize, res.1)
        }
    }
}

#[cfg(target_pointer_width = "64")]
impl OverflowingOps for isize {
    #[inline(always)]
    fn overflowing_add(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i64_add_with_overflow(self as i64, rhs as i64);
            (res.0 as isize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_sub(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i64_sub_with_overflow(self as i64, rhs as i64);
            (res.0 as isize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_mul(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i64_mul_with_overflow(self as i64, rhs as i64);
            (res.0 as isize, res.1)
        }
    }
}

#[cfg(target_pointer_width = "32")]
impl OverflowingOps for isize {
    #[inline(always)]
    fn overflowing_add(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i32_add_with_overflow(self as i32, rhs as i32);
            (res.0 as isize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_sub(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i32_sub_with_overflow(self as i32, rhs as i32);
            (res.0 as isize, res.1)
        }
    }
    #[inline(always)]
    fn overflowing_mul(self, rhs: isize) -> (isize, bool) {
        unsafe {
            let res = i32_mul_with_overflow(self as i32, rhs as i32);
            (res.0 as isize, res.1)
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate errno;

use self::libc::{c_int};

use std::{ptr, mem};
use std::fmt;

use crate::libproc::helpers;

// See https://opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/sys/msgbuf.h
const MAX_MSG_BSIZE : c_int = (1*1024*1024);
const MSG_MAGIC : c_int = 0x063061;

// See /usr/include/sys/msgbuf.h on your Mac.
#[repr(C)]
struct MessageBuffer {
    pub msg_magic : c_int,
    pub msg_size : c_int,
    pub msg_bufx : c_int,      // write pointer
    pub msg_bufr : c_int,      // read pointer
    pub msg_bufc : * mut u8     // buffer
}

impl Default for MessageBuffer {
    fn default() -> MessageBuffer {
        MessageBuffer {
            msg_magic : 0,
            msg_size : 0,
            msg_bufx : 0,
            msg_bufr : 0,
            msg_bufc : ptr::null_mut() as * mut u8
        }
    }
}

impl fmt::Debug for MessageBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MessageBuffer {{ magic: 0x{:x}, size: {}, bufx: {}}}", self.msg_magic, self.msg_size, self.msg_bufx)
    }
}

// this extern block links to the libproc library
// Original signatures of functions can be found at http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c
#[cfg(target_os = "macos")]
#[link(name = "proc", kind = "dylib")]
extern {
    fn proc_kmsgbuf(buffer : *mut MessageBuffer, buffersize : u32) -> c_int;
}

/// Get upto buffersize bytes from the the kernel message buffer - as used by dmesg
/// extern crate libproc;
/// extern crate libc;
///
/// use std::str;
/// use std::io::Write;
/// use libproc::libproc::kmesg_buffer;
///
/// fn main() {
///     if kmesg_buffer::am_root() {
///         match kmesg_buffer::kmsgbuf() {
///             Ok(message) => println!("{}", message),
///             Err(err) => writeln!(&mut std::io::stderr(), "Error: {}", err).unwrap()
///         }
///     } else {
///         writeln!(&mut std::io::stderr(), "Must be run as root").unwrap()
///     }
// See http://opensource.apple.com//source/system_cmds/system_cmds-336.6/dmesg.tproj/dmesg.c
#[cfg(target_os = "macos")]
pub fn kmsgbuf() -> Result<String, String> {
    let mut message_buffer : MessageBuffer = Default::default();
    let ret: i32;

    unsafe {
        ret = proc_kmsgbuf(&mut message_buffer, mem::size_of::<MessageBuffer>() as u32);
    }

    if ret <= 0 {
        Err(helpers::get_errno_with_message(ret))
    } else
    {
        if message_buffer.msg_magic != MSG_MAGIC {
            println!("Message buffer: {:?}", message_buffer);
            Err(format!("The magic number 0x{:x} is incorrect", message_buffer.msg_magic))
        } else {
            // Avoid starting beyond the end of the buffer
            if message_buffer.msg_bufx >= MAX_MSG_BSIZE {
                message_buffer.msg_bufx = 0;
            }
            let mut output : Vec<u8> = Vec::new();

            // The message buffer is circular; start at the read pointer, and go to the write pointer - 1.
            unsafe {
                let mut ch : u8;
//                let newl : bool = false;
//                let skip : bool = false;
                let mut p : * mut u8 = message_buffer.msg_bufc.offset(message_buffer.msg_bufx as isize);
                let ep : * mut u8 = message_buffer.msg_bufc.offset((message_buffer.msg_bufx - 1) as isize);
//                let buf : [u8; 5];

                while p != ep {
                    // If at the end, then loop around to the start
                    // TODO should use actual size (from struct element) - not the max size??
                    if p == message_buffer.msg_bufc.offset(MAX_MSG_BSIZE as isize) {
                        p = message_buffer.msg_bufc;
                    }

                    ch = *p;

                    /* Skip "\n<.*>" syslog sequences.
                    if skip {
                        if ch == '>' {
                            newl = skip = false;
                        }
                        continue;
                    }

                    if newl && ch == '<' {
                        skip = true;
                        continue;
                    }

                    if ch == '\0' {
                        continue;
                    }

                    newl = ch == '\n';

//                    (void)vis(buf, ch, 0, 0);

                    if buf[1] == 0 {
                        output.append(buf[0]);
                    } else {
                        output.append("%s", buf);
                    }
                    */

                    output.push(ch);
                    p = p.offset(1);
                }

                Ok(String::from_utf8(output).unwrap())
            }
        }
    }
}

#[cfg(not(target_os = "macos"))]
pub fn kmsgbuf() -> Result<String, String> {
    unimplemented!()
}

/// Determine if the current user ID of this process is root
///
/// ```
/// use libproc::libproc::kmesg_buffer::am_root;
///
/// if am_root() {
///     println!("With great power comes great responsibility");
/// }
/// ```
#[cfg(target_os = "macos")]
pub fn am_root() -> bool {
    // geteuid() is unstable still - wait for it or wrap this:
    // https://stackoverflow.com/questions/3214297/how-can-my-c-c-application-determine-if-the-root-user-is-executing-the-command
    unsafe { libc::getuid() == 0 }
}

#[cfg(target_os = "linux")]
pub fn am_root() -> bool {
    // when this becomes stable in rust libc then we can remove this function or combine for mac and linux
    unsafe { libc::geteuid() == 0 }
}

#[cfg(test)]
mod test {
    use std::io;
    use std::io::Write;
    #[cfg(not(target_os = "macos"))]
    use super::kmsgbuf;
    use super::am_root;

    #[test]
    fn test_if_root() {
        if am_root() {
            println!("You are root");
        } else {
            println!("You are not root");
        }
    }

    // If you want this test to actually test something, then you need to run as root 'sudo cargo test'
    #[test]
    // TODO fix this on macos: error message returned is
    // Message buffer: MessageBuffer { magic: 0x3a657461, size: 1986947360, bufx: 1684630625}
    // thread 'libproc::kmesg_buffer::test::kmessagebuffer_test' panicked at 'The magic number 0x3a657461 is incorrect', src/libproc/kmesg_buffer.rs:194:33
    fn kmessagebuffer_test() {
        if am_root() {
            #[cfg(not(target_os = "macos"))]
            match kmsgbuf() {
                Ok(buffer) => println!("Buffer: {:?}", buffer),
                Err(message) => assert!(false, message)
            }
        } else {
            writeln!(&mut io::stdout(), "test libproc::kmesg_buffer::kmessagebuffer_test ... skipped as it needs to be run as root").unwrap();
        }
    }
}<commit_msg>Avoid kmsgbug_test on linux for meantime<commit_after>extern crate libc;
extern crate errno;

use self::libc::{c_int};

use std::{ptr, mem};
use std::fmt;

use crate::libproc::helpers;

// See https://opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/sys/msgbuf.h
const MAX_MSG_BSIZE : c_int = (1*1024*1024);
const MSG_MAGIC : c_int = 0x063061;

// See /usr/include/sys/msgbuf.h on your Mac.
#[repr(C)]
struct MessageBuffer {
    pub msg_magic : c_int,
    pub msg_size : c_int,
    pub msg_bufx : c_int,      // write pointer
    pub msg_bufr : c_int,      // read pointer
    pub msg_bufc : * mut u8     // buffer
}

impl Default for MessageBuffer {
    fn default() -> MessageBuffer {
        MessageBuffer {
            msg_magic : 0,
            msg_size : 0,
            msg_bufx : 0,
            msg_bufr : 0,
            msg_bufc : ptr::null_mut() as * mut u8
        }
    }
}

impl fmt::Debug for MessageBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MessageBuffer {{ magic: 0x{:x}, size: {}, bufx: {}}}", self.msg_magic, self.msg_size, self.msg_bufx)
    }
}

// this extern block links to the libproc library
// Original signatures of functions can be found at http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c
#[cfg(target_os = "macos")]
#[link(name = "proc", kind = "dylib")]
extern {
    fn proc_kmsgbuf(buffer : *mut MessageBuffer, buffersize : u32) -> c_int;
}

/// Get upto buffersize bytes from the the kernel message buffer - as used by dmesg
/// extern crate libproc;
/// extern crate libc;
///
/// use std::str;
/// use std::io::Write;
/// use libproc::libproc::kmesg_buffer;
///
/// fn main() {
///     if kmesg_buffer::am_root() {
///         match kmesg_buffer::kmsgbuf() {
///             Ok(message) => println!("{}", message),
///             Err(err) => writeln!(&mut std::io::stderr(), "Error: {}", err).unwrap()
///         }
///     } else {
///         writeln!(&mut std::io::stderr(), "Must be run as root").unwrap()
///     }
// See http://opensource.apple.com//source/system_cmds/system_cmds-336.6/dmesg.tproj/dmesg.c
#[cfg(target_os = "macos")]
pub fn kmsgbuf() -> Result<String, String> {
    let mut message_buffer : MessageBuffer = Default::default();
    let ret: i32;

    unsafe {
        ret = proc_kmsgbuf(&mut message_buffer, mem::size_of::<MessageBuffer>() as u32);
    }

    if ret <= 0 {
        Err(helpers::get_errno_with_message(ret))
    } else
    {
        if message_buffer.msg_magic != MSG_MAGIC {
            println!("Message buffer: {:?}", message_buffer);
            Err(format!("The magic number 0x{:x} is incorrect", message_buffer.msg_magic))
        } else {
            // Avoid starting beyond the end of the buffer
            if message_buffer.msg_bufx >= MAX_MSG_BSIZE {
                message_buffer.msg_bufx = 0;
            }
            let mut output : Vec<u8> = Vec::new();

            // The message buffer is circular; start at the read pointer, and go to the write pointer - 1.
            unsafe {
                let mut ch : u8;
//                let newl : bool = false;
//                let skip : bool = false;
                let mut p : * mut u8 = message_buffer.msg_bufc.offset(message_buffer.msg_bufx as isize);
                let ep : * mut u8 = message_buffer.msg_bufc.offset((message_buffer.msg_bufx - 1) as isize);
//                let buf : [u8; 5];

                while p != ep {
                    // If at the end, then loop around to the start
                    // TODO should use actual size (from struct element) - not the max size??
                    if p == message_buffer.msg_bufc.offset(MAX_MSG_BSIZE as isize) {
                        p = message_buffer.msg_bufc;
                    }

                    ch = *p;

                    /* Skip "\n<.*>" syslog sequences.
                    if skip {
                        if ch == '>' {
                            newl = skip = false;
                        }
                        continue;
                    }

                    if newl && ch == '<' {
                        skip = true;
                        continue;
                    }

                    if ch == '\0' {
                        continue;
                    }

                    newl = ch == '\n';

//                    (void)vis(buf, ch, 0, 0);

                    if buf[1] == 0 {
                        output.append(buf[0]);
                    } else {
                        output.append("%s", buf);
                    }
                    */

                    output.push(ch);
                    p = p.offset(1);
                }

                Ok(String::from_utf8(output).unwrap())
            }
        }
    }
}

#[cfg(not(target_os = "macos"))]
pub fn kmsgbuf() -> Result<String, String> {
    unimplemented!()
}

/// Determine if the current user ID of this process is root
///
/// ```
/// use libproc::libproc::kmesg_buffer::am_root;
///
/// if am_root() {
///     println!("With great power comes great responsibility");
/// }
/// ```
#[cfg(target_os = "macos")]
pub fn am_root() -> bool {
    // geteuid() is unstable still - wait for it or wrap this:
    // https://stackoverflow.com/questions/3214297/how-can-my-c-c-application-determine-if-the-root-user-is-executing-the-command
    unsafe { libc::getuid() == 0 }
}

#[cfg(target_os = "linux")]
pub fn am_root() -> bool {
    // when this becomes stable in rust libc then we can remove this function or combine for mac and linux
    unsafe { libc::geteuid() == 0 }
}

#[cfg(test)]
mod test {
    use std::io;
    use std::io::Write;
    #[cfg(target_os = "macos")]
    use super::kmsgbuf;
    use super::am_root;

    #[test]
    fn test_if_root() {
        if am_root() {
            println!("You are root");
        } else {
            println!("You are not root");
        }
    }

    #[cfg(target_os = "macos")]
    #[test]
    // TODO fix this on macos: error message returned is
    // Message buffer: MessageBuffer { magic: 0x3a657461, size: 1986947360, bufx: 1684630625}
    // thread 'libproc::kmesg_buffer::test::kmessagebuffer_test' panicked at 'The magic number 0x3a657461 is incorrect', src/libproc/kmesg_buffer.rs:194:33
    fn kmessagebuffer_test() {
        if am_root() {
            match kmsgbuf() {
                Ok(buffer) => println!("Buffer: {:?}", buffer),
                Err(message) => assert!(false, message)
            }
        } else {
            writeln!(&mut io::stdout(), "test libproc::kmesg_buffer::kmessagebuffer_test ... skipped as it needs to be run as root").unwrap();
        }
    }
}<|endoftext|>


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

pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};

const NSEC_PER_SEC: u64 = 1_000_000_000;

#[cfg(any(target_os = "macos", target_os = "ios"))]
mod inner {
    use cmp::Ordering;
    use fmt;
    use libc;
    use super::NSEC_PER_SEC;
    use sync::Once;
    use sys::cvt;
    use sys_common::mul_div_u64;
    use time::Duration;

    const USEC_PER_SEC: u64 = NSEC_PER_SEC / 1000;

    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
    pub struct Instant {
        t: u64
    }

    #[derive(Copy, Clone)]
    pub struct SystemTime {
        t: libc::timeval,
    }

    pub const UNIX_EPOCH: SystemTime = SystemTime {
        t: libc::timeval {
            tv_sec: 0,
            tv_usec: 0,
        },
    };

    impl Instant {
        pub fn now() -> Instant {
            Instant { t: unsafe { libc::mach_absolute_time() } }
        }

        pub fn sub_instant(&self, other: &Instant) -> Duration {
            let info = info();
            let diff = self.t.checked_sub(other.t)
                           .expect("second instant is later than self");
            let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64);
            Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
        }

        pub fn add_duration(&self, other: &Duration) -> Instant {
            Instant {
                t: self.t.checked_add(dur2intervals(other))
                       .expect("overflow when adding duration to instant"),
            }
        }

        pub fn sub_duration(&self, other: &Duration) -> Instant {
            Instant {
                t: self.t.checked_sub(dur2intervals(other))
                       .expect("overflow when adding duration to instant"),
            }
        }
    }

    impl SystemTime {
        pub fn now() -> SystemTime {
            let mut s = SystemTime {
                t: libc::timeval {
                    tv_sec: 0,
                    tv_usec: 0,
                },
            };
            cvt(unsafe {
                libc::gettimeofday(&mut s.t, 0 as *mut _)
            }).unwrap();
            return s
        }

        pub fn sub_time(&self, other: &SystemTime)
                        -> Result<Duration, Duration> {
            if self >= other {
                Ok(if self.t.tv_usec >= other.t.tv_usec {
                    Duration::new(self.t.tv_sec as u64 - other.t.tv_sec as u64,
                                  (self.t.tv_usec as u32 -
                                   other.t.tv_usec as u32) * 1000)
                } else {
                    Duration::new(self.t.tv_sec as u64 - 1 - other.t.tv_sec as u64,
                                  (self.t.tv_usec as u32 + (USEC_PER_SEC as u32) -
                                   other.t.tv_usec as u32) * 1000)
                })
            } else {
                match other.sub_time(self) {
                    Ok(d) => Err(d),
                    Err(d) => Ok(d),
                }
            }
        }

        pub fn add_duration(&self, other: &Duration) -> SystemTime {
            let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64);
            let mut secs = secs.expect("overflow when adding duration to time");

            // Nano calculations can't overflow because nanos are <1B which fit
            // in a u32.
            let mut usec = (other.subsec_nanos() / 1000) + self.t.tv_usec as u32;
            if usec >= USEC_PER_SEC as u32 {
                usec -= USEC_PER_SEC as u32;
                secs = secs.checked_add(1).expect("overflow when adding \
                                                   duration to time");
            }
            SystemTime {
                t: libc::timeval {
                    tv_sec: secs as libc::time_t,
                    tv_usec: usec as libc::suseconds_t,
                },
            }
        }

        pub fn sub_duration(&self, other: &Duration) -> SystemTime {
            let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64);
            let mut secs = secs.expect("overflow when subtracting duration \
                                        from time");

            // Similar to above, nanos can't overflow.
            let mut usec = self.t.tv_usec as i32 -
                           (other.subsec_nanos() / 1000) as i32;
            if usec < 0 {
                usec += USEC_PER_SEC as i32;
                secs = secs.checked_sub(1).expect("overflow when subtracting \
                                                   duration from time");
            }
            SystemTime {
                t: libc::timeval {
                    tv_sec: secs as libc::time_t,
                    tv_usec: usec as libc::suseconds_t,
                },
            }
        }
    }

    impl From<libc::timeval> for SystemTime {
        fn from(t: libc::timeval) -> SystemTime {
            SystemTime { t: t }
        }
    }

    impl PartialEq for SystemTime {
        fn eq(&self, other: &SystemTime) -> bool {
            self.t.tv_sec == other.t.tv_sec && self.t.tv_usec == other.t.tv_usec
        }
    }

    impl Eq for SystemTime {}

    impl PartialOrd for SystemTime {
        fn partial_cmp(&self, other: &SystemTime) -> Option<Ordering> {
            Some(self.cmp(other))
        }
    }

    impl Ord for SystemTime {
        fn cmp(&self, other: &SystemTime) -> Ordering {
            let me = (self.t.tv_sec, self.t.tv_usec);
            let other = (other.t.tv_sec, other.t.tv_usec);
            me.cmp(&other)
        }
    }

    impl fmt::Debug for SystemTime {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.debug_struct("SystemTime")
             .field("tv_sec", &self.t.tv_sec)
             .field("tv_usec", &self.t.tv_usec)
             .finish()
        }
    }

    fn dur2intervals(dur: &Duration) -> u64 {
        let info = info();
        let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| {
            nanos.checked_add(dur.subsec_nanos() as u64)
        }).expect("overflow converting duration to nanoseconds");
        mul_div_u64(nanos, info.denom as u64, info.numer as u64)
    }

    fn info() -> &'static libc::mach_timebase_info {
        static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info {
            numer: 0,
            denom: 0,
        };
        static ONCE: Once = Once::new();

        unsafe {
            ONCE.call_once(|| {
                libc::mach_timebase_info(&mut INFO);
            });
            &INFO
        }
    }
}

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
mod inner {
    use cmp::Ordering;
    use fmt;
    use libc;
    use super::NSEC_PER_SEC;
    use sys::cvt;
    use time::Duration;

    #[derive(Copy, Clone)]
    struct Timespec {
        t: libc::timespec,
    }

    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct Instant {
        t: Timespec,
    }

    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct SystemTime {
        t: Timespec,
    }

    pub const UNIX_EPOCH: SystemTime = SystemTime {
        t: Timespec {
            t: libc::timespec {
                tv_sec: 0,
                tv_nsec: 0,
            },
        },
    };

    impl Instant {
        pub fn now() -> Instant {
            Instant { t: Timespec::now(libc::CLOCK_MONOTONIC) }
        }

        pub fn sub_instant(&self, other: &Instant) -> Duration {
            self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
                panic!("other was less than the current instant")
            })
        }

        pub fn add_duration(&self, other: &Duration) -> Instant {
            Instant { t: self.t.add_duration(other) }
        }

        pub fn sub_duration(&self, other: &Duration) -> Instant {
            Instant { t: self.t.sub_duration(other) }
        }
    }

    impl fmt::Debug for Instant {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.debug_struct("Instant")
             .field("tv_sec", &self.t.t.tv_sec)
             .field("tv_nsec", &self.t.t.tv_nsec)
             .finish()
        }
    }

    impl SystemTime {
        pub fn now() -> SystemTime {
            SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
        }

        pub fn sub_time(&self, other: &SystemTime)
                        -> Result<Duration, Duration> {
            self.t.sub_timespec(&other.t)
        }

        pub fn add_duration(&self, other: &Duration) -> SystemTime {
            SystemTime { t: self.t.add_duration(other) }
        }

        pub fn sub_duration(&self, other: &Duration) -> SystemTime {
            SystemTime { t: self.t.sub_duration(other) }
        }
    }

    impl From<libc::timespec> for SystemTime {
        fn from(t: libc::timespec) -> SystemTime {
            SystemTime { t: Timespec { t: t } }
        }
    }

    impl fmt::Debug for SystemTime {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.debug_struct("SystemTime")
             .field("tv_sec", &self.t.t.tv_sec)
             .field("tv_nsec", &self.t.t.tv_nsec)
             .finish()
        }
    }

    impl Timespec {
        pub fn now(clock: libc::c_int) -> Timespec {
            let mut t = Timespec {
                t: libc::timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                }
            };
            cvt(unsafe {
                libc::clock_gettime(clock, &mut t.t)
            }).unwrap();
            t
        }

        fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
            if self >= other {
                Ok(if self.t.tv_nsec >= other.t.tv_nsec {
                    Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
                                  (self.t.tv_nsec - other.t.tv_nsec) as u32)
                } else {
                    Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
                                  self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) -
                                  other.t.tv_nsec as u32)
                })
            } else {
                match other.sub_timespec(self) {
                    Ok(d) => Err(d),
                    Err(d) => Ok(d),
                }
            }
        }

        fn add_duration(&self, other: &Duration) -> Timespec {
            let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64);
            let mut secs = secs.expect("overflow when adding duration to time");

            // Nano calculations can't overflow because nanos are <1B which fit
            // in a u32.
            let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
            if nsec >= NSEC_PER_SEC as u32 {
                nsec -= NSEC_PER_SEC as u32;
                secs = secs.checked_add(1).expect("overflow when adding \
                                                   duration to time");
            }
            Timespec {
                t: libc::timespec {
                    tv_sec: secs as libc::time_t,
                    tv_nsec: nsec as libc::c_long,
                },
            }
        }

        fn sub_duration(&self, other: &Duration) -> Timespec {
            let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64);
            let mut secs = secs.expect("overflow when subtracting duration \
                                        from time");

            // Similar to above, nanos can't overflow.
            let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
            if nsec < 0 {
                nsec += NSEC_PER_SEC as i32;
                secs = secs.checked_sub(1).expect("overflow when subtracting \
                                                   duration from time");
            }
            Timespec {
                t: libc::timespec {
                    tv_sec: secs as libc::time_t,
                    tv_nsec: nsec as libc::c_long,
                },
            }
        }
    }

    impl PartialEq for Timespec {
        fn eq(&self, other: &Timespec) -> bool {
            self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec
        }
    }

    impl Eq for Timespec {}

    impl PartialOrd for Timespec {
        fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> {
            Some(self.cmp(other))
        }
    }

    impl Ord for Timespec {
        fn cmp(&self, other: &Timespec) -> Ordering {
            let me = (self.t.tv_sec, self.t.tv_nsec);
            let other = (other.t.tv_sec, other.t.tv_nsec);
            me.cmp(&other)
        }
    }
}
<commit_msg>std: Fix overflow when subtracting Instant<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};

const NSEC_PER_SEC: u64 = 1_000_000_000;

#[cfg(any(target_os = "macos", target_os = "ios"))]
mod inner {
    use cmp::Ordering;
    use fmt;
    use libc;
    use super::NSEC_PER_SEC;
    use sync::Once;
    use sys::cvt;
    use sys_common::mul_div_u64;
    use time::Duration;

    const USEC_PER_SEC: u64 = NSEC_PER_SEC / 1000;

    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
    pub struct Instant {
        t: u64
    }

    #[derive(Copy, Clone)]
    pub struct SystemTime {
        t: libc::timeval,
    }

    pub const UNIX_EPOCH: SystemTime = SystemTime {
        t: libc::timeval {
            tv_sec: 0,
            tv_usec: 0,
        },
    };

    impl Instant {
        pub fn now() -> Instant {
            Instant { t: unsafe { libc::mach_absolute_time() } }
        }

        pub fn sub_instant(&self, other: &Instant) -> Duration {
            let info = info();
            let diff = self.t.checked_sub(other.t)
                           .expect("second instant is later than self");
            let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64);
            Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
        }

        pub fn add_duration(&self, other: &Duration) -> Instant {
            Instant {
                t: self.t.checked_add(dur2intervals(other))
                       .expect("overflow when adding duration to instant"),
            }
        }

        pub fn sub_duration(&self, other: &Duration) -> Instant {
            Instant {
                t: self.t.checked_sub(dur2intervals(other))
                       .expect("overflow when adding duration to instant"),
            }
        }
    }

    impl SystemTime {
        pub fn now() -> SystemTime {
            let mut s = SystemTime {
                t: libc::timeval {
                    tv_sec: 0,
                    tv_usec: 0,
                },
            };
            cvt(unsafe {
                libc::gettimeofday(&mut s.t, 0 as *mut _)
            }).unwrap();
            return s
        }

        pub fn sub_time(&self, other: &SystemTime)
                        -> Result<Duration, Duration> {
            if self >= other {
                Ok(if self.t.tv_usec >= other.t.tv_usec {
                    Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
                                  ((self.t.tv_usec -
                                    other.t.tv_usec) as u32) * 1000)
                } else {
                    Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
                                  (self.t.tv_usec as u32 + (USEC_PER_SEC as u32) -
                                   other.t.tv_usec as u32) * 1000)
                })
            } else {
                match other.sub_time(self) {
                    Ok(d) => Err(d),
                    Err(d) => Ok(d),
                }
            }
        }

        pub fn add_duration(&self, other: &Duration) -> SystemTime {
            let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64);
            let mut secs = secs.expect("overflow when adding duration to time");

            // Nano calculations can't overflow because nanos are <1B which fit
            // in a u32.
            let mut usec = (other.subsec_nanos() / 1000) + self.t.tv_usec as u32;
            if usec >= USEC_PER_SEC as u32 {
                usec -= USEC_PER_SEC as u32;
                secs = secs.checked_add(1).expect("overflow when adding \
                                                   duration to time");
            }
            SystemTime {
                t: libc::timeval {
                    tv_sec: secs as libc::time_t,
                    tv_usec: usec as libc::suseconds_t,
                },
            }
        }

        pub fn sub_duration(&self, other: &Duration) -> SystemTime {
            let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64);
            let mut secs = secs.expect("overflow when subtracting duration \
                                        from time");

            // Similar to above, nanos can't overflow.
            let mut usec = self.t.tv_usec as i32 -
                           (other.subsec_nanos() / 1000) as i32;
            if usec < 0 {
                usec += USEC_PER_SEC as i32;
                secs = secs.checked_sub(1).expect("overflow when subtracting \
                                                   duration from time");
            }
            SystemTime {
                t: libc::timeval {
                    tv_sec: secs as libc::time_t,
                    tv_usec: usec as libc::suseconds_t,
                },
            }
        }
    }

    impl From<libc::timeval> for SystemTime {
        fn from(t: libc::timeval) -> SystemTime {
            SystemTime { t: t }
        }
    }

    impl PartialEq for SystemTime {
        fn eq(&self, other: &SystemTime) -> bool {
            self.t.tv_sec == other.t.tv_sec && self.t.tv_usec == other.t.tv_usec
        }
    }

    impl Eq for SystemTime {}

    impl PartialOrd for SystemTime {
        fn partial_cmp(&self, other: &SystemTime) -> Option<Ordering> {
            Some(self.cmp(other))
        }
    }

    impl Ord for SystemTime {
        fn cmp(&self, other: &SystemTime) -> Ordering {
            let me = (self.t.tv_sec, self.t.tv_usec);
            let other = (other.t.tv_sec, other.t.tv_usec);
            me.cmp(&other)
        }
    }

    impl fmt::Debug for SystemTime {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.debug_struct("SystemTime")
             .field("tv_sec", &self.t.tv_sec)
             .field("tv_usec", &self.t.tv_usec)
             .finish()
        }
    }

    fn dur2intervals(dur: &Duration) -> u64 {
        let info = info();
        let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| {
            nanos.checked_add(dur.subsec_nanos() as u64)
        }).expect("overflow converting duration to nanoseconds");
        mul_div_u64(nanos, info.denom as u64, info.numer as u64)
    }

    fn info() -> &'static libc::mach_timebase_info {
        static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info {
            numer: 0,
            denom: 0,
        };
        static ONCE: Once = Once::new();

        unsafe {
            ONCE.call_once(|| {
                libc::mach_timebase_info(&mut INFO);
            });
            &INFO
        }
    }
}

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
mod inner {
    use cmp::Ordering;
    use fmt;
    use libc;
    use super::NSEC_PER_SEC;
    use sys::cvt;
    use time::Duration;

    #[derive(Copy, Clone)]
    struct Timespec {
        t: libc::timespec,
    }

    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct Instant {
        t: Timespec,
    }

    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct SystemTime {
        t: Timespec,
    }

    pub const UNIX_EPOCH: SystemTime = SystemTime {
        t: Timespec {
            t: libc::timespec {
                tv_sec: 0,
                tv_nsec: 0,
            },
        },
    };

    impl Instant {
        pub fn now() -> Instant {
            Instant { t: Timespec::now(libc::CLOCK_MONOTONIC) }
        }

        pub fn sub_instant(&self, other: &Instant) -> Duration {
            self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
                panic!("other was less than the current instant")
            })
        }

        pub fn add_duration(&self, other: &Duration) -> Instant {
            Instant { t: self.t.add_duration(other) }
        }

        pub fn sub_duration(&self, other: &Duration) -> Instant {
            Instant { t: self.t.sub_duration(other) }
        }
    }

    impl fmt::Debug for Instant {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.debug_struct("Instant")
             .field("tv_sec", &self.t.t.tv_sec)
             .field("tv_nsec", &self.t.t.tv_nsec)
             .finish()
        }
    }

    impl SystemTime {
        pub fn now() -> SystemTime {
            SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
        }

        pub fn sub_time(&self, other: &SystemTime)
                        -> Result<Duration, Duration> {
            self.t.sub_timespec(&other.t)
        }

        pub fn add_duration(&self, other: &Duration) -> SystemTime {
            SystemTime { t: self.t.add_duration(other) }
        }

        pub fn sub_duration(&self, other: &Duration) -> SystemTime {
            SystemTime { t: self.t.sub_duration(other) }
        }
    }

    impl From<libc::timespec> for SystemTime {
        fn from(t: libc::timespec) -> SystemTime {
            SystemTime { t: Timespec { t: t } }
        }
    }

    impl fmt::Debug for SystemTime {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.debug_struct("SystemTime")
             .field("tv_sec", &self.t.t.tv_sec)
             .field("tv_nsec", &self.t.t.tv_nsec)
             .finish()
        }
    }

    impl Timespec {
        pub fn now(clock: libc::c_int) -> Timespec {
            let mut t = Timespec {
                t: libc::timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                }
            };
            cvt(unsafe {
                libc::clock_gettime(clock, &mut t.t)
            }).unwrap();
            t
        }

        fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
            if self >= other {
                Ok(if self.t.tv_nsec >= other.t.tv_nsec {
                    Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
                                  (self.t.tv_nsec - other.t.tv_nsec) as u32)
                } else {
                    Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
                                  self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) -
                                  other.t.tv_nsec as u32)
                })
            } else {
                match other.sub_timespec(self) {
                    Ok(d) => Err(d),
                    Err(d) => Ok(d),
                }
            }
        }

        fn add_duration(&self, other: &Duration) -> Timespec {
            let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64);
            let mut secs = secs.expect("overflow when adding duration to time");

            // Nano calculations can't overflow because nanos are <1B which fit
            // in a u32.
            let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
            if nsec >= NSEC_PER_SEC as u32 {
                nsec -= NSEC_PER_SEC as u32;
                secs = secs.checked_add(1).expect("overflow when adding \
                                                   duration to time");
            }
            Timespec {
                t: libc::timespec {
                    tv_sec: secs as libc::time_t,
                    tv_nsec: nsec as libc::c_long,
                },
            }
        }

        fn sub_duration(&self, other: &Duration) -> Timespec {
            let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64);
            let mut secs = secs.expect("overflow when subtracting duration \
                                        from time");

            // Similar to above, nanos can't overflow.
            let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
            if nsec < 0 {
                nsec += NSEC_PER_SEC as i32;
                secs = secs.checked_sub(1).expect("overflow when subtracting \
                                                   duration from time");
            }
            Timespec {
                t: libc::timespec {
                    tv_sec: secs as libc::time_t,
                    tv_nsec: nsec as libc::c_long,
                },
            }
        }
    }

    impl PartialEq for Timespec {
        fn eq(&self, other: &Timespec) -> bool {
            self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec
        }
    }

    impl Eq for Timespec {}

    impl PartialOrd for Timespec {
        fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> {
            Some(self.cmp(other))
        }
    }

    impl Ord for Timespec {
        fn cmp(&self, other: &Timespec) -> Ordering {
            let me = (self.t.tv_sec, self.t.tv_nsec);
            let other = (other.t.tv_sec, other.t.tv_nsec);
            me.cmp(&other)
        }
    }
}
<|endoftext|>


<commit_before>use super::*;
use redox::*;

impl Editor {
    /// Redraw the window
    pub fn redraw(&mut self) {
        // TODO: Only draw when relevant for the window
        let x = self.x();
        let y = self.y();
        // Redraw window
        self.window.set(Color::BLACK);

        self.window.rect(8 * (x - self.scroll_y) as isize,
                         16 * (y - self.scroll_x) as isize,
                         8,
                         16,
                         Color::WHITE);

        for (y, row) in self.text.iter().enumerate() {
            for (x, c) in row.iter().enumerate() {
                if self.x() == x && self.y() == y {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     Color::BLACK);
                } else {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     Color::WHITE);
                }
            }
        }
        let h = self.window.height();
        let w = self.window.width();
        self.window.rect(0, h as isize - 18, w, 18, Color::rgba(74, 74, 74, 255));

        for (n, c) in (if self.status_bar.mode.len() > w / (8 * 4) {
            self.status_bar.mode.chars().take(w / (8 * 4) - 5).chain(vec!['.', '.', '.']).collect::<Vec<_>>()
        } else {
            self.status_bar.mode.chars().collect()
        }).into_iter().enumerate() {
            self.window.char(n as isize * 8, h as isize - 16 - 1, if c == '\t' { ' ' } else { c }, [255, 255, 255, 255]);
        }

        self.window.sync();
    }
}

/// The statubar (showing various info about the current state of the editor)
pub struct StatusBar {
    /// The current mode
    pub mode: String,
    /// The cureent char
    pub file: String,
    /// The current command
    pub cmd: String,
    /// A message (such as an error or other info to the user)
    pub msg: String,
}

impl StatusBar {
    /// Create new status bar
    pub fn new() -> Self {
        StatusBar {
            mode: "Normal".to_string(),
            file: String::new(),
            cmd: String::new(),
            msg: String::new(),
        }
    }
}
<commit_msg>Make it up-to-date with libredox<commit_after>use super::*;
use redox::*;

impl Editor {
    /// Redraw the window
    pub fn redraw(&mut self) {
        // TODO: Only draw when relevant for the window
        let x = self.x();
        let y = self.y();
        // Redraw window
        self.window.set(Color::BLACK);

        self.window.rect(8 * (x - self.scroll_y) as isize,
                         16 * (y - self.scroll_x) as isize,
                         8,
                         16,
                         Color::WHITE);

        for (y, row) in self.text.iter().enumerate() {
            for (x, c) in row.iter().enumerate() {
                if self.x() == x && self.y() == y {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     Color::BLACK);
                } else {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     Color::WHITE);
                }
            }
        }
        let h = self.window.height();
        let w = self.window.width();
        self.window.rect(0, h as isize - 18, w, 18, Color::rgba(74, 74, 74, 255));

        for (n, c) in (if self.status_bar.mode.len() > w / (8 * 4) {
            self.status_bar.mode.chars().take(w / (8 * 4) - 5).chain(vec!['.', '.', '.']).collect::<Vec<_>>()
        } else {
            self.status_bar.mode.chars().collect()
        }).into_iter().enumerate() {
            self.window.char(n as isize * 8, h as isize - 16 - 1, if c == '\t' { ' ' } else { c }, Color::WHITE);
        }

        self.window.sync();
    }
}

/// The statubar (showing various info about the current state of the editor)
pub struct StatusBar {
    /// The current mode
    pub mode: String,
    /// The cureent char
    pub file: String,
    /// The current command
    pub cmd: String,
    /// A message (such as an error or other info to the user)
    pub msg: String,
}

impl StatusBar {
    /// Create new status bar
    pub fn new() -> Self {
        StatusBar {
            mode: "Normal".to_string(),
            file: String::new(),
            cmd: String::new(),
            msg: String::new(),
        }
    }
}
<|endoftext|>


<commit_before>use libimagstore::store::EntryHeader;

use error::{LinkError, LinkErrorKind};
use link::{Link, Links};
use result::Result;

use toml::Value;

pub fn get_links(header: &EntryHeader) -> Result<Links> {
    process_rw_result(header.read("imag.links"))
}

/// Set the links in a header and return the old links, if any.
pub fn set_links(header: &mut EntryHeader, links: Links) -> Result<Links> {
    let links : Vec<Link> = links.into();
    let links : Vec<Value> = links.into_iter().map(|link| Value::String(link.into())).collect();
    process_rw_result(header.set("imag.links", Value::Array(links)))
}

pub fn add_link(header: &mut EntryHeader, link: Link) -> Result<()> {
    unimplemented!()
}

<commit_msg>Add helper for processing store result<commit_after>use libimagstore::store::EntryHeader;
use libimagstore::store::Result as StoreResult;

use error::{LinkError, LinkErrorKind};
use link::{Link, Links};
use result::Result;

use toml::Value;

pub fn get_links(header: &EntryHeader) -> Result<Links> {
    process_rw_result(header.read("imag.links"))
}

/// Set the links in a header and return the old links, if any.
pub fn set_links(header: &mut EntryHeader, links: Links) -> Result<Links> {
    let links : Vec<Link> = links.into();
    let links : Vec<Value> = links.into_iter().map(|link| Value::String(link.into())).collect();
    process_rw_result(header.set("imag.links", Value::Array(links)))
}

pub fn add_link(header: &mut EntryHeader, link: Link) -> Result<()> {
    unimplemented!()
}

fn process_rw_result(links: StoreResult<Option<Value>>) -> Result<Links> {
    if links.is_err() {
        let lerr  = LinkError::new(LinkErrorKind::EntryHeaderReadError,
                                   Some(Box::new(links.err().unwrap())));
        return Err(lerr);
    }
    let links = links.unwrap();

    if links.iter().any(|l| match l { &Value::String(_) => true, _ => false }) {
        return Err(LinkError::new(LinkErrorKind::ExistingLinkTypeWrong, None));
    }

    let links : Vec<Link> = links.into_iter()
        .map(|link| {
            match link {
                Value::String(s) => Link::new(s),
                _ => unreachable!(),
            }
        })
        .collect();

    Ok(Links::new(links))
}

<|endoftext|>


<commit_before>extern crate gcc;
extern crate libbindgen;

use std::env;
use std::path::Path;

fn main() {
    let mut gcc_config = gcc::Config::new();

    gcc_config.file("src/fasthash.cpp")
        .file("src/smhasher/City.cpp")
        .file("src/smhasher/farmhash-c.c")
        .file("src/smhasher/lookup3.cpp")
        .file("src/smhasher/mum.cc")
        .file("src/smhasher/metrohash64.cpp")
        .file("src/smhasher/metrohash128.cpp")
        .file("src/smhasher/MurmurHash1.cpp")
        .file("src/smhasher/MurmurHash2.cpp")
        .file("src/smhasher/MurmurHash3.cpp")
        .file("src/smhasher/Spooky.cpp")
        .file("src/smhasher/t1ha.cc")
        .file("src/smhasher/xxhash.c");

    if cfg!(feature = "sse42") {
        gcc_config.flag("-msse4.2")
            .file("src/smhasher/metrohash64crc.cpp")
            .file("src/smhasher/metrohash128crc.cpp");
    }

    gcc_config.compile("libfasthash.a");

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_file = Path::new(&out_dir).join("src/fasthash.rs");

    let _ = libbindgen::builder()
        .clang_arg("-xc++")
        .clang_arg("--std=c++11")
        .clang_arg(if cfg!(feature = "sse42") {
            "-msse4.2"
        } else {
            "-march=native"
        })
        .header("src/fasthash.hpp")
        .no_unstable_rust()
        .whitelisted_function("^CityHash.*")
        .whitelisted_function("^farmhash.*")
        .whitelisted_function("^lookup3.*")
        .whitelisted_function("^metrohash.*")
        .whitelisted_function("^mum_hash.*")
        .whitelisted_function("^MurmurHash.*")
        .whitelisted_function("^SpookyHasher.*")
        .whitelisted_function("^t1ha.*")
        .whitelisted_function("^XXH.*")
        .link_static("fasthash")
        .generate()
        .unwrap()
        .write_to_file(out_file)
        .expect("Couldn't write bindings!");

    if cfg!(target_os = "macos") {
        println!("cargo:rustc-link-lib=dylib=c++");
    } else {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    }
}
<commit_msg>Make libbindgen 1.7 and Arch linux happy<commit_after>extern crate gcc;
extern crate libbindgen;

use std::env;
use std::path::Path;

fn main() {
    let mut gcc_config = gcc::Config::new();

    gcc_config.file("src/fasthash.cpp")
        .file("src/smhasher/City.cpp")
        .file("src/smhasher/farmhash-c.c")
        .file("src/smhasher/lookup3.cpp")
        .file("src/smhasher/mum.cc")
        .file("src/smhasher/metrohash64.cpp")
        .file("src/smhasher/metrohash128.cpp")
        .file("src/smhasher/MurmurHash1.cpp")
        .file("src/smhasher/MurmurHash2.cpp")
        .file("src/smhasher/MurmurHash3.cpp")
        .file("src/smhasher/Spooky.cpp")
        .file("src/smhasher/t1ha.cc")
        .file("src/smhasher/xxhash.c");

    if cfg!(feature = "sse42") {
        gcc_config.flag("-msse4.2")
            .file("src/smhasher/metrohash64crc.cpp")
            .file("src/smhasher/metrohash128crc.cpp");
    }

    gcc_config.compile("libfasthash.a");

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_file = Path::new(&out_dir).join("src/fasthash.rs");

    let _ = libbindgen::builder()
        .clang_arg("-xc++")
        .clang_arg("--std=c++11")
        .clang_arg(if cfg!(feature = "sse42") {
            "-msse4.2"
        } else {
            "-march=native"
        })
        .header("src/fasthash.hpp")
        .no_unstable_rust()
        .disable_name_namespacing()
        .hide_type(".*PCCP.*")
        .whitelisted_function("^CityHash.*")
        .whitelisted_function("^farmhash.*")
        .whitelisted_function("^lookup3.*")
        .whitelisted_function("^metrohash.*")
        .whitelisted_function("^mum_hash.*")
        .whitelisted_function("^MurmurHash.*")
        .whitelisted_function("^SpookyHasher.*")
        .whitelisted_function("^t1ha.*")
        .whitelisted_function("^XXH.*")
        .link_static("fasthash")
        .generate()
        .unwrap()
        .write_to_file(out_file)
        .expect("Couldn't write bindings!");

    if cfg!(target_os = "macos") {
        println!("cargo:rustc-link-lib=dylib=c++");
    } else {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    }
}
<|endoftext|>