<commit_before>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// 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.

//! TCP packet abstraction

use packet::Packet;
use packet::HasPseudoheader;
use packet::checksum::rfc1071_checksum;
use pnet_macros::types::*;

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    sequence: u32be,
    acknowledgement: u32be,
    data_offset_and_reserved: u8,
    control_bits: u8,
    window: u16be,
    checksum: u16be,
    urgent_pointer: u16be,
    #[length_fn = "tcp_options_length"]
    options: Vec<TcpOptions>,
    #[length_fn = "tcp_padding_length"]
    padding: Vec<TcpPadding>,
    #[payload]
    payload: Vec<u8>
}

fn tcp_options_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The data offset field specifies the total size of the TCP header
       in 32-bit words. The minimum size of a TCP header is 20 bytes and thus
       TCP headers must have data offset set to 5 or more.
     */
    let size = tcp.get_data_offset_and_reserved() as usize;
    return (size / 4) - 5 // XXX the "reserved" 4-bit word is zeros and is ignored when we divide by 4
}

/// Represents the TCP Option fields
#[packet]
pub struct TcpOptions {
    kind: u8,
    #[payload]
    data: Vec<u8>
}

fn tcp_padding_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The TCP header padding is used to ensure that the entire header
       ends on a 32 bit boundary.
     */
    return tcp.get_data_offset_and_reserved() as usize % 4;
}

/// Represents the TCP header padding
#[packet]
pub struct TcpPadding {
    #[payload]
    data: Vec<u8>
}

/// Calculates the checksum of a TCP packet
/// The passed in TcpPacket must have it's initial checksum value set to zero.
pub fn checksum<'a, T: HasPseudoheader>(packet: &TcpPacket<'a>, encapsulating_packet: T) -> u16be {
    let mut sum = encapsulating_packet.pseudoheader_checksum();
    let length = packet.packet().len() as u32;
    sum = sum + length & 0xffff;
    sum = sum + length >> 16;
    return rfc1071_checksum(packet.packet(), sum);
}

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

    const TCP_MIN_HEADER_LEN: usize = 20;
    const TCP_OPTIONS_LEN: usize = 12;
    const PAYLOAD_LEN: usize = 5;

    #[test]
    fn tcp_header_ipv4_test() {
        use pnet::packet::ip::IpNextHeaderProtocols;
        use pnet::packet::ipv4::{Ipv4Packet,MutableIpv4Packet};
        use std::net::{Ipv4Addr};

        const IPV4_HEADER_LEN: usize = 20;

        let mut packet = [0u8; IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + PAYLOAD_LEN];
        let ipv4_source = Ipv4Addr::new(127, 0, 0, 1);
        let ipv4_destination = Ipv4Addr::new(127, 0, 0, 1);
        let next_level_protocol = IpNextHeaderProtocols::Tcp;

        {
            let mut mut_ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
            mut_ip_header.set_next_level_protocol(next_level_protocol);
            mut_ip_header.set_source(ipv4_source);
            mut_ip_header.set_destination(ipv4_destination);
        }

        {
            let mut mutable_tcp_header = MutableTcpPacket::new(&mut packet[IPV4_HEADER_LEN..]).unwrap();
            mutable_tcp_header.set_checksum(0);
        }

        {
            let ip_header = Ipv4Packet::new(&packet[..IPV4_HEADER_LEN]).unwrap();
            let tcp_header = TcpPacket::new(&packet[IPV4_HEADER_LEN..]).unwrap();
            let csum = checksum(&tcp_header, ip_header);
        }

        {
            generate_simple_tcp_header(&mut packet[IPV4_HEADER_LEN..]);
        }

        // Set payload data
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 0] = 'm' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 1] = 'e' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 2] = 'o' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 3] = 'w' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 4] = '\n' as u8;

        let ref_tcp_packet = [0xe0, 0x0f, // source port
                              0x25, 0xc2, // dest port
                              0xdf, 0x06, // sequence
                              0xe6, 0xe6,
                              0xc9, 0x2d, // acknowledgement
                              0x98, 0x71,
                              0x80,       // header length + reserved
                              0x18,       // control bits
                              0x02, 0xab, // window
                              0xfe, 0x2d, // checksum
                              0x00, 0x00, // urgent pointer
                              0x01, 0x01, // tcp option no-op
                              0x08, 0x0a, // tcp option timestamp, options length == 10 bytes
                              0x1d, 0xfc, // 4-byte send timestamp
                              0xcb, 0x76,
                              0x1d, 0xfc, // 4-byte latest replied timestamp
                              0xbe, 0x62,
                              0x6d, 0x65, // payload
                              0x6f, 0x77, 0x0a];
        assert_eq!(&ref_tcp_packet[..], &packet[IPV4_HEADER_LEN..]);

        //tcp/ipv4 == "45, 00 00 39 58 89 40 00 40 06 e4 33 7f 00 00 01 7f 00 00 01 e0 0f 25 c2 df 06 e6 e6 c9 2d 98 71 80 18 02 ab fe 2d 00 00 01 01 08 0a 1d fc cb 76 1d fc be 62 6d 65 6f 77 0a";

    }

    fn generate_simple_tcp_header<'p>(packet: &'p mut [u8]) {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[..]).unwrap();
        tcp_header.set_source(57359);
        assert_eq!(tcp_header.get_source(), 57359);

        tcp_header.set_destination(9666);
        assert_eq!(tcp_header.get_destination(), 9666);

        tcp_header.set_sequence(3741771494);
        assert_eq!(tcp_header.get_sequence(), 3741771494);

        tcp_header.set_acknowledgement(3375208561);
        assert_eq!(tcp_header.get_acknowledgement(), 3375208561);

        tcp_header.set_data_offset_and_reserved(0x80);
        assert_eq!(tcp_header.get_data_offset_and_reserved(), 0x80);

        tcp_header.set_control_bits(0x18);
        assert_eq!(tcp_header.get_control_bits(), 0x18);

        tcp_header.set_window(0x02ab);
        assert_eq!(tcp_header.get_window(), 0x02ab);

        tcp_header.set_checksum(0xfe2d);
        assert_eq!(tcp_header.get_checksum(), 0xfe2d);

        tcp_header.set_urgent_pointer(0x0000);
        assert_eq!(tcp_header.get_urgent_pointer(), 0x0000);

        let mut opts: Vec<TcpOptions> = Vec::new();
        let tcp_option = TcpOptions{
            kind: 0x1,
            data: vec![0x01,0x08,0x0a,0x1d,0xfc,0xcb,0x76,0x1d,0xfc,0xbe,0x62],
        };
        opts.push(tcp_option);
        tcp_header.set_options(opts);
    }
}
<commit_msg>Attempt to fix len method; still broken test<commit_after>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// 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.

//! TCP packet abstraction

use packet::Packet;
use packet::HasPseudoheader;
use packet::checksum::rfc1071_checksum;
use pnet_macros::types::*;

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    sequence: u32be,
    acknowledgement: u32be,
    data_offset_and_reserved: u8,
    control_bits: u8,
    window: u16be,
    checksum: u16be,
    urgent_pointer: u16be,
    #[length_fn = "tcp_options_length"]
    options: Vec<TcpOptions>,
    #[length_fn = "tcp_padding_length"]
    padding: Vec<TcpPadding>,
    #[payload]
    payload: Vec<u8>
}

fn tcp_options_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The data offset field specifies the total size of the TCP header
       in 32-bit words. The minimum size of a TCP header is 20 bytes and thus
       TCP headers must have data offset set to 5 or more.
     */
    let mut v = tcp.get_data_offset_and_reserved();
    v  = v >> 4;
    v = v * 4;
    return v as usize;
}

/// Represents the TCP Option fields
#[packet]
pub struct TcpOptions {
    kind: u8,
    #[payload]
    data: Vec<u8>
}

fn tcp_padding_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The TCP header padding is used to ensure that the entire header
       ends on a 32 bit boundary.
     */
    return tcp.get_data_offset_and_reserved() as usize % 4;
}

/// Represents the TCP header padding
#[packet]
pub struct TcpPadding {
    #[payload]
    data: Vec<u8>
}

/// Calculates the checksum of a TCP packet
/// The passed in TcpPacket must have it's initial checksum value set to zero.
pub fn checksum<'a, T: HasPseudoheader>(packet: &TcpPacket<'a>, encapsulating_packet: T) -> u16be {
    let mut sum = encapsulating_packet.pseudoheader_checksum();
    let length = packet.packet().len() as u32;
    sum = sum + length & 0xffff;
    sum = sum + length >> 16;
    return rfc1071_checksum(packet.packet(), sum);
}

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

    const TCP_MIN_HEADER_LEN: usize = 20;
    const TCP_OPTIONS_LEN: usize = 12;
    const PAYLOAD_LEN: usize = 5;

    #[test]
    fn tcp_header_ipv4_test() {
        use pnet::packet::ip::IpNextHeaderProtocols;
        use pnet::packet::ipv4::{Ipv4Packet,MutableIpv4Packet};
        use std::net::{Ipv4Addr};

        const IPV4_HEADER_LEN: usize = 20;

        let mut packet = [0u8; IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + PAYLOAD_LEN];
        let ipv4_source = Ipv4Addr::new(127, 0, 0, 1);
        let ipv4_destination = Ipv4Addr::new(127, 0, 0, 1);
        let next_level_protocol = IpNextHeaderProtocols::Tcp;
        let mut csum = 0;

        {
            let mut mut_ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
            mut_ip_header.set_next_level_protocol(next_level_protocol);
            mut_ip_header.set_source(ipv4_source);
            mut_ip_header.set_destination(ipv4_destination);
        }

        {
            let mut mutable_tcp_header = MutableTcpPacket::new(&mut packet[IPV4_HEADER_LEN..]).unwrap();
            mutable_tcp_header.set_checksum(0);
        }

        {
            let ip_header = Ipv4Packet::new(&packet[..IPV4_HEADER_LEN]).unwrap();
            let tcp_header = TcpPacket::new(&packet[IPV4_HEADER_LEN..]).unwrap();
            csum = checksum(&tcp_header, ip_header);
        }

        {
            let mut mutable_tcp_header = MutableTcpPacket::new(&mut packet[IPV4_HEADER_LEN..]).unwrap();
            mutable_tcp_header.set_checksum(csum);
        }

        {
            generate_simple_tcp_header(&mut packet[IPV4_HEADER_LEN..]);
        }

        // Set payload data
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 0] = 'm' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 1] = 'e' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 2] = 'o' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 3] = 'w' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 4] = '\n' as u8;

        let ref_tcp_packet = [0xe0, 0x0f, // source port
                              0x25, 0xc2, // dest port
                              0xdf, 0x06, // sequence
                              0xe6, 0xe6,
                              0xc9, 0x2d, // acknowledgement
                              0x98, 0x71,
                              0x80,       // header length + reserved
                              0x18,       // control bits
                              0x02, 0xab, // window
                              0xfe, 0x2d, // checksum
                              0x00, 0x00, // urgent pointer
                              0x01, 0x01, // tcp option no-op
                              0x08, 0x0a, // tcp option timestamp, options length == 10 bytes
                              0x1d, 0xfc, // 4-byte send timestamp
                              0xcb, 0x76,
                              0x1d, 0xfc, // 4-byte latest replied timestamp
                              0xbe, 0x62,
                              0x6d, 0x65, // payload
                              0x6f, 0x77, 0x0a];
        assert_eq!(&ref_tcp_packet[..], &packet[IPV4_HEADER_LEN..]);

        //tcp/ipv4 == "45, 00 00 39 58 89 40 00 40 06 e4 33 7f 00 00 01 7f 00 00 01 e0 0f 25 c2 df 06 e6 e6 c9 2d 98 71 80 18 02 ab fe 2d 00 00 01 01 08 0a 1d fc cb 76 1d fc be 62 6d 65 6f 77 0a";

    }

    fn generate_simple_tcp_header<'p>(packet: &'p mut [u8]) {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[..]).unwrap();
        tcp_header.set_source(57359);
        assert_eq!(tcp_header.get_source(), 57359);

        tcp_header.set_destination(9666);
        assert_eq!(tcp_header.get_destination(), 9666);

        tcp_header.set_sequence(3741771494);
        assert_eq!(tcp_header.get_sequence(), 3741771494);

        tcp_header.set_acknowledgement(3375208561);
        assert_eq!(tcp_header.get_acknowledgement(), 3375208561);

        tcp_header.set_data_offset_and_reserved(0x80);
        assert_eq!(tcp_header.get_data_offset_and_reserved(), 0x80);

        tcp_header.set_control_bits(0x18);
        assert_eq!(tcp_header.get_control_bits(), 0x18);

        tcp_header.set_window(0x02ab);
        assert_eq!(tcp_header.get_window(), 0x02ab);

        tcp_header.set_checksum(0xfe2d);
        assert_eq!(tcp_header.get_checksum(), 0xfe2d);

        tcp_header.set_urgent_pointer(0x0000);
        assert_eq!(tcp_header.get_urgent_pointer(), 0x0000);

        let mut opts: Vec<TcpOptions> = Vec::new();
        let tcp_option = TcpOptions{
            kind: 0x1,
            data: vec![0x01,0x08,0x0a,0x1d,0xfc,0xcb,0x76,0x1d,0xfc,0xbe,0x62],
        };
        opts.push(tcp_option);
        tcp_header.set_options(opts);
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-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.

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

use std::char;
use std::mem;

use {Rand,Rng};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    #[test]
    fn floating_point_edge_cases() {
        // the test for exact equality is correct here.
        assert!(ConstantRng(0xffff_ffff).gen::<f32>() != 1.0);
        assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::<f64>() != 1.0);
    }

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

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

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

            let Closed01(f) = rng.gen::<Closed01<f32>>();
            assert!(0.0 <= f && f <= 1.0);
        }
    }
}
<commit_msg>Implement Rand for arrays with n <= 32<commit_after>// Copyright 2013-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.

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

use std::char;
use std::mem;

use {Rand,Rng};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    #[test]
    fn floating_point_edge_cases() {
        // the test for exact equality is correct here.
        assert!(ConstantRng(0xffff_ffff).gen::<f32>() != 1.0);
        assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::<f64>() != 1.0);
    }

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

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

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

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


<commit_before>use std::rc::Rc;
use std::string::ToString;
use std::collections::HashMap;

use regex::{Regex, RegexSet, Captures};

#[doc(hidden)]
pub struct RouteRecognizer<T> {
    prefix: usize,
    patterns: RegexSet,
    routes: Vec<(Pattern, T)>,
}

impl<T> Default for RouteRecognizer<T> {

    fn default() -> Self {
        RouteRecognizer {
            prefix: 0,
            patterns: RegexSet::new([""].iter()).unwrap(),
            routes: Vec::new(),
        }
    }
}

impl<T> RouteRecognizer<T> {

    pub fn new<P: ToString, U>(prefix: P, routes: U) -> Self
        where U: IntoIterator<Item=(String, T)>
    {
        let mut paths = Vec::new();
        let mut handlers = Vec::new();
        for item in routes {
            let pat = parse(&item.0);
            handlers.push((Pattern::new(&pat), item.1));
            paths.push(pat);
        };
        let regset = RegexSet::new(&paths);

        RouteRecognizer {
            prefix: prefix.to_string().len() - 1,
            patterns: regset.unwrap(),
            routes: handlers,
        }
    }

    pub fn set_routes(&mut self, routes: Vec<(&str, T)>) {
        let mut paths = Vec::new();
        let mut handlers = Vec::new();
        for item in routes {
            let pat = parse(item.0);
            handlers.push((Pattern::new(&pat), item.1));
            paths.push(pat);
        };
        self.patterns = RegexSet::new(&paths).unwrap();
        self.routes = handlers;
    }

    pub fn set_prefix<P: ToString>(&mut self, prefix: P) {
        self.prefix = prefix.to_string().len() - 1;
    }

    pub fn recognize(&self, path: &str) -> Option<(Option<Params>, &T)> {
        if let Some(idx) = self.patterns.matches(&path[self.prefix..]).into_iter().next()
        {
            let (ref pattern, ref route) = self.routes[idx];
            Some((pattern.match_info(&path[self.prefix..]), route))
        } else {
            None
        }
    }
}

struct Pattern {
    re: Regex,
    names: Rc<HashMap<String, usize>>,
}

impl Pattern {
    fn new(pattern: &str) -> Self {
        let re = Regex::new(pattern).unwrap();
        let names = re.capture_names()
            .enumerate()
            .filter_map(|(i, name)| name.map(|name| (name.to_owned(), i)))
            .collect();

        Pattern {
            re,
            names: Rc::new(names),
        }
    }

    fn match_info(&self, text: &str) -> Option<Params> {
        let captures = match self.re.captures(text) {
            Some(captures) => captures,
            None => return None,
        };

        Some(Params::new(Rc::clone(&self.names), text, captures))
    }
}

pub(crate) fn check_pattern(path: &str) {
    if let Err(err) = Regex::new(&parse(path)) {
        panic!("Wrong path pattern: \"{}\" {}", path, err);
    }
}

fn parse(pattern: &str) -> String {
    const DEFAULT_PATTERN: &'static str = "[^/]+";

    let mut re = String::from("^/");
    let mut in_param = false;
    let mut in_param_pattern = false;
    let mut param_name = String::new();
    let mut param_pattern = String::from(DEFAULT_PATTERN);

    for (index, ch) in pattern.chars().enumerate() {
        // All routes must have a leading slash so its optional to have one
        if index == 0 && ch == '/' {
            continue;
        }

        if in_param {
            // In parameter segment: `{....}`
            if ch == '}' {
                re.push_str(&format!(r"(?P<{}>{})", &param_name, &param_pattern));

                param_name.clear();
                param_pattern = String::from(DEFAULT_PATTERN);

                in_param_pattern = false;
                in_param = false;
            } else if ch == ':' {
                // The parameter name has been determined; custom pattern land
                in_param_pattern = true;
                param_pattern.clear();
            } else if in_param_pattern {
                // Ignore leading whitespace for pattern
                if !(ch == ' ' && param_pattern.is_empty()) {
                    param_pattern.push(ch);
                }
            } else {
                param_name.push(ch);
            }
        } else if ch == '{' {
            in_param = true;
        } else {
            re.push(ch);
        }
    }

    re.push('$');
    re
}

/// Route match information
///
/// If resource path contains variable patterns, `Params` stores this variables.
#[derive(Debug)]
pub struct Params {
    text: String,
    matches: Vec<Option<(usize, usize)>>,
    names: Rc<HashMap<String, usize>>,
}

impl Params {
    pub(crate) fn new(names: Rc<HashMap<String, usize>>,
                      text: &str,
                      captures: Captures) -> Self
    {
        Params {
            names,
            text: text.into(),
            matches: captures
                .iter()
                .map(|capture| capture.map(|m| (m.start(), m.end())))
                .collect(),
        }
    }

    pub(crate) fn empty() -> Self
    {
        Params {
            text: String::new(),
            names: Rc::new(HashMap::new()),
            matches: Vec::new(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.names.is_empty()
    }

    fn by_idx(&self, index: usize) -> Option<&str> {
        self.matches
            .get(index + 1)
            .and_then(|m| m.map(|(start, end)| &self.text[start..end]))
    }

    /// Get matched parameter by name
    pub fn get(&self, key: &str) -> Option<&str> {
        self.names.get(key).and_then(|&i| self.by_idx(i - 1))
    }
}
<commit_msg>better path recognision<commit_after>use std::rc::Rc;
use std::string::ToString;
use std::collections::HashMap;

use regex::{Regex, RegexSet, Captures};

#[doc(hidden)]
pub struct RouteRecognizer<T> {
    prefix: usize,
    patterns: RegexSet,
    routes: Vec<(Pattern, T)>,
}

impl<T> Default for RouteRecognizer<T> {

    fn default() -> Self {
        RouteRecognizer {
            prefix: 0,
            patterns: RegexSet::new([""].iter()).unwrap(),
            routes: Vec::new(),
        }
    }
}

impl<T> RouteRecognizer<T> {

    pub fn new<P: ToString, U>(prefix: P, routes: U) -> Self
        where U: IntoIterator<Item=(String, T)>
    {
        let mut paths = Vec::new();
        let mut handlers = Vec::new();
        for item in routes {
            let pat = parse(&item.0);
            handlers.push((Pattern::new(&pat), item.1));
            paths.push(pat);
        };
        let regset = RegexSet::new(&paths);

        RouteRecognizer {
            prefix: prefix.to_string().len() - 1,
            patterns: regset.unwrap(),
            routes: handlers,
        }
    }

    pub fn set_routes(&mut self, routes: Vec<(&str, T)>) {
        let mut paths = Vec::new();
        let mut handlers = Vec::new();
        for item in routes {
            let pat = parse(item.0);
            handlers.push((Pattern::new(&pat), item.1));
            paths.push(pat);
        };
        self.patterns = RegexSet::new(&paths).unwrap();
        self.routes = handlers;
    }

    pub fn set_prefix<P: ToString>(&mut self, prefix: P) {
        let p = prefix.to_string();
        if p.ends_with('/') {
            self.prefix = p.len() - 1;
        } else {
            self.prefix = p.len();
        }
    }

    pub fn recognize(&self, path: &str) -> Option<(Option<Params>, &T)> {
        let p = &path[self.prefix..];
        if p.is_empty() {
            if let Some(idx) = self.patterns.matches("/").into_iter().next() {
                let (ref pattern, ref route) = self.routes[idx];
                return Some((pattern.match_info(&path[self.prefix..]), route))
            }
        } else if let Some(idx) = self.patterns.matches(p).into_iter().next() {
            let (ref pattern, ref route) = self.routes[idx];
            return Some((pattern.match_info(&path[self.prefix..]), route))
        }
        None
    }
}

struct Pattern {
    re: Regex,
    names: Rc<HashMap<String, usize>>,
}

impl Pattern {
    fn new(pattern: &str) -> Self {
        let re = Regex::new(pattern).unwrap();
        let names = re.capture_names()
            .enumerate()
            .filter_map(|(i, name)| name.map(|name| (name.to_owned(), i)))
            .collect();

        Pattern {
            re,
            names: Rc::new(names),
        }
    }

    fn match_info(&self, text: &str) -> Option<Params> {
        let captures = match self.re.captures(text) {
            Some(captures) => captures,
            None => return None,
        };

        Some(Params::new(Rc::clone(&self.names), text, captures))
    }
}

pub(crate) fn check_pattern(path: &str) {
    if let Err(err) = Regex::new(&parse(path)) {
        panic!("Wrong path pattern: \"{}\" {}", path, err);
    }
}

fn parse(pattern: &str) -> String {
    const DEFAULT_PATTERN: &'static str = "[^/]+";

    let mut re = String::from("^/");
    let mut in_param = false;
    let mut in_param_pattern = false;
    let mut param_name = String::new();
    let mut param_pattern = String::from(DEFAULT_PATTERN);

    for (index, ch) in pattern.chars().enumerate() {
        // All routes must have a leading slash so its optional to have one
        if index == 0 && ch == '/' {
            continue;
        }

        if in_param {
            // In parameter segment: `{....}`
            if ch == '}' {
                re.push_str(&format!(r"(?P<{}>{})", &param_name, &param_pattern));

                param_name.clear();
                param_pattern = String::from(DEFAULT_PATTERN);

                in_param_pattern = false;
                in_param = false;
            } else if ch == ':' {
                // The parameter name has been determined; custom pattern land
                in_param_pattern = true;
                param_pattern.clear();
            } else if in_param_pattern {
                // Ignore leading whitespace for pattern
                if !(ch == ' ' && param_pattern.is_empty()) {
                    param_pattern.push(ch);
                }
            } else {
                param_name.push(ch);
            }
        } else if ch == '{' {
            in_param = true;
        } else {
            re.push(ch);
        }
    }

    re.push('$');
    re
}

/// Route match information
///
/// If resource path contains variable patterns, `Params` stores this variables.
#[derive(Debug)]
pub struct Params {
    text: String,
    matches: Vec<Option<(usize, usize)>>,
    names: Rc<HashMap<String, usize>>,
}

impl Params {
    pub(crate) fn new(names: Rc<HashMap<String, usize>>,
                      text: &str,
                      captures: Captures) -> Self
    {
        Params {
            names,
            text: text.into(),
            matches: captures
                .iter()
                .map(|capture| capture.map(|m| (m.start(), m.end())))
                .collect(),
        }
    }

    pub(crate) fn empty() -> Self
    {
        Params {
            text: String::new(),
            names: Rc::new(HashMap::new()),
            matches: Vec::new(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.names.is_empty()
    }

    fn by_idx(&self, index: usize) -> Option<&str> {
        self.matches
            .get(index + 1)
            .and_then(|m| m.map(|(start, end)| &self.text[start..end]))
    }

    /// Get matched parameter by name
    pub fn get(&self, key: &str) -> Option<&str> {
        self.names.get(key).and_then(|&i| self.by_idx(i - 1))
    }
}
<|endoftext|>


<commit_before>#[cfg(test)]
mod tests;

use gmp::{mpz, rand};
use std::fmt;
use std::result;

pub struct ShamirShare {
    pub data: mpz::Mpz,
    pub prime: mpz::Mpz, // The prime used to generate this share
    pub input: u64, // The input to the polynomial which gives "data" as the output
}

#[derive(Debug)]
pub enum ShamirError {
    InvalidArgument(String),
    PrimeMismatch,
}

impl fmt::Display for ShamirError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ShamirError::InvalidArgument(ref err) => write!(f, "Invalid argument: {}", err),
            ShamirError::PrimeMismatch => {
                write!(f,
                       "Prime mismatch: not all shares have the same prime number.")
            }
        }
    }
}

pub type Result<T> = result::Result<T, ShamirError>;

/// Generates a Vec<ShamirShare> from a given secret.
///
/// # Failures
///
/// Returns ShamirError::InvalidArgument when the number of pieces generated is
/// less than the number of pieces required to rebuild, and when either num_pieces
/// or required_pieces is 0.
///
/// # Examples
///
/// ```
/// use shamir::{ShamirShare, generate_shares};
///
/// let data: Vec<u8> = Vec::from("Hello World");
/// let result = generate_shares(data.as_slice(), 5, 3);
/// let shares: Vec<ShamirShare>;
/// match result {
///     Ok(s) => shares = s,
///     Err(err) => panic!("could not generate shares"),
/// }
/// ```
pub fn generate_shares(secret: &[u8],
                       num_pieces: u64,
                       required_pieces: u64)
                       -> Result<Vec<ShamirShare>> {
    if required_pieces > num_pieces {
        return Err(ShamirError::InvalidArgument("required_pieces must be less than or equal to \
                                                 num_pieces"
                                                    .to_string()));
    }
    if required_pieces <= 0 || num_pieces <= 0 {
        return Err(ShamirError::InvalidArgument("required_pieces or num_pieces cannot be less \
                                                 than or equal to 0"
                                                    .to_string()));
    }
    let prime_size: u64 = (secret.len() as f64 * 1.1 * 8.0) as u64;
    let mut randstate = rand::RandState::new_mt();
    let mut prime = randstate.urandom_2exp(prime_size);
    prime = prime.nextprime();

    let mut coefficients: Vec<mpz::Mpz> = Vec::new();
    let big_secret = mpz::Mpz::from(secret);
    coefficients.push(big_secret);

    for _ in 1..required_pieces {
        let tmp = randstate.urandom(&prime);
        coefficients.push(tmp);
    }

    let mut pieces: Vec<ShamirShare> = Vec::new();
    for x in 1..num_pieces + 1 {
        let mut total = mpz::Mpz::zero();
        for i in 0..required_pieces as usize {
            let degree_total = &coefficients[i] * (mpz::Mpz::from(x).pow(i as u32));
            total = total + degree_total;
        }
        total = total.modulus(&prime);
        pieces.push(ShamirShare {
            data: total,
            prime: prime.clone(),
            input: x,
        });
    }
    Ok(pieces)
}

/// Rebuild a secret from a given set of ShamirShares.
///
/// # Failures
///
/// If the set of shares do not share a common prime number, then they
/// definitely did not all come from the same secret. In this case, we return
/// ShamirError::PrimeMismatch.
///
/// # Examples
///
/// ```
/// use shamir::{ShamirShare, generate_shares, rebuild_secret};
///
/// let data: Vec<u8> = Vec::from("Hello World");
/// let shares = generate_shares(data.as_slice(), 5, 3).unwrap();
/// let secret: Vec<u8>;
/// let result = rebuild_secret(shares.as_slice());
/// match result {
///     Ok(sec) => secret = sec,
///     Err(err) => panic!("error rebuilding secret"),
/// }
/// ```
pub fn rebuild_secret(shares: &[ShamirShare]) -> Result<Vec<u8>> {
    let prime = &shares[0].prime;
    for share in shares {
        if *prime != share.prime {
            return Err(ShamirError::PrimeMismatch);
        }
    }
    let mut inputs: Vec<i64> = Vec::new();
    for i in 0..shares.len() {
        inputs.push(shares[i].input as i64);
    }

    let mut sum = mpz::Mpz::zero();
    for i in 0..shares.len() {
        let mut numerator = mpz::Mpz::one();
        let mut denominator = mpz::Mpz::one();
        for j in 0..shares.len() {
            if j == i {
                continue;
            }
            numerator = (numerator * mpz::Mpz::from(-inputs[j])) % prime;
            denominator = (denominator * mpz::Mpz::from(inputs[i] - inputs[j])) % prime;
        }
        let tmp = &shares[i].data * numerator * denominator.invert(prime).unwrap();
        sum = (sum + prime + tmp) % prime;
    }
    Ok(Into::<Option<Vec<u8>>>::into(&sum).unwrap())
}
<commit_msg>Changed Option<Vec<u8>> to Vec<u8>.<commit_after>#[cfg(test)]
mod tests;

use gmp::{mpz, rand};
use std::fmt;
use std::result;

pub struct ShamirShare {
    pub data: mpz::Mpz,
    pub prime: mpz::Mpz, // The prime used to generate this share
    pub input: u64, // The input to the polynomial which gives "data" as the output
}

#[derive(Debug)]
pub enum ShamirError {
    InvalidArgument(String),
    PrimeMismatch,
}

impl fmt::Display for ShamirError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ShamirError::InvalidArgument(ref err) => write!(f, "Invalid argument: {}", err),
            ShamirError::PrimeMismatch => {
                write!(f,
                       "Prime mismatch: not all shares have the same prime number.")
            }
        }
    }
}

pub type Result<T> = result::Result<T, ShamirError>;

/// Generates a Vec<ShamirShare> from a given secret.
///
/// # Failures
///
/// Returns ShamirError::InvalidArgument when the number of pieces generated is
/// less than the number of pieces required to rebuild, and when either num_pieces
/// or required_pieces is 0.
///
/// # Examples
///
/// ```
/// use shamir::{ShamirShare, generate_shares};
///
/// let data: Vec<u8> = Vec::from("Hello World");
/// let result = generate_shares(data.as_slice(), 5, 3);
/// let shares: Vec<ShamirShare>;
/// match result {
///     Ok(s) => shares = s,
///     Err(err) => panic!("could not generate shares"),
/// }
/// ```
pub fn generate_shares(secret: &[u8],
                       num_pieces: u64,
                       required_pieces: u64)
                       -> Result<Vec<ShamirShare>> {
    if required_pieces > num_pieces {
        return Err(ShamirError::InvalidArgument("required_pieces must be less than or equal to \
                                                 num_pieces"
                                                    .to_string()));
    }
    if required_pieces <= 0 || num_pieces <= 0 {
        return Err(ShamirError::InvalidArgument("required_pieces or num_pieces cannot be less \
                                                 than or equal to 0"
                                                    .to_string()));
    }
    let prime_size: u64 = (secret.len() as f64 * 1.1 * 8.0) as u64;
    let mut randstate = rand::RandState::new_mt();
    let mut prime = randstate.urandom_2exp(prime_size);
    prime = prime.nextprime();

    let mut coefficients: Vec<mpz::Mpz> = Vec::new();
    let big_secret = mpz::Mpz::from(secret);
    coefficients.push(big_secret);

    for _ in 1..required_pieces {
        let tmp = randstate.urandom(&prime);
        coefficients.push(tmp);
    }

    let mut pieces: Vec<ShamirShare> = Vec::new();
    for x in 1..num_pieces + 1 {
        let mut total = mpz::Mpz::zero();
        for i in 0..required_pieces as usize {
            let degree_total = &coefficients[i] * (mpz::Mpz::from(x).pow(i as u32));
            total = total + degree_total;
        }
        total = total.modulus(&prime);
        pieces.push(ShamirShare {
            data: total,
            prime: prime.clone(),
            input: x,
        });
    }
    Ok(pieces)
}

/// Rebuild a secret from a given set of ShamirShares.
///
/// # Failures
///
/// If the set of shares do not share a common prime number, then they
/// definitely did not all come from the same secret. In this case, we return
/// ShamirError::PrimeMismatch.
///
/// # Examples
///
/// ```
/// use shamir::{ShamirShare, generate_shares, rebuild_secret};
///
/// let data: Vec<u8> = Vec::from("Hello World");
/// let shares = generate_shares(data.as_slice(), 5, 3).unwrap();
/// let secret: Vec<u8>;
/// let result = rebuild_secret(shares.as_slice());
/// match result {
///     Ok(sec) => secret = sec,
///     Err(err) => panic!("error rebuilding secret"),
/// }
/// ```
pub fn rebuild_secret(shares: &[ShamirShare]) -> Result<Vec<u8>> {
    let prime = &shares[0].prime;
    for share in shares {
        if *prime != share.prime {
            return Err(ShamirError::PrimeMismatch);
        }
    }
    let mut inputs: Vec<i64> = Vec::new();
    for i in 0..shares.len() {
        inputs.push(shares[i].input as i64);
    }

    let mut sum = mpz::Mpz::zero();
    for i in 0..shares.len() {
        let mut numerator = mpz::Mpz::one();
        let mut denominator = mpz::Mpz::one();
        for j in 0..shares.len() {
            if j == i {
                continue;
            }
            numerator = (numerator * mpz::Mpz::from(-inputs[j])) % prime;
            denominator = (denominator * mpz::Mpz::from(inputs[i] - inputs[j])) % prime;
        }
        let tmp = &shares[i].data * numerator * denominator.invert(prime).unwrap();
        sum = (sum + prime + tmp) % prime;
    }
    Ok(Into::<Vec<u8>>::into(&sum))
}
<|endoftext|>


<commit_before>use std::convert::From;
use std::io::{self, Read};
use std::iter::Iterator;
use std::path::{Component, Path, PathBuf};
use std::slice;

use flate2::read::GzDecoder;
use tar;
use time::Timespec;

use backend::Backend;
use collections::{CollectionsStatus, SignatureFile};

pub struct BackupFiles {
    chains: Vec<Chain>
}

pub struct Snapshot {
    pub time: Timespec
}

pub struct File {
    pub name: String,
    pub last_modified: Timespec
}

/// Iterator over a list of backup snapshots.
pub type Snapshots<'a> = slice::Iter<'a, Snapshot>;

enum DiffType {
    Signature,
    Snapshot,
    Deleted
}

/// Store separately informations about the signatures and informations about the paths in the
/// signatures. This allows to reuse informations between snapshots and avoid duplicating them.
struct Chain {
    timestamps: Vec<Timespec>,
    files: Vec<PathSnapshots>
}

struct PathSnapshots {
    // the directory or file path
    path: PathBuf,
    // all the snapshots for this path
    snapshots: Vec<PathSnapshot>
}

struct PathSnapshot {
    // info are None if the snapshot has deleted this path
    info: Option<PathInfo>,
    // the index of the snapshot in the chain
    index: u8
}

/// Informations about a path inside a snapshot.
struct PathInfo {
    mtime: Timespec
}

impl BackupFiles {
    pub fn new<B: Backend>(backend: &B) -> io::Result<BackupFiles> {
        let collection = {
            let filenames = try!(backend.get_file_names());
            CollectionsStatus::from_filenames(&filenames)
        };
        let mut chains: Vec<Chain> = Vec::new();
        let coll_chains = collection.signature_chains();
        for coll_chain in coll_chains {
            // translate collections::SignatureChain into a Chain
            let mut chain = Chain{ timestamps: Vec::new(), files: Vec::new() };
            // add to the chain the full signature and all the incremental signatures
            // if an error occurs in the full signature exit
            let file = try!(backend.open_file(coll_chain.fullsig.file_name.as_ref()));
            try!(add_sigfile_to_chain(&mut chain, file, &coll_chain.fullsig));
            for inc in coll_chain.inclist.iter() {
                // TODO: if an error occurs here, do not exit with an error, instead
                // break the iteration and store the error inside the chain
                let file = try!(backend.open_file(inc.file_name.as_ref()));
                try!(add_sigfile_to_chain(&mut chain, file, &inc));
            }
            chains.push(chain);
        }
        Ok(BackupFiles{ chains: chains })
    }

    pub fn snapshots(&self) -> Snapshots {
        unimplemented!()
    }
}

fn add_sigfile_to_chain<R: Read>(chain: &mut Chain,
                                 file: R,
                                 sigfile: &SignatureFile) -> io::Result<()>
{
    let result = {
        let snapshot_id = chain.files.len() as u8;
        if sigfile.compressed {
            let gz_decoder = try!(GzDecoder::new(file));
            add_sigtar_to_snapshots(&mut chain.files, tar::Archive::new(gz_decoder), snapshot_id)
        }
        else {
            add_sigtar_to_snapshots(&mut chain.files, tar::Archive::new(file), snapshot_id)
        }
    };
    if result.is_ok() {
        // add to the list of signatures only if everything is ok
        // we do not need to cleanup the chain if someting went wrong, because if the list of
        // signatures is not updated, the change is not observable
        chain.timestamps.push(sigfile.time);
    }
    result
}

fn add_sigtar_to_snapshots<R: Read>(snapshots: &mut Vec<PathSnapshots>,
                                    mut tar: tar::Archive<R>,
                                    snapshot_id: u8) -> io::Result<()>
{
    for tarfile in try!(tar.files_mut()) {
        // we can ignore paths with errors
        // the only problem here is that we miss some change in the chain, but it is better
        // than abort the whole signature
        let tarfile = unwrap_or_continue!(tarfile);
        let header = tarfile.header();
        let path = unwrap_or_continue!(header.path());
        let (difftype, path) = unwrap_opt_or_continue!(parse_snapshot_path(&path));
    }
    Ok(())
}

fn parse_snapshot_path(path: &Path) -> Option<(DiffType, &Path)> {
    // split the path in (first directory, the remaining path)
    // the first is the type, the remaining is the real path
    let mut pcomps = path.components();
    let pfirst = try_opt!(pcomps.next());
    if let Component::Normal(strfirst) = pfirst {
        let difftype = match strfirst.to_str() {
            Some("signature") => DiffType::Signature,
            Some("snapshot")  => DiffType::Snapshot,
            Some("deleted")   => DiffType::Deleted,
            _                 => { return None; }
        };
        let realpath = pcomps.as_path();
        Some((difftype, realpath))
    }
    else {
        None
    }
}

<commit_msg>Completed snapshots creation<commit_after>use std::io::{self, Read};
use std::iter::Iterator;
use std::path::{Component, Path, PathBuf};
use std::slice;

use flate2::read::GzDecoder;
use tar;
use time::Timespec;

use backend::Backend;
use collections::{CollectionsStatus, SignatureFile};

pub struct BackupFiles {
    chains: Vec<Chain>
}

pub struct Snapshot {
    pub time: Timespec
}

pub struct File {
    pub name: String,
    pub last_modified: Timespec
}

/// Iterator over a list of backup snapshots.
pub type Snapshots<'a> = slice::Iter<'a, Snapshot>;

enum DiffType {
    Signature,
    Snapshot,
    Deleted
}

/// Store separately informations about the signatures and informations about the paths in the
/// signatures. This allows to reuse informations between snapshots and avoid duplicating them.
struct Chain {
    timestamps: Vec<Timespec>,
    files: Vec<PathSnapshots>
}

struct PathSnapshots {
    // the directory or file path
    path: PathBuf,
    // all the snapshots for this path
    snapshots: Vec<PathSnapshot>
}

struct PathSnapshot {
    // info are None if the snapshot has deleted this path
    info: Option<PathInfo>,
    // the index of the snapshot in the chain
    index: u8
}

/// Informations about a path inside a snapshot.
struct PathInfo {
    mtime: Timespec
}

impl BackupFiles {
    pub fn new<B: Backend>(backend: &B) -> io::Result<BackupFiles> {
        let collection = {
            let filenames = try!(backend.get_file_names());
            CollectionsStatus::from_filenames(&filenames)
        };
        let mut chains: Vec<Chain> = Vec::new();
        let coll_chains = collection.signature_chains();
        for coll_chain in coll_chains {
            // translate collections::SignatureChain into a Chain
            let mut chain = Chain{ timestamps: Vec::new(), files: Vec::new() };
            // add to the chain the full signature and all the incremental signatures
            // if an error occurs in the full signature exit
            let file = try!(backend.open_file(coll_chain.fullsig.file_name.as_ref()));
            try!(add_sigfile_to_chain(&mut chain, file, &coll_chain.fullsig));
            for inc in coll_chain.inclist.iter() {
                // TODO: if an error occurs here, do not exit with an error, instead
                // break the iteration and store the error inside the chain
                let file = try!(backend.open_file(inc.file_name.as_ref()));
                try!(add_sigfile_to_chain(&mut chain, file, &inc));
            }
            chains.push(chain);
        }
        Ok(BackupFiles{ chains: chains })
    }

    pub fn snapshots(&self) -> Snapshots {
        unimplemented!()
    }
}

fn add_sigfile_to_chain<R: Read>(chain: &mut Chain,
                                 file: R,
                                 sigfile: &SignatureFile) -> io::Result<()>
{
    let result = {
        let snapshot_id = chain.files.len() as u8;
        if sigfile.compressed {
            let gz_decoder = try!(GzDecoder::new(file));
            add_sigtar_to_snapshots(&mut chain.files, tar::Archive::new(gz_decoder), snapshot_id)
        }
        else {
            add_sigtar_to_snapshots(&mut chain.files, tar::Archive::new(file), snapshot_id)
        }
    };
    if result.is_ok() {
        // add to the list of signatures only if everything is ok
        // we do not need to cleanup the chain if someting went wrong, because if the list of
        // signatures is not updated, the change is not observable
        chain.timestamps.push(sigfile.time);
    }
    result
}

fn add_sigtar_to_snapshots<R: Read>(snapshots: &mut Vec<PathSnapshots>,
                                    mut tar: tar::Archive<R>,
                                    snapshot_id: u8) -> io::Result<()>
{
    let mut new_files: Vec<PathSnapshots> = Vec::new();
    {
        let mut old_snapshots = snapshots.iter_mut();
        for tarfile in try!(tar.files_mut()) {
            // we can ignore paths with errors
            // the only problem here is that we miss some change in the chain, but it is better
            // than abort the whole signature
            let tarfile = unwrap_or_continue!(tarfile);
            let header = tarfile.header();
            let path = unwrap_or_continue!(header.path());
            let (difftype, path) = unwrap_opt_or_continue!(parse_snapshot_path(&path));
            let info = match difftype {
                DiffType::Signature | DiffType::Snapshot => {
                    let time = Timespec::new(header.mtime().unwrap_or(0 as u64) as i64, 0);
                    Some(PathInfo{ mtime: time })
                }
                _ => None
            };
            let new_snapshot = PathSnapshot{ info: info, index: snapshot_id };
            // find the current path in the old snapshots
            // note: they are ordered
            while let Some(path_snapshots) = old_snapshots.next() {
                if path_snapshots.path.as_path() < path {
                    continue;
                }
                if path_snapshots.path.as_path() == path {
                    // this path is already present in old snapshots: update them
                    path_snapshots.snapshots.push(new_snapshot);
                }
                else {
                    // the path is not present in the old snapshots: add to new list
                    new_files.push(PathSnapshots{
                        path: path.to_path_buf(),
                        snapshots: vec![new_snapshot]
                    });
                }
                break;
            }
        }
    }
    // merge the new files with old snapthots
    if !new_files.is_empty() {
        // TODO: Performance hurt here: we have two sorted arrays to merge,
        // better to use this algorithm: http://stackoverflow.com/a/4553321/1667955
        snapshots.extend(new_files.into_iter());
        snapshots.sort_by(|a, b| a.path.cmp(&b.path));
    }
    Ok(())
}

fn parse_snapshot_path(path: &Path) -> Option<(DiffType, &Path)> {
    // split the path in (first directory, the remaining path)
    // the first is the type, the remaining is the real path
    let mut pcomps = path.components();
    let pfirst = try_opt!(pcomps.next());
    if let Component::Normal(strfirst) = pfirst {
        let difftype = match strfirst.to_str() {
            Some("signature") => DiffType::Signature,
            Some("snapshot")  => DiffType::Snapshot,
            Some("deleted")   => DiffType::Deleted,
            _                 => { return None; }
        };
        let realpath = pcomps.as_path();
        Some((difftype, realpath))
    }
    else {
        None
    }
}

<|endoftext|>


<commit_before>#![allow(unsafe_code)]

#[cfg(any(target_os = "linux", target_os = "macos"))]
use std::io;
#[cfg(any(target_os = "linux"))]
use {std::fs::File, std::io::Read};

/// See the Kernel's documentation for more information about this subsystem,
/// found at:  [Documentation/cgroup-v1/memory.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt)
///
/// If there's no memory limit specified on the container this may return
/// 0x7FFFFFFFFFFFF000 (2^63-1 rounded down to 4k which is a common page size).
/// So we know we are not running in a memory restricted environment.
#[cfg(target_os = "linux")]
fn get_cgroup_memory_limit() -> io::Result<u64> {
    File::open("/sys/fs/cgroup/memory/memory.limit_in_bytes")
        .and_then(read_u64_from)
}

#[cfg(target_os = "linux")]
fn read_u64_from(mut file: File) -> io::Result<u64> {
    let mut s = String::new();
    file.read_to_string(&mut s).and_then(|_| {
        s.trim()
            .parse()
            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
    })
}

/// Returns the maximum size of total available memory of the process, in bytes.
/// If this limit is exceeded, the malloc() and mmap() functions shall fail with
/// errno set to [ENOMEM].
#[cfg(any(target_os = "linux", target_os = "macos"))]
fn get_rlimit_as() -> io::Result<libc::rlimit> {
    let mut limit = std::mem::MaybeUninit::<libc::rlimit>::uninit();

    let ret = unsafe { libc::getrlimit(libc::RLIMIT_AS, limit.as_mut_ptr()) };

    if ret == 0 {
        Ok(unsafe { limit.assume_init() })
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub fn get_available_memory() -> io::Result<u64> {
    use std::convert::TryFrom;

    let pages = unsafe { libc::sysconf(libc::_SC_PHYS_PAGES) };
    if pages == -1 {
        return Err(io::Error::last_os_error());
    }

    let page_size = unsafe { libc::sysconf(libc::_SC_PAGE_SIZE) };
    if page_size == -1 {
        return Err(io::Error::last_os_error());
    }

    Ok(u64::try_from(pages).unwrap() * u64::try_from(page_size).unwrap())
}

pub fn get_memory_limit() -> u64 {
    // Maximum addressable memory space limit in u64
    static MAX_USIZE: u64 = usize::max_value() as u64;

    let mut max: u64 = 0;

    #[cfg(target_os = "linux")]
    {
        if let Ok(mem) = get_cgroup_memory_limit() {
            max = mem;
        }

        // If there's no memory limit specified on the container this
        // actually returns 0x7FFFFFFFFFFFF000 (2^63-1 rounded down to
        // 4k which is a common page size). So we know we are not
        // running in a memory restricted environment.
        // src: https://github.com/dotnet/coreclr/blob/master/src/pal/src/misc/cgroup.cpp#L385-L428
        if max > 0x7FFF_FFFF_0000_0000 {
            return 0;
        }
    }

    #[cfg(any(target_os = "linux", target_os = "macos"))]
    {
        if let Ok(rlim) = get_rlimit_as() {
            let rlim_cur = Into::<u64>::into(rlim.rlim_cur);
            if max == 0 || rlim_cur < max {
                max = rlim_cur;
            }
        }

        if let Ok(available) = get_available_memory() {
            if max == 0 || available < max {
                max = available;
            }
        }
    }

    if max > MAX_USIZE {
        // It is observed in practice when the memory is unrestricted, Linux
        // control group returns a physical limit that is bigger than
        // the address space
        max = MAX_USIZE;
    }

    #[cfg(miri)]
    {
        // Miri has a significant memory consumption overhead. During a small
        // test run, a memory amplification of ~35x was observed. Certain
        // memory overheads may increase asymptotically with longer test runs,
        // such as the interpreter's dead_alloc_map. Memory overhead is
        // dominated by stacked borrows tags; the asymptotic behavior of this
        // overhead needs further investigation.
        max /= 40;
    }

    max
}
<commit_msg>Avoid u64's in sys_limits module<commit_after>#![allow(unsafe_code)]

#[cfg(any(target_os = "linux", target_os = "macos"))]
use std::io;
#[cfg(any(target_os = "linux"))]
use {std::fs::File, std::io::Read};

use std::convert::TryFrom;

/// See the Kernel's documentation for more information about this subsystem,
/// found at:  [Documentation/cgroup-v1/memory.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt)
///
/// If there's no memory limit specified on the container this may return
/// 0x7FFFFFFFFFFFF000 (2^63-1 rounded down to 4k which is a common page size).
/// So we know we are not running in a memory restricted environment.
#[cfg(target_os = "linux")]
fn get_cgroup_memory_limit() -> io::Result<usize> {
    File::open("/sys/fs/cgroup/memory/memory.limit_in_bytes")
        .and_then(read_usize_from)
}

#[cfg(target_os = "linux")]
fn read_usize_from(mut file: File) -> io::Result<usize> {
    let mut s = String::new();
    file.read_to_string(&mut s).and_then(|_| {
        s.trim()
            .parse()
            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
    })
}

/// Returns the maximum size of total available memory of the process, in bytes.
/// If this limit is exceeded, the malloc() and mmap() functions shall fail with
/// errno set to [ENOMEM].
#[cfg(any(target_os = "linux", target_os = "macos"))]
fn get_rlimit_as() -> io::Result<libc::rlimit> {
    let mut limit = std::mem::MaybeUninit::<libc::rlimit>::uninit();

    let ret = unsafe { libc::getrlimit(libc::RLIMIT_AS, limit.as_mut_ptr()) };

    if ret == 0 {
        Ok(unsafe { limit.assume_init() })
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub fn get_available_memory() -> io::Result<usize> {
    let pages = unsafe { libc::sysconf(libc::_SC_PHYS_PAGES) };
    if pages == -1 {
        return Err(io::Error::last_os_error());
    }

    let page_size = unsafe { libc::sysconf(libc::_SC_PAGE_SIZE) };
    if page_size == -1 {
        return Err(io::Error::last_os_error());
    }

    Ok(usize::try_from(pages).unwrap() * usize::try_from(page_size).unwrap())
}

pub fn get_memory_limit() -> Option<usize> {
    let mut max: usize = 0;

    #[cfg(target_os = "linux")]
    {
        if let Ok(mem) = get_cgroup_memory_limit() {
            max = mem;
        }

        // If there's no memory limit specified on the container this
        // actually returns 0x7FFFFFFFFFFFF000 (2^63-1 rounded down to
        // 4k which is a common page size). So we know we are not
        // running in a memory restricted environment.
        // src: https://github.com/dotnet/coreclr/blob/master/src/pal/src/misc/cgroup.cpp#L385-L428
        if max > 0x7FFF_FFFF_0000_0000 {
            return None;
        }
    }

    #[cfg(any(target_os = "linux", target_os = "macos"))]
    {
        if let Ok(rlim) = get_rlimit_as() {
            let rlim_cur = usize::try_from(rlim.rlim_cur).unwrap();
            if max == 0 || rlim_cur < max {
                max = rlim_cur;
            }
        }

        if let Ok(available) = get_available_memory() {
            if max == 0 || available < max {
                max = available;
            }
        }
    }

    #[cfg(miri)]
    {
        // Miri has a significant memory consumption overhead. During a small
        // test run, a memory amplification of ~35x was observed. Certain
        // memory overheads may increase asymptotically with longer test runs,
        // such as the interpreter's dead_alloc_map. Memory overhead is
        // dominated by stacked borrows tags; the asymptotic behavior of this
        // overhead needs further investigation.
        max /= 40;
    }

    Some(max)
}
<|endoftext|>


<commit_before>use ::{Client, Term};
use types::data;

pub trait IntoTerm {
    fn into_term(self) -> Term;
}

impl IntoTerm for String {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl<'a> IntoTerm for &'a String {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl<'a> IntoTerm for &'a str {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl<O> IntoTerm for Client<data::Number, O> {
    fn into_term(self) -> Term {
        self.cmd.0.into()
    }
}

impl IntoTerm for f32 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl IntoTerm for i32 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl IntoTerm for u32 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl IntoTerm for f64 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl IntoTerm for i64 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl IntoTerm for u64 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl<O> IntoTerm for Client<data::Bool, O> {
    fn into_term(self) -> Term {
        self.cmd.0.into()
    }
}

impl IntoTerm for bool {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}
<commit_msg>Impl IntoTerm for client string<commit_after>use ::{Client, Term};
use types::data;

pub trait IntoTerm {
    fn into_term(self) -> Term;
}

impl<O> IntoTerm for Client<data::String, O> {
    fn into_term(self) -> Term {
        self.cmd.0.into()
    }
}

impl IntoTerm for String {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl<'a> IntoTerm for &'a String {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl<'a> IntoTerm for &'a str {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl<O> IntoTerm for Client<data::Number, O> {
    fn into_term(self) -> Term {
        self.cmd.0.into()
    }
}

impl IntoTerm for f32 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl IntoTerm for i32 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl IntoTerm for u32 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl IntoTerm for f64 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl IntoTerm for i64 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl IntoTerm for u64 {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}

impl<O> IntoTerm for Client<data::Bool, O> {
    fn into_term(self) -> Term {
        self.cmd.0.into()
    }
}

impl IntoTerm for bool {
    fn into_term(self) -> Term {
        Term::from_json(self)
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

pub mod ll;
pub mod ops;

pub trait BlasVector<T> {
    fn inc(&self) -> i32;
    fn len(&self) -> i32;
    fn as_ptr(&self) -> *const T;
    fn as_mut_ptr(&mut self) -> *mut T;
}
<commit_msg>Implement BlasVector on Vec and slice<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use std::raw::Repr;

pub mod ll;
pub mod ops;

pub trait BlasVector<T> {
    fn inc(&self) -> i32;
    fn len(&self) -> i32;
    fn as_ptr(&self) -> *const T;
    fn as_mut_ptr(&mut self) -> *mut T;
}

impl<T> BlasVector<T> for Vec<T> {
    #[inline]
    fn inc(&self) -> i32 { 1i32 }

    #[inline]
    fn len(&self) -> i32 {
        let l: Option<i32> = NumCast::from(self.len());
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn as_ptr(&self) -> *const T { self.as_slice().as_ptr() }

    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T { self.as_mut_slice().as_mut_ptr() }
}

impl<'a, T> BlasVector<T> for &'a [T] {
    #[inline]
    fn inc(&self) -> i32 { 1i32 }

    #[inline]
    fn len(&self) -> i32 {
        let l: Option<i32> = NumCast::from(self.len());
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn as_ptr(&self) -> *const T { self.repr().data }

    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T { self.repr().data as *mut T }
}
<|endoftext|>


<commit_before>//! lint on missing cargo common metadata

use std::path::PathBuf;

use crate::utils::{run_lints, span_lint};
use rustc_hir::{hir_id::CRATE_HIR_ID, Crate};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::DUMMY_SP;

declare_clippy_lint! {
    /// **What it does:** Checks to see if all common metadata is defined in
    /// `Cargo.toml`. See: https://rust-lang-nursery.github.io/api-guidelines/documentation.html#cargotoml-includes-all-common-metadata-c-metadata
    ///
    /// **Why is this bad?** It will be more difficult for users to discover the
    /// purpose of the crate, and key information related to it.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```toml
    /// # This `Cargo.toml` is missing an authors field:
    /// [package]
    /// name = "clippy"
    /// version = "0.0.212"
    /// authors = ["Someone <someone@rust-lang.org>"]
    /// description = "A bunch of helpful lints to avoid common pitfalls in Rust"
    /// repository = "https://github.com/rust-lang/rust-clippy"
    /// readme = "README.md"
    /// license = "MIT OR Apache-2.0"
    /// keywords = ["clippy", "lint", "plugin"]
    /// categories = ["development-tools", "development-tools::cargo-plugins"]
    /// ```
    pub CARGO_COMMON_METADATA,
    cargo,
    "common metadata is defined in `Cargo.toml`"
}

fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, field: &str) {
    let message = format!("package `{}` is missing `{}` metadata", package.name, field);
    span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message);
}

fn is_empty_str(value: &Option<String>) -> bool {
    value.as_ref().map_or(true, String::is_empty)
}

fn is_empty_path(value: &Option<PathBuf>) -> bool {
    value.as_ref().and_then(|x| x.to_str()).map_or(true, str::is_empty)
}

fn is_empty_vec(value: &[String]) -> bool {
    // This works because empty iterators return true
    value.iter().all(String::is_empty)
}

declare_lint_pass!(CargoCommonMetadata => [CARGO_COMMON_METADATA]);

impl LateLintPass<'_> for CargoCommonMetadata {
    fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
        if !run_lints(cx, &[CARGO_COMMON_METADATA], CRATE_HIR_ID) {
            return;
        }

        let metadata = unwrap_cargo_metadata!(cx, CARGO_COMMON_METADATA, false);

        for package in metadata.packages {
            if is_empty_vec(&package.authors) {
                missing_warning(cx, &package, "package.authors");
            }

            if is_empty_str(&package.description) {
                missing_warning(cx, &package, "package.description");
            }

            if is_empty_str(&package.license) && is_empty_path(&package.license_file) {
                missing_warning(cx, &package, "either package.license or package.license_file");
            }

            if is_empty_str(&package.repository) {
                missing_warning(cx, &package, "package.repository");
            }

            if is_empty_path(&package.readme) {
                missing_warning(cx, &package, "package.readme");
            }

            if is_empty_vec(&package.keywords) {
                missing_warning(cx, &package, "package.keywords");
            }

            if is_empty_vec(&package.categories) {
                missing_warning(cx, &package, "package.categories");
            }
        }
    }
}
<commit_msg>Fix example for cargo common data<commit_after>//! lint on missing cargo common metadata

use std::path::PathBuf;

use crate::utils::{run_lints, span_lint};
use rustc_hir::{hir_id::CRATE_HIR_ID, Crate};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::DUMMY_SP;

declare_clippy_lint! {
    /// **What it does:** Checks to see if all common metadata is defined in
    /// `Cargo.toml`. See: https://rust-lang-nursery.github.io/api-guidelines/documentation.html#cargotoml-includes-all-common-metadata-c-metadata
    ///
    /// **Why is this bad?** It will be more difficult for users to discover the
    /// purpose of the crate, and key information related to it.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```toml
    /// # This `Cargo.toml` is missing an authors field:
    /// [package]
    /// name = "clippy"
    /// version = "0.0.212"
    /// description = "A bunch of helpful lints to avoid common pitfalls in Rust"
    /// repository = "https://github.com/rust-lang/rust-clippy"
    /// readme = "README.md"
    /// license = "MIT OR Apache-2.0"
    /// keywords = ["clippy", "lint", "plugin"]
    /// categories = ["development-tools", "development-tools::cargo-plugins"]
    /// ```
    ///
    /// Should include an authors field like:
    ///
    /// ```toml
    /// # This `Cargo.toml` includes all common metadata
    /// [package]
    /// name = "clippy"
    /// version = "0.0.212"
    /// authors = ["Someone <someone@rust-lang.org>"]
    /// description = "A bunch of helpful lints to avoid common pitfalls in Rust"
    /// repository = "https://github.com/rust-lang/rust-clippy"
    /// readme = "README.md"
    /// license = "MIT OR Apache-2.0"
    /// keywords = ["clippy", "lint", "plugin"]
    /// categories = ["development-tools", "development-tools::cargo-plugins"]
    /// ```
    pub CARGO_COMMON_METADATA,
    cargo,
    "common metadata is defined in `Cargo.toml`"
}

fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, field: &str) {
    let message = format!("package `{}` is missing `{}` metadata", package.name, field);
    span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message);
}

fn is_empty_str(value: &Option<String>) -> bool {
    value.as_ref().map_or(true, String::is_empty)
}

fn is_empty_path(value: &Option<PathBuf>) -> bool {
    value.as_ref().and_then(|x| x.to_str()).map_or(true, str::is_empty)
}

fn is_empty_vec(value: &[String]) -> bool {
    // This works because empty iterators return true
    value.iter().all(String::is_empty)
}

declare_lint_pass!(CargoCommonMetadata => [CARGO_COMMON_METADATA]);

impl LateLintPass<'_> for CargoCommonMetadata {
    fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
        if !run_lints(cx, &[CARGO_COMMON_METADATA], CRATE_HIR_ID) {
            return;
        }

        let metadata = unwrap_cargo_metadata!(cx, CARGO_COMMON_METADATA, false);

        for package in metadata.packages {
            if is_empty_vec(&package.authors) {
                missing_warning(cx, &package, "package.authors");
            }

            if is_empty_str(&package.description) {
                missing_warning(cx, &package, "package.description");
            }

            if is_empty_str(&package.license) && is_empty_path(&package.license_file) {
                missing_warning(cx, &package, "either package.license or package.license_file");
            }

            if is_empty_str(&package.repository) {
                missing_warning(cx, &package, "package.repository");
            }

            if is_empty_path(&package.readme) {
                missing_warning(cx, &package, "package.readme");
            }

            if is_empty_vec(&package.keywords) {
                missing_warning(cx, &package, "package.keywords");
            }

            if is_empty_vec(&package.categories) {
                missing_warning(cx, &package, "package.categories");
            }
        }
    }
}
<|endoftext|>


<commit_before>use askama::Template;

#[derive(Template)]
#[template(path = "for.html")]
struct ForTemplate<'a> {
    strings: Vec<&'a str>,
    tuple_strings: Vec<(&'a str, &'a str)>,
}

#[test]
fn test_for() {
    let s = ForTemplate {
        strings: vec!["A", "alfa", "1"],
        tuple_strings: vec![("B", "beta")],
    };
    assert_eq!(
        s.render().unwrap(),
        "0. A (first)\n1. alfa\n2. 1\n\n0. B,beta (first)\n"
    );
}

#[derive(Template)]
#[template(path = "nested-for.html")]
struct NestedForTemplate<'a> {
    seqs: Vec<&'a [&'a str]>,
}

#[test]
fn test_nested_for() {
    let alpha = vec!["a", "b", "c"];
    let numbers = vec!["one", "two"];
    let s = NestedForTemplate {
        seqs: vec![&alpha, &numbers],
    };
    assert_eq!(s.render().unwrap(), "1\n  0a1b2c2\n  0one1two");
}

#[derive(Template)]
#[template(path = "precedence-for.html")]
struct PrecedenceTemplate<'a> {
    strings: Vec<&'a str>,
}

#[test]
fn test_precedence_for() {
    let s = PrecedenceTemplate {
        strings: vec!["A", "alfa", "1"],
    };
    assert_eq!(
        s.render().unwrap(),
        "0. A2 (first)\n1. alfa4\n2. 16 (last)\n"
    );
}

#[derive(Template)]
#[template(path = "for-range.html")]
struct ForRangeTemplate {
    init: i32,
    end: i32,
}

#[test]
fn test_for_range() {
    let s = ForRangeTemplate { init: -1, end: 1 };
    assert_eq!(
        s.render().unwrap(),
        "foo (first)\nfoo (last)\nbar\nbar\nfoo\nbar\nbar\n"
    );
}

#[derive(Template)]
#[template(source = "{% for i in [1, 2, 3] %}{{ i }}{% endfor %}", ext = "txt")]
struct ForArrayTemplate {}

#[test]
fn test_for_array() {
    let t = ForArrayTemplate {};
    assert_eq!(t.render().unwrap(), "123");
}

#[derive(Template)]
#[template(
    source = "{% for i in [1, 2, 3].iter() %}{{ i }}{% endfor %}",
    ext = "txt"
)]
struct ForMethodCallTemplate {}

#[test]
fn test_for_method_call() {
    let t = ForMethodCallTemplate {};
    assert_eq!(t.render().unwrap(), "123");
}

#[derive(Template)]
#[template(
    source = "{% for i in ::std::iter::repeat(\"a\").take(5) %}{{ i }}{% endfor %}",
    ext = "txt"
)]
struct ForPathCallTemplate;

#[test]
fn test_for_path_call() {
    assert_eq!(ForPathCallTemplate.render().unwrap(), "aaaaa");
}

#[derive(Template)]
#[template(
    source = "{% for i in [1, 2, 3, 4, 5][3..] %}{{ i }}{% endfor %}",
    ext = "txt"
)]
struct ForIndexTemplate {}

#[test]
fn test_for_index() {
    let t = ForIndexTemplate {};
    assert_eq!(t.render().unwrap(), "45");
}
<commit_msg>Added range test case<commit_after>use askama::Template;

#[derive(Template)]
#[template(path = "for.html")]
struct ForTemplate<'a> {
    strings: Vec<&'a str>,
    tuple_strings: Vec<(&'a str, &'a str)>,
}

#[test]
fn test_for() {
    let s = ForTemplate {
        strings: vec!["A", "alfa", "1"],
        tuple_strings: vec![("B", "beta")],
    };
    assert_eq!(
        s.render().unwrap(),
        "0. A (first)\n1. alfa\n2. 1\n\n0. B,beta (first)\n"
    );
}

#[derive(Template)]
#[template(path = "nested-for.html")]
struct NestedForTemplate<'a> {
    seqs: Vec<&'a [&'a str]>,
}

#[test]
fn test_nested_for() {
    let alpha = vec!["a", "b", "c"];
    let numbers = vec!["one", "two"];
    let s = NestedForTemplate {
        seqs: vec![&alpha, &numbers],
    };
    assert_eq!(s.render().unwrap(), "1\n  0a1b2c2\n  0one1two");
}

#[derive(Template)]
#[template(path = "precedence-for.html")]
struct PrecedenceTemplate<'a> {
    strings: Vec<&'a str>,
}

#[test]
fn test_precedence_for() {
    let s = PrecedenceTemplate {
        strings: vec!["A", "alfa", "1"],
    };
    assert_eq!(
        s.render().unwrap(),
        "0. A2 (first)\n1. alfa4\n2. 16 (last)\n"
    );
}

#[derive(Template)]
#[template(path = "for-range.html")]
struct ForRangeTemplate {
    init: i32,
    end: i32,
}

#[test]
fn test_for_range() {
    let s = ForRangeTemplate { init: -1, end: 1 };
    assert_eq!(
        s.render().unwrap(),
        "foo (first)\nfoo (last)\nbar\nbar\nfoo\nbar\nbar\n"
    );
}

#[derive(Template)]
#[template(source = "{% for i in [1, 2, 3] %}{{ i }}{% endfor %}", ext = "txt")]
struct ForArrayTemplate;

#[test]
fn test_for_array() {
    let t = ForArrayTemplate;
    assert_eq!(t.render().unwrap(), "123");
}

#[derive(Template)]
#[template(
    source = "{% for i in [1, 2, 3].iter() %}{{ i }}{% endfor %}",
    ext = "txt"
)]
struct ForMethodCallTemplate;

#[test]
fn test_for_method_call() {
    let t = ForMethodCallTemplate;
    assert_eq!(t.render().unwrap(), "123");
}

#[derive(Template)]
#[template(
    source = "{% for i in ::std::iter::repeat(\"a\").take(5) %}{{ i }}{% endfor %}",
    ext = "txt"
)]
struct ForPathCallTemplate;

#[test]
fn test_for_path_call() {
    assert_eq!(ForPathCallTemplate.render().unwrap(), "aaaaa");
}

#[derive(Template)]
#[template(
    source = "{% for i in [1, 2, 3, 4, 5][3..] %}{{ i }}{% endfor %}",
    ext = "txt"
)]
struct ForIndexTemplate;

#[test]
fn test_for_index() {
    let t = ForIndexTemplate;
    assert_eq!(t.render().unwrap(), "45");
}

#[derive(Template)]
#[template(
    source = "{% for (i, j) in (0..10).zip(10..20).zip(30..40) %}{{ i.0 }} {{ i.1 }} {{ j }} {% endfor %}",
    ext = "txt"
)]
struct ForZipRangesTemplate;

#[test]
fn test_for_zip_ranges() {
    let t = ForZipRangesTemplate;
    assert_eq!(
        t.render().unwrap(),
        "0 10 30 1 11 31 2 12 32 3 13 33 4 14 34 5 15 35 6 16 36 7 17 37 8 18 38 9 19 39 "
    );
}
<|endoftext|>


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

//! Periodically check membership rumors to automatically "time out"
//! `Suspect` rumors to `Confirmed`, and `Confirmed` rumors to
//! `Departed`.

use std::thread;
use std::time::Duration;

use rumor::{RumorKey, RumorType};
use server::timing::Timing;
use server::Server;

const LOOP_PERIOD_MS: u64 = 500;

pub struct Expire {
    pub server: Server,
    pub timing: Timing,
}

impl Expire {
    pub fn new(server: Server, timing: Timing) -> Expire {
        Expire {
            server: server,
            timing: timing,
        }
    }

    pub fn run(&self) {
        loop {
            let newly_confirmed_members = self
                .server
                .member_list
                .members_expired_to_confirmed(self.timing.suspicion_timeout_duration());

            for id in newly_confirmed_members {
                self.server
                    .rumor_heat
                    .start_hot_rumor(RumorKey::new(RumorType::Member, id, ""));
            }

            let newly_departed_members = self
                .server
                .member_list
                .members_expired_to_departed(self.timing.departure_timeout_duration());

            for id in newly_departed_members {
                self.server
                    .rumor_heat
                    .start_hot_rumor(RumorKey::new(RumorType::Member, id, ""));
            }

            thread::sleep(Duration::from_millis(LOOP_PERIOD_MS));
        }
    }
}
<commit_msg>[PR REVIEW]: LOOP_PERIOD_MS => LOOP_DELAY_MS<commit_after>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Periodically check membership rumors to automatically "time out"
//! `Suspect` rumors to `Confirmed`, and `Confirmed` rumors to
//! `Departed`.

use std::thread;
use std::time::Duration;

use rumor::{RumorKey, RumorType};
use server::timing::Timing;
use server::Server;

const LOOP_DELAY_MS: u64 = 500;

pub struct Expire {
    pub server: Server,
    pub timing: Timing,
}

impl Expire {
    pub fn new(server: Server, timing: Timing) -> Expire {
        Expire {
            server: server,
            timing: timing,
        }
    }

    pub fn run(&self) {
        loop {
            let newly_confirmed_members = self
                .server
                .member_list
                .members_expired_to_confirmed(self.timing.suspicion_timeout_duration());

            for id in newly_confirmed_members {
                self.server
                    .rumor_heat
                    .start_hot_rumor(RumorKey::new(RumorType::Member, id, ""));
            }

            let newly_departed_members = self
                .server
                .member_list
                .members_expired_to_departed(self.timing.departure_timeout_duration());

            for id in newly_departed_members {
                self.server
                    .rumor_heat
                    .start_hot_rumor(RumorKey::new(RumorType::Member, id, ""));
            }

            thread::sleep(Duration::from_millis(LOOP_DELAY_MS));
        }
    }
}
<|endoftext|>