<commit_before>use std::any::Any;
use std::error::Error;
use std::fmt;
use std::mem;

use runtime::{Class, Imp, Object, Sel, Super};

mod verify;

#[cfg(target_arch = "x86")]
#[path = "x86.rs"]
mod platform;
#[cfg(target_arch = "x86_64")]
#[path = "x86_64.rs"]
mod platform;
#[cfg(target_arch = "arm")]
#[path = "arm.rs"]
mod platform;
#[cfg(all(target_arch = "aarch64", not(feature = "gnustep")))]
#[path = "arm64.rs"]
mod platform;

#[cfg(feature= "gnustep")]
mod gnustep;

#[cfg(not(feature = "gnustep"))]
use self::platform::{msg_send_fn, msg_send_super_fn};
#[cfg(feature = "gnustep")]
use self::gnustep::{msg_send_fn, msg_send_super_fn};

/// Types that may be sent Objective-C messages.
/// For example: objects, classes, and blocks.
pub unsafe trait Message {
    #[cfg(not(feature = "verify_message"))]
    unsafe fn send_message<A, R>(&self, sel: Sel, args: A)
            -> Result<R, MessageError>
            where Self: Sized, A: MessageArguments, R: Any {
        send_message(self, sel, args)
    }

    #[cfg(feature = "verify_message")]
    unsafe fn send_message<A, R>(&self, sel: Sel, args: A)
            -> Result<R, MessageError>
            where Self: Sized, A: MessageArguments + ::EncodeArguments,
            R: Any + ::Encode {
        send_message(self, sel, args)
    }
}

unsafe impl Message for Object { }

unsafe impl Message for Class { }

/// Types that may be used as the arguments of an Objective-C message.
pub trait MessageArguments: Sized {
    unsafe fn invoke<R>(imp: Imp, obj: *mut Object, sel: Sel, args: Self) -> R
            where R: Any;

    /// Sends a message to the given obj with the given selector and self as
    /// the arguments.
    ///
    /// The correct version of `objc_msgSend` will be chosen based on the
    /// return type. For more information, see Apple's documenation:
    /// https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html#//apple_ref/doc/uid/TP40001418-CH1g-88778
    ///
    /// It is recommended to use the `msg_send!` macro rather than calling this
    /// method directly.
    unsafe fn send<T, R>(self, obj: *mut T, sel: Sel) -> R
            where T: Message, R: Any {
        send_unverified(obj, sel, self).unwrap()
    }

    /// Sends a message to the superclass of an instance of a class with self
    /// as the arguments.
    unsafe fn send_super<T, R>(self, obj: *mut T, superclass: &Class, sel: Sel) -> R
            where T: Message, R: Any {
        send_super_unverified(obj, superclass, sel, self).unwrap()
    }
}

macro_rules! message_args_impl {
    ($($a:ident : $t:ident),*) => (
        impl<$($t),*> MessageArguments for ($($t,)*) {
            unsafe fn invoke<R>(imp: Imp, obj: *mut Object, sel: Sel, ($($a,)*): Self) -> R
                    where R: Any {
                let imp: unsafe extern fn(*mut Object, Sel $(, $t)*) -> R =
                    mem::transmute(imp);
                imp(obj, sel $(, $a)*)
            }
        }
    );
}

message_args_impl!();
message_args_impl!(a: A);
message_args_impl!(a: A, b: B);
message_args_impl!(a: A, b: B, c: C);
message_args_impl!(a: A, b: B, c: C, d: D);
message_args_impl!(a: A, b: B, c: C, d: D, e: E);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);

#[derive(Debug)]
pub struct MessageError(String);

impl fmt::Display for MessageError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

impl Error for MessageError {
    fn description(&self) -> &str {
        &self.0
    }
}

#[cfg(feature = "exception")]
macro_rules! objc_try {
    ($b:block) => (
        $crate::exception::try(|| $b).map_err(|exception| match exception {
            Some(exception) => MessageError(format!("Uncaught exception {:?}", &*exception)),
            None => MessageError("Uncaught exception nil".to_owned()),
        })
    )
}

#[cfg(not(feature = "exception"))]
macro_rules! objc_try {
    ($b:block) => (Ok($b))
}

unsafe fn send_unverified<T, A, R>(obj: *const T, sel: Sel, args: A)
        -> Result<R, MessageError>
        where T: Message, A: MessageArguments, R: Any {
    let (msg_send_fn, receiver) = msg_send_fn::<R>(obj as *mut T as *mut Object, sel);
    objc_try!({
        A::invoke(msg_send_fn, receiver, sel, args)
    })
}

#[doc(hidden)]
#[inline(always)]
#[cfg(not(feature = "verify_message"))]
pub unsafe fn send_message<T, A, R>(obj: *const T, sel: Sel, args: A)
        -> Result<R, MessageError>
        where T: Message, A: MessageArguments, R: Any {
    send_unverified(obj, sel, args)
}

#[doc(hidden)]
#[inline(always)]
#[cfg(feature = "verify_message")]
pub unsafe fn send_message<T, A, R>(obj: *const T, sel: Sel, args: A)
        -> Result<R, MessageError>
        where T: Message, A: MessageArguments + ::EncodeArguments,
        R: Any + ::Encode {
    use self::verify::verify_message_signature;

    let cls = if obj.is_null() {
        return Err(MessageError(format!("Messaging {:?} to nil", sel)));
    } else {
        (*(obj as *const Object)).class()
    };

    verify_message_signature::<A, R>(cls, sel).and_then(|_| {
        send_unverified(obj, sel, args)
    })
}

unsafe fn send_super_unverified<T, A, R>(obj: *const T, superclass: &Class,
        sel: Sel, args: A) -> Result<R, MessageError>
        where T: Message, A: MessageArguments, R: Any {
    let sup = Super { receiver: obj as *mut T as *mut Object, superclass: superclass };
    let (msg_send_fn, receiver) = msg_send_super_fn::<R>(&sup, sel);
    objc_try!({
        A::invoke(msg_send_fn, receiver, sel, args)
    })
}

#[doc(hidden)]
#[inline(always)]
#[cfg(not(feature = "verify_message"))]
pub unsafe fn send_super_message<T, A, R>(obj: *const T, superclass: &Class,
        sel: Sel, args: A) -> Result<R, MessageError>
        where T: Message, A: MessageArguments, R: Any {
    send_super_unverified(obj, superclass, sel, args)
}

#[doc(hidden)]
#[inline(always)]
#[cfg(feature = "verify_message")]
pub unsafe fn send_super_message<T, A, R>(obj: *const T, superclass: &Class,
        sel: Sel, args: A) -> Result<R, MessageError>
        where T: Message, A: MessageArguments + ::EncodeArguments,
        R: Any + ::Encode {
    use self::verify::verify_message_signature;

    if obj.is_null() {
        return Err(MessageError(format!("Messaging {:?} to nil", sel)));
    }

    verify_message_signature::<A, R>(superclass, sel).and_then(|_| {
        send_super_unverified(obj, superclass, sel, args)
    })
}

#[cfg(test)]
mod tests {
    use runtime::Object;
    use test_utils;

    #[test]
    fn test_send_message() {
        let obj = test_utils::custom_object();
        let result: u32 = unsafe {
            let _: () = msg_send![obj, setFoo:4u32];
            msg_send![obj, foo]
        };
        assert!(result == 4);
    }

    #[test]
    fn test_send_message_stret() {
        let obj = test_utils::custom_object();
        let result: test_utils::CustomStruct = unsafe {
            msg_send![obj, customStruct]
        };
        let expected = test_utils::CustomStruct { a: 1, b:2, c: 3, d: 4 };
        assert!(result == expected);
    }

    #[test]
    fn test_send_message_nil() {
        let nil: *mut Object = ::std::ptr::null_mut();
        let result: usize = unsafe {
            msg_send![nil, hash]
        };
        assert!(result == 0);

        let result: *mut Object = unsafe {
            msg_send![nil, description]
        };
        assert!(result.is_null());

        let result: f64 = unsafe {
            msg_send![nil, doubleValue]
        };
        assert!(result == 0.0);
    }

    #[test]
    fn test_send_message_super() {
        let obj = test_utils::custom_subclass_object();
        let superclass = test_utils::custom_class();
        unsafe {
            let _: () = msg_send![obj, setFoo:4u32];
            let foo: u32 = msg_send![super(obj, superclass), foo];
            assert!(foo == 4);

            // The subclass is overriden to return foo + 2
            let foo: u32 = msg_send![obj, foo];
            assert!(foo == 6);
        }
    }
}
<commit_msg>Removed MessageArguments send and send_verified methods.<commit_after>use std::any::Any;
use std::error::Error;
use std::fmt;
use std::mem;

use runtime::{Class, Imp, Object, Sel, Super};

mod verify;

#[cfg(target_arch = "x86")]
#[path = "x86.rs"]
mod platform;
#[cfg(target_arch = "x86_64")]
#[path = "x86_64.rs"]
mod platform;
#[cfg(target_arch = "arm")]
#[path = "arm.rs"]
mod platform;
#[cfg(all(target_arch = "aarch64", not(feature = "gnustep")))]
#[path = "arm64.rs"]
mod platform;

#[cfg(feature= "gnustep")]
mod gnustep;

#[cfg(not(feature = "gnustep"))]
use self::platform::{msg_send_fn, msg_send_super_fn};
#[cfg(feature = "gnustep")]
use self::gnustep::{msg_send_fn, msg_send_super_fn};

/// Types that may be sent Objective-C messages.
/// For example: objects, classes, and blocks.
pub unsafe trait Message {
    #[cfg(not(feature = "verify_message"))]
    unsafe fn send_message<A, R>(&self, sel: Sel, args: A)
            -> Result<R, MessageError>
            where Self: Sized, A: MessageArguments, R: Any {
        send_message(self, sel, args)
    }

    #[cfg(feature = "verify_message")]
    unsafe fn send_message<A, R>(&self, sel: Sel, args: A)
            -> Result<R, MessageError>
            where Self: Sized, A: MessageArguments + ::EncodeArguments,
            R: Any + ::Encode {
        send_message(self, sel, args)
    }
}

unsafe impl Message for Object { }

unsafe impl Message for Class { }

/// Types that may be used as the arguments of an Objective-C message.
pub trait MessageArguments: Sized {
    unsafe fn invoke<R>(imp: Imp, obj: *mut Object, sel: Sel, args: Self) -> R
            where R: Any;
}

macro_rules! message_args_impl {
    ($($a:ident : $t:ident),*) => (
        impl<$($t),*> MessageArguments for ($($t,)*) {
            unsafe fn invoke<R>(imp: Imp, obj: *mut Object, sel: Sel, ($($a,)*): Self) -> R
                    where R: Any {
                let imp: unsafe extern fn(*mut Object, Sel $(, $t)*) -> R =
                    mem::transmute(imp);
                imp(obj, sel $(, $a)*)
            }
        }
    );
}

message_args_impl!();
message_args_impl!(a: A);
message_args_impl!(a: A, b: B);
message_args_impl!(a: A, b: B, c: C);
message_args_impl!(a: A, b: B, c: C, d: D);
message_args_impl!(a: A, b: B, c: C, d: D, e: E);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);

#[derive(Debug)]
pub struct MessageError(String);

impl fmt::Display for MessageError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

impl Error for MessageError {
    fn description(&self) -> &str {
        &self.0
    }
}

#[cfg(feature = "exception")]
macro_rules! objc_try {
    ($b:block) => (
        $crate::exception::try(|| $b).map_err(|exception| match exception {
            Some(exception) => MessageError(format!("Uncaught exception {:?}", &*exception)),
            None => MessageError("Uncaught exception nil".to_owned()),
        })
    )
}

#[cfg(not(feature = "exception"))]
macro_rules! objc_try {
    ($b:block) => (Ok($b))
}

unsafe fn send_unverified<T, A, R>(obj: *const T, sel: Sel, args: A)
        -> Result<R, MessageError>
        where T: Message, A: MessageArguments, R: Any {
    let (msg_send_fn, receiver) = msg_send_fn::<R>(obj as *mut T as *mut Object, sel);
    objc_try!({
        A::invoke(msg_send_fn, receiver, sel, args)
    })
}

#[doc(hidden)]
#[inline(always)]
#[cfg(not(feature = "verify_message"))]
pub unsafe fn send_message<T, A, R>(obj: *const T, sel: Sel, args: A)
        -> Result<R, MessageError>
        where T: Message, A: MessageArguments, R: Any {
    send_unverified(obj, sel, args)
}

#[doc(hidden)]
#[inline(always)]
#[cfg(feature = "verify_message")]
pub unsafe fn send_message<T, A, R>(obj: *const T, sel: Sel, args: A)
        -> Result<R, MessageError>
        where T: Message, A: MessageArguments + ::EncodeArguments,
        R: Any + ::Encode {
    use self::verify::verify_message_signature;

    let cls = if obj.is_null() {
        return Err(MessageError(format!("Messaging {:?} to nil", sel)));
    } else {
        (*(obj as *const Object)).class()
    };

    verify_message_signature::<A, R>(cls, sel).and_then(|_| {
        send_unverified(obj, sel, args)
    })
}

unsafe fn send_super_unverified<T, A, R>(obj: *const T, superclass: &Class,
        sel: Sel, args: A) -> Result<R, MessageError>
        where T: Message, A: MessageArguments, R: Any {
    let sup = Super { receiver: obj as *mut T as *mut Object, superclass: superclass };
    let (msg_send_fn, receiver) = msg_send_super_fn::<R>(&sup, sel);
    objc_try!({
        A::invoke(msg_send_fn, receiver, sel, args)
    })
}

#[doc(hidden)]
#[inline(always)]
#[cfg(not(feature = "verify_message"))]
pub unsafe fn send_super_message<T, A, R>(obj: *const T, superclass: &Class,
        sel: Sel, args: A) -> Result<R, MessageError>
        where T: Message, A: MessageArguments, R: Any {
    send_super_unverified(obj, superclass, sel, args)
}

#[doc(hidden)]
#[inline(always)]
#[cfg(feature = "verify_message")]
pub unsafe fn send_super_message<T, A, R>(obj: *const T, superclass: &Class,
        sel: Sel, args: A) -> Result<R, MessageError>
        where T: Message, A: MessageArguments + ::EncodeArguments,
        R: Any + ::Encode {
    use self::verify::verify_message_signature;

    if obj.is_null() {
        return Err(MessageError(format!("Messaging {:?} to nil", sel)));
    }

    verify_message_signature::<A, R>(superclass, sel).and_then(|_| {
        send_super_unverified(obj, superclass, sel, args)
    })
}

#[cfg(test)]
mod tests {
    use runtime::Object;
    use test_utils;

    #[test]
    fn test_send_message() {
        let obj = test_utils::custom_object();
        let result: u32 = unsafe {
            let _: () = msg_send![obj, setFoo:4u32];
            msg_send![obj, foo]
        };
        assert!(result == 4);
    }

    #[test]
    fn test_send_message_stret() {
        let obj = test_utils::custom_object();
        let result: test_utils::CustomStruct = unsafe {
            msg_send![obj, customStruct]
        };
        let expected = test_utils::CustomStruct { a: 1, b:2, c: 3, d: 4 };
        assert!(result == expected);
    }

    #[test]
    fn test_send_message_nil() {
        let nil: *mut Object = ::std::ptr::null_mut();
        let result: usize = unsafe {
            msg_send![nil, hash]
        };
        assert!(result == 0);

        let result: *mut Object = unsafe {
            msg_send![nil, description]
        };
        assert!(result.is_null());

        let result: f64 = unsafe {
            msg_send![nil, doubleValue]
        };
        assert!(result == 0.0);
    }

    #[test]
    fn test_send_message_super() {
        let obj = test_utils::custom_subclass_object();
        let superclass = test_utils::custom_class();
        unsafe {
            let _: () = msg_send![obj, setFoo:4u32];
            let foo: u32 = msg_send![super(obj, superclass), foo];
            assert!(foo == 4);

            // The subclass is overriden to return foo + 2
            let foo: u32 = msg_send![obj, foo];
            assert!(foo == 6);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2016 Robert Clipsham <robert@octarineparrot.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.

//! Support for sending and receiving data link layer packets using Linux's `AF_PACKET`.

extern crate libc;

use bindings::linux;
use {DataLinkReceiver, DataLinkSender, MacAddr, NetworkInterface};

use pnet_sys;

use std::cmp;
use std::io;
use std::mem;
use std::ptr;
use std::sync::Arc;
use std::time::Duration;

fn network_addr_to_sockaddr(
    ni: &NetworkInterface,
    storage: *mut libc::sockaddr_storage,
    proto: libc::c_int,
) -> usize {
    unsafe {
        let sll: *mut libc::sockaddr_ll = mem::transmute(storage);
        (*sll).sll_family = libc::AF_PACKET as libc::sa_family_t;
        if let Some(MacAddr(a, b, c, d, e, f)) = ni.mac {
            (*sll).sll_addr = [a, b, c, d, e, f, 0, 0];
        }
        (*sll).sll_protocol = (proto as u16).to_be();
        (*sll).sll_halen = 6;
        (*sll).sll_ifindex = ni.index as i32;
        mem::size_of::<libc::sockaddr_ll>()
    }
}

/// Configuration for the Linux datalink backend.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Config {
    /// The size of buffer to use when writing packets. Defaults to 4096.
    pub write_buffer_size: usize,

    /// The size of buffer to use when reading packets. Defaults to 4096.
    pub read_buffer_size: usize,

    /// The read timeout. Defaults to None.
    pub read_timeout: Option<Duration>,

    /// The write timeout. Defaults to None.
    pub write_timeout: Option<Duration>,

    /// Specifies whether to read packets at the datalink layer or network layer.
    /// NOTE FIXME Currently ignored.
    /// Defaults to Layer2.
    pub channel_type: super::ChannelType,

    /// Specifies packet fanout option, if desired. Defaults to None.
    pub fanout: Option<super::FanoutOption>,

    /// Promiscuous mode.
    pub promiscuous: bool,
}

impl<'a> From<&'a super::Config> for Config {
    fn from(config: &super::Config) -> Config {
        Config {
            write_buffer_size: config.write_buffer_size,
            read_buffer_size: config.read_buffer_size,
            channel_type: config.channel_type,
            read_timeout: config.read_timeout,
            write_timeout: config.write_timeout,
            fanout: config.linux_fanout,
            promiscuous: config.promiscuous,
        }
    }
}

impl Default for Config {
    fn default() -> Config {
        Config {
            write_buffer_size: 4096,
            read_buffer_size: 4096,
            read_timeout: None,
            write_timeout: None,
            channel_type: super::ChannelType::Layer2,
            fanout: None,
            promiscuous: true,
        }
    }
}

/// Create a data link channel using the Linux's `AF_PACKET` socket type.
#[inline]
pub fn channel(network_interface: &NetworkInterface, config: Config) -> io::Result<super::Channel> {
    let eth_p_all = 0x0003;
    let (typ, proto) = match config.channel_type {
        super::ChannelType::Layer2 => (libc::SOCK_RAW, eth_p_all),
        super::ChannelType::Layer3(proto) => (libc::SOCK_DGRAM, proto),
    };
    let socket = unsafe { libc::socket(libc::AF_PACKET, typ, proto.to_be() as i32) };
    if socket == -1 {
        return Err(io::Error::last_os_error());
    }
    let mut addr: libc::sockaddr_storage = unsafe { mem::zeroed() };
    let len = network_addr_to_sockaddr(network_interface, &mut addr, proto as i32);

    let send_addr = (&addr as *const libc::sockaddr_storage) as *const libc::sockaddr;

    // Bind to interface
    if unsafe { libc::bind(socket, send_addr, len as libc::socklen_t) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            pnet_sys::close(socket);
        }
        return Err(err);
    }

    let mut pmr: linux::packet_mreq = unsafe { mem::zeroed() };
    pmr.mr_ifindex = network_interface.index as i32;
    pmr.mr_type = linux::PACKET_MR_PROMISC as u16;

    // Enable promiscuous capture
    if config.promiscuous {
        if unsafe {
            libc::setsockopt(
                socket,
                linux::SOL_PACKET,
                linux::PACKET_ADD_MEMBERSHIP,
                (&pmr as *const linux::packet_mreq) as *const libc::c_void,
                mem::size_of::<linux::packet_mreq>() as libc::socklen_t,
            )
        } == -1
        {
            let err = io::Error::last_os_error();
            unsafe {
                pnet_sys::close(socket);
            }
            return Err(err);
        }
    }

    // Enable packet fanout
    if let Some(fanout) = config.fanout {
        use super::FanoutType;
        let mut typ = match fanout.fanout_type {
            FanoutType::HASH => linux::PACKET_FANOUT_HASH,
            FanoutType::LB => linux::PACKET_FANOUT_LB,
            FanoutType::CPU => linux::PACKET_FANOUT_CPU,
            FanoutType::ROLLOVER => linux::PACKET_FANOUT_ROLLOVER,
            FanoutType::RND => linux::PACKET_FANOUT_RND,
            FanoutType::QM => linux::PACKET_FANOUT_QM,
            FanoutType::CBPF => linux::PACKET_FANOUT_CBPF,
            FanoutType::EBPF => linux::PACKET_FANOUT_EBPF,
        } as u32;
        // set defrag flag
        if fanout.defrag {
            typ = typ | linux::PACKET_FANOUT_FLAG_DEFRAG;
        }
        // set rollover flag
        if fanout.rollover {
            typ = typ | linux::PACKET_FANOUT_FLAG_ROLLOVER;
        }
        // set uniqueid flag -- probably not needed atm..
        // PACKET_FANOUT_FLAG_UNIQUEID -- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4a69a864209e9ab436d4a58e8028ac96cc873d15
        let arg: libc::c_uint = fanout.group_id as u32 | (typ << 16);

        if unsafe {
            libc::setsockopt(
                socket,
                linux::SOL_PACKET,
                linux::PACKET_FANOUT,
                (&arg as *const libc::c_uint) as *const libc::c_void,
                mem::size_of::<libc::c_uint>() as libc::socklen_t,
            )
        } == -1
        {
            let err = io::Error::last_os_error();
            unsafe {
                pnet_sys::close(socket);
            }
            return Err(err);
        }
    }

    // Enable nonblocking
    if unsafe { libc::fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            pnet_sys::close(socket);
        }
        return Err(err);
    }

    let fd = Arc::new(pnet_sys::FileDesc { fd: socket });
    let sender = Box::new(DataLinkSenderImpl {
        socket: fd.clone(),
        fd_set: unsafe { mem::zeroed() },
        write_buffer: vec![0; config.write_buffer_size],
        _channel_type: config.channel_type,
        send_addr: unsafe { *(send_addr as *const libc::sockaddr_ll) },
        send_addr_len: len,
        timeout: config
            .write_timeout
            .map(|to| pnet_sys::duration_to_timespec(to)),
    });
    let receiver = Box::new(DataLinkReceiverImpl {
        socket: fd.clone(),
        fd_set: unsafe { mem::zeroed() },
        read_buffer: vec![0; config.read_buffer_size],
        _channel_type: config.channel_type,
        timeout: config
            .read_timeout
            .map(|to| pnet_sys::duration_to_timespec(to)),
    });

    Ok(super::Channel::Ethernet(sender, receiver))
}

struct DataLinkSenderImpl {
    socket: Arc<pnet_sys::FileDesc>,
    fd_set: libc::fd_set,
    write_buffer: Vec<u8>,
    _channel_type: super::ChannelType,
    send_addr: libc::sockaddr_ll,
    send_addr_len: usize,
    timeout: Option<libc::timespec>,
}

impl DataLinkSender for DataLinkSenderImpl {
    // FIXME Layer 3
    #[inline]
    fn build_and_send(
        &mut self,
        num_packets: usize,
        packet_size: usize,
        func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>> {
        let len = num_packets * packet_size;
        if len < self.write_buffer.len() {
            let min = cmp::min(self.write_buffer[..].len(), len);
            let mut_slice = &mut self.write_buffer;
            for chunk in mut_slice[..min].chunks_mut(packet_size) {
                func(chunk);
                let send_addr =
                    (&self.send_addr as *const libc::sockaddr_ll) as *const libc::sockaddr;

                unsafe {
                    libc::FD_ZERO(&mut self.fd_set as *mut libc::fd_set);
                    libc::FD_SET(self.socket.fd, &mut self.fd_set as *mut libc::fd_set);
                }
                let ret = unsafe {
                    libc::pselect(
                        self.socket.fd + 1,
                        ptr::null_mut(),
                        &mut self.fd_set as *mut libc::fd_set,
                        ptr::null_mut(),
                        self.timeout
                            .as_ref()
                            .map(|to| to as *const libc::timespec)
                            .unwrap_or(ptr::null()),
                        ptr::null(),
                    )
                };
                if ret == -1 {
                    return Some(Err(io::Error::last_os_error()));
                } else if ret == 0 {
                    return Some(Err(io::Error::new(io::ErrorKind::TimedOut, "Timed out")));
                } else {
                    if let Err(e) = pnet_sys::send_to(
                        self.socket.fd,
                        chunk,
                        send_addr,
                        self.send_addr_len as libc::socklen_t,
                    ) {
                        return Some(Err(e));
                    }
                }
            }

            Some(Ok(()))
        } else {
            None
        }
    }

    #[inline]
    fn send_to(&mut self, packet: &[u8], _dst: Option<NetworkInterface>) -> Option<io::Result<()>> {
        unsafe {
            libc::FD_ZERO(&mut self.fd_set as *mut libc::fd_set);
            libc::FD_SET(self.socket.fd, &mut self.fd_set as *mut libc::fd_set);
        }
        let ret = unsafe {
            libc::pselect(
                self.socket.fd + 1,
                ptr::null_mut(),
                &mut self.fd_set as *mut libc::fd_set,
                ptr::null_mut(),
                self.timeout
                    .as_ref()
                    .map(|to| to as *const libc::timespec)
                    .unwrap_or(ptr::null()),
                ptr::null(),
            )
        };
        if ret == -1 {
            Some(Err(io::Error::last_os_error()))
        } else if ret == 0 {
            Some(Err(io::Error::new(io::ErrorKind::TimedOut, "Timed out")))
        } else {
            match pnet_sys::send_to(
                self.socket.fd,
                packet,
                (&self.send_addr as *const libc::sockaddr_ll) as *const _,
                self.send_addr_len as libc::socklen_t,
            ) {
                Err(e) => Some(Err(e)),
                Ok(_) => Some(Ok(())),
            }
        }
    }
}

struct DataLinkReceiverImpl {
    socket: Arc<pnet_sys::FileDesc>,
    fd_set: libc::fd_set,
    read_buffer: Vec<u8>,
    _channel_type: super::ChannelType,
    timeout: Option<libc::timespec>,
}

impl DataLinkReceiver for DataLinkReceiverImpl {
    fn next(&mut self) -> io::Result<&[u8]> {
        let mut caddr: libc::sockaddr_storage = unsafe { mem::zeroed() };
        unsafe {
            libc::FD_ZERO(&mut self.fd_set as *mut libc::fd_set);
            libc::FD_SET(self.socket.fd, &mut self.fd_set as *mut libc::fd_set);
        }
        let ret = unsafe {
            libc::pselect(
                self.socket.fd + 1,
                &mut self.fd_set as *mut libc::fd_set,
                ptr::null_mut(),
                ptr::null_mut(),
                self.timeout
                    .as_ref()
                    .map(|to| to as *const libc::timespec)
                    .unwrap_or(ptr::null()),
                ptr::null(),
            )
        };
        if ret == -1 {
            Err(io::Error::last_os_error())
        } else if ret == 0 {
            Err(io::Error::new(io::ErrorKind::TimedOut, "Timed out"))
        } else {
            let res = pnet_sys::recv_from(self.socket.fd, &mut self.read_buffer, &mut caddr);
            match res {
                Ok(len) => Ok(&self.read_buffer[0..len]),
                Err(e) => Err(e),
            }
        }
    }
}

/// Get a list of available network interfaces for the current machine.
pub fn interfaces() -> Vec<NetworkInterface> {
    #[path = "unix_interfaces.rs"]
    mod interfaces;
    interfaces::interfaces()
}
<commit_msg>Fix length check in datalink's build_and_send() (#515)<commit_after>// Copyright (c) 2014-2016 Robert Clipsham <robert@octarineparrot.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.

//! Support for sending and receiving data link layer packets using Linux's `AF_PACKET`.

extern crate libc;

use bindings::linux;
use {DataLinkReceiver, DataLinkSender, MacAddr, NetworkInterface};

use pnet_sys;

use std::cmp;
use std::io;
use std::mem;
use std::ptr;
use std::sync::Arc;
use std::time::Duration;

fn network_addr_to_sockaddr(
    ni: &NetworkInterface,
    storage: *mut libc::sockaddr_storage,
    proto: libc::c_int,
) -> usize {
    unsafe {
        let sll: *mut libc::sockaddr_ll = mem::transmute(storage);
        (*sll).sll_family = libc::AF_PACKET as libc::sa_family_t;
        if let Some(MacAddr(a, b, c, d, e, f)) = ni.mac {
            (*sll).sll_addr = [a, b, c, d, e, f, 0, 0];
        }
        (*sll).sll_protocol = (proto as u16).to_be();
        (*sll).sll_halen = 6;
        (*sll).sll_ifindex = ni.index as i32;
        mem::size_of::<libc::sockaddr_ll>()
    }
}

/// Configuration for the Linux datalink backend.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Config {
    /// The size of buffer to use when writing packets. Defaults to 4096.
    pub write_buffer_size: usize,

    /// The size of buffer to use when reading packets. Defaults to 4096.
    pub read_buffer_size: usize,

    /// The read timeout. Defaults to None.
    pub read_timeout: Option<Duration>,

    /// The write timeout. Defaults to None.
    pub write_timeout: Option<Duration>,

    /// Specifies whether to read packets at the datalink layer or network layer.
    /// NOTE FIXME Currently ignored.
    /// Defaults to Layer2.
    pub channel_type: super::ChannelType,

    /// Specifies packet fanout option, if desired. Defaults to None.
    pub fanout: Option<super::FanoutOption>,

    /// Promiscuous mode.
    pub promiscuous: bool,
}

impl<'a> From<&'a super::Config> for Config {
    fn from(config: &super::Config) -> Config {
        Config {
            write_buffer_size: config.write_buffer_size,
            read_buffer_size: config.read_buffer_size,
            channel_type: config.channel_type,
            read_timeout: config.read_timeout,
            write_timeout: config.write_timeout,
            fanout: config.linux_fanout,
            promiscuous: config.promiscuous,
        }
    }
}

impl Default for Config {
    fn default() -> Config {
        Config {
            write_buffer_size: 4096,
            read_buffer_size: 4096,
            read_timeout: None,
            write_timeout: None,
            channel_type: super::ChannelType::Layer2,
            fanout: None,
            promiscuous: true,
        }
    }
}

/// Create a data link channel using the Linux's `AF_PACKET` socket type.
#[inline]
pub fn channel(network_interface: &NetworkInterface, config: Config) -> io::Result<super::Channel> {
    let eth_p_all = 0x0003;
    let (typ, proto) = match config.channel_type {
        super::ChannelType::Layer2 => (libc::SOCK_RAW, eth_p_all),
        super::ChannelType::Layer3(proto) => (libc::SOCK_DGRAM, proto),
    };
    let socket = unsafe { libc::socket(libc::AF_PACKET, typ, proto.to_be() as i32) };
    if socket == -1 {
        return Err(io::Error::last_os_error());
    }
    let mut addr: libc::sockaddr_storage = unsafe { mem::zeroed() };
    let len = network_addr_to_sockaddr(network_interface, &mut addr, proto as i32);

    let send_addr = (&addr as *const libc::sockaddr_storage) as *const libc::sockaddr;

    // Bind to interface
    if unsafe { libc::bind(socket, send_addr, len as libc::socklen_t) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            pnet_sys::close(socket);
        }
        return Err(err);
    }

    let mut pmr: linux::packet_mreq = unsafe { mem::zeroed() };
    pmr.mr_ifindex = network_interface.index as i32;
    pmr.mr_type = linux::PACKET_MR_PROMISC as u16;

    // Enable promiscuous capture
    if config.promiscuous {
        if unsafe {
            libc::setsockopt(
                socket,
                linux::SOL_PACKET,
                linux::PACKET_ADD_MEMBERSHIP,
                (&pmr as *const linux::packet_mreq) as *const libc::c_void,
                mem::size_of::<linux::packet_mreq>() as libc::socklen_t,
            )
        } == -1
        {
            let err = io::Error::last_os_error();
            unsafe {
                pnet_sys::close(socket);
            }
            return Err(err);
        }
    }

    // Enable packet fanout
    if let Some(fanout) = config.fanout {
        use super::FanoutType;
        let mut typ = match fanout.fanout_type {
            FanoutType::HASH => linux::PACKET_FANOUT_HASH,
            FanoutType::LB => linux::PACKET_FANOUT_LB,
            FanoutType::CPU => linux::PACKET_FANOUT_CPU,
            FanoutType::ROLLOVER => linux::PACKET_FANOUT_ROLLOVER,
            FanoutType::RND => linux::PACKET_FANOUT_RND,
            FanoutType::QM => linux::PACKET_FANOUT_QM,
            FanoutType::CBPF => linux::PACKET_FANOUT_CBPF,
            FanoutType::EBPF => linux::PACKET_FANOUT_EBPF,
        } as u32;
        // set defrag flag
        if fanout.defrag {
            typ = typ | linux::PACKET_FANOUT_FLAG_DEFRAG;
        }
        // set rollover flag
        if fanout.rollover {
            typ = typ | linux::PACKET_FANOUT_FLAG_ROLLOVER;
        }
        // set uniqueid flag -- probably not needed atm..
        // PACKET_FANOUT_FLAG_UNIQUEID -- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4a69a864209e9ab436d4a58e8028ac96cc873d15
        let arg: libc::c_uint = fanout.group_id as u32 | (typ << 16);

        if unsafe {
            libc::setsockopt(
                socket,
                linux::SOL_PACKET,
                linux::PACKET_FANOUT,
                (&arg as *const libc::c_uint) as *const libc::c_void,
                mem::size_of::<libc::c_uint>() as libc::socklen_t,
            )
        } == -1
        {
            let err = io::Error::last_os_error();
            unsafe {
                pnet_sys::close(socket);
            }
            return Err(err);
        }
    }

    // Enable nonblocking
    if unsafe { libc::fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            pnet_sys::close(socket);
        }
        return Err(err);
    }

    let fd = Arc::new(pnet_sys::FileDesc { fd: socket });
    let sender = Box::new(DataLinkSenderImpl {
        socket: fd.clone(),
        fd_set: unsafe { mem::zeroed() },
        write_buffer: vec![0; config.write_buffer_size],
        _channel_type: config.channel_type,
        send_addr: unsafe { *(send_addr as *const libc::sockaddr_ll) },
        send_addr_len: len,
        timeout: config
            .write_timeout
            .map(|to| pnet_sys::duration_to_timespec(to)),
    });
    let receiver = Box::new(DataLinkReceiverImpl {
        socket: fd.clone(),
        fd_set: unsafe { mem::zeroed() },
        read_buffer: vec![0; config.read_buffer_size],
        _channel_type: config.channel_type,
        timeout: config
            .read_timeout
            .map(|to| pnet_sys::duration_to_timespec(to)),
    });

    Ok(super::Channel::Ethernet(sender, receiver))
}

struct DataLinkSenderImpl {
    socket: Arc<pnet_sys::FileDesc>,
    fd_set: libc::fd_set,
    write_buffer: Vec<u8>,
    _channel_type: super::ChannelType,
    send_addr: libc::sockaddr_ll,
    send_addr_len: usize,
    timeout: Option<libc::timespec>,
}

impl DataLinkSender for DataLinkSenderImpl {
    // FIXME Layer 3
    #[inline]
    fn build_and_send(
        &mut self,
        num_packets: usize,
        packet_size: usize,
        func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>> {
        let len = num_packets * packet_size;
        if len <= self.write_buffer.len() {
            let min = cmp::min(self.write_buffer[..].len(), len);
            let mut_slice = &mut self.write_buffer;
            for chunk in mut_slice[..min].chunks_mut(packet_size) {
                func(chunk);
                let send_addr =
                    (&self.send_addr as *const libc::sockaddr_ll) as *const libc::sockaddr;

                unsafe {
                    libc::FD_ZERO(&mut self.fd_set as *mut libc::fd_set);
                    libc::FD_SET(self.socket.fd, &mut self.fd_set as *mut libc::fd_set);
                }
                let ret = unsafe {
                    libc::pselect(
                        self.socket.fd + 1,
                        ptr::null_mut(),
                        &mut self.fd_set as *mut libc::fd_set,
                        ptr::null_mut(),
                        self.timeout
                            .as_ref()
                            .map(|to| to as *const libc::timespec)
                            .unwrap_or(ptr::null()),
                        ptr::null(),
                    )
                };
                if ret == -1 {
                    return Some(Err(io::Error::last_os_error()));
                } else if ret == 0 {
                    return Some(Err(io::Error::new(io::ErrorKind::TimedOut, "Timed out")));
                } else {
                    if let Err(e) = pnet_sys::send_to(
                        self.socket.fd,
                        chunk,
                        send_addr,
                        self.send_addr_len as libc::socklen_t,
                    ) {
                        return Some(Err(e));
                    }
                }
            }

            Some(Ok(()))
        } else {
            None
        }
    }

    #[inline]
    fn send_to(&mut self, packet: &[u8], _dst: Option<NetworkInterface>) -> Option<io::Result<()>> {
        unsafe {
            libc::FD_ZERO(&mut self.fd_set as *mut libc::fd_set);
            libc::FD_SET(self.socket.fd, &mut self.fd_set as *mut libc::fd_set);
        }
        let ret = unsafe {
            libc::pselect(
                self.socket.fd + 1,
                ptr::null_mut(),
                &mut self.fd_set as *mut libc::fd_set,
                ptr::null_mut(),
                self.timeout
                    .as_ref()
                    .map(|to| to as *const libc::timespec)
                    .unwrap_or(ptr::null()),
                ptr::null(),
            )
        };
        if ret == -1 {
            Some(Err(io::Error::last_os_error()))
        } else if ret == 0 {
            Some(Err(io::Error::new(io::ErrorKind::TimedOut, "Timed out")))
        } else {
            match pnet_sys::send_to(
                self.socket.fd,
                packet,
                (&self.send_addr as *const libc::sockaddr_ll) as *const _,
                self.send_addr_len as libc::socklen_t,
            ) {
                Err(e) => Some(Err(e)),
                Ok(_) => Some(Ok(())),
            }
        }
    }
}

struct DataLinkReceiverImpl {
    socket: Arc<pnet_sys::FileDesc>,
    fd_set: libc::fd_set,
    read_buffer: Vec<u8>,
    _channel_type: super::ChannelType,
    timeout: Option<libc::timespec>,
}

impl DataLinkReceiver for DataLinkReceiverImpl {
    fn next(&mut self) -> io::Result<&[u8]> {
        let mut caddr: libc::sockaddr_storage = unsafe { mem::zeroed() };
        unsafe {
            libc::FD_ZERO(&mut self.fd_set as *mut libc::fd_set);
            libc::FD_SET(self.socket.fd, &mut self.fd_set as *mut libc::fd_set);
        }
        let ret = unsafe {
            libc::pselect(
                self.socket.fd + 1,
                &mut self.fd_set as *mut libc::fd_set,
                ptr::null_mut(),
                ptr::null_mut(),
                self.timeout
                    .as_ref()
                    .map(|to| to as *const libc::timespec)
                    .unwrap_or(ptr::null()),
                ptr::null(),
            )
        };
        if ret == -1 {
            Err(io::Error::last_os_error())
        } else if ret == 0 {
            Err(io::Error::new(io::ErrorKind::TimedOut, "Timed out"))
        } else {
            let res = pnet_sys::recv_from(self.socket.fd, &mut self.read_buffer, &mut caddr);
            match res {
                Ok(len) => Ok(&self.read_buffer[0..len]),
                Err(e) => Err(e),
            }
        }
    }
}

/// Get a list of available network interfaces for the current machine.
pub fn interfaces() -> Vec<NetworkInterface> {
    #[path = "unix_interfaces.rs"]
    mod interfaces;
    interfaces::interfaces()
}
<|endoftext|>


<commit_before>use super::*;

use std::{fmt, ops::Deref};

const INLINE_LEN_MASK: u8 = 0b0000_1111;
const KIND_MASK: u8 = 0b1111_0000;
const KIND_INLINE: u8 = 0b1000_0000;
const KIND_OWNED: u8 = 0b0100_0000;
const KIND_BORROWED: u8 = 0b0010_0000;

#[derive(Default, Ord, Eq, Serialize, Deserialize)]
pub(crate) struct IVec {
    #[serde(with = "ser")]
    data: [u8; 16],
}

impl IVec {
    pub(crate) fn new(v: Vec<u8>) -> IVec {
        if v.len() <= 15 {
            let sz = v.len() as u8;
            let tag = KIND_INLINE | sz;

            let mut data = [0u8; 16];
            data[15] = tag;
            data[0..v.len()].copy_from_slice(&v[0..v.len()]);

            IVec { data }
        } else {
            let bs = v.into_boxed_slice();
            let ptr: *mut _ = Box::into_raw(bs);
            let mut data: [u8; 16] =
                unsafe { std::mem::transmute(ptr) };

            assert_eq!(
                data[15],
                0,
                "we incorrectly assumed that we could use \
                the highest bits in the length field. please \
                report this bug ASAP!"
            );

            data[15] = KIND_OWNED;

            IVec { data }
        }
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> IVec {
        IVec::new(v)
    }
}

impl Deref for IVec {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        let tag = self.data[15];
        let kind = tag & KIND_MASK;
        match kind {
            k if k == KIND_INLINE => {
                let base = self.data.as_ptr();
                let len = (tag & INLINE_LEN_MASK) as usize;
                unsafe { std::slice::from_raw_parts(base, len) }
            }
            k if (k == KIND_OWNED || k == KIND_BORROWED) => {
                let mut data = self.data.clone();
                data[15] = 0;
                let ptr: *mut [u8] =
                    unsafe { std::mem::transmute(data) };

                unsafe { &*ptr }
            }
            other => {
                panic!("unknown kind {}", other);
            }
        }
    }
}

impl Clone for IVec {
    fn clone(&self) -> IVec {
        self.to_vec().into()
    }
}

impl Drop for IVec {
    fn drop(&mut self) {
        let tag = self.data[15];
        let kind = tag & KIND_MASK;
        match kind {
            k if k == KIND_OWNED => {
                let mut data = self.data.clone();
                data[15] = 0;
                let ptr: *mut [u8] =
                    unsafe { std::mem::transmute(data) };
                let b: Box<[u8]> = unsafe { Box::from_raw(ptr) };
                drop(b);
            }
            _ => {
                // no owned remote storage
            }
        }
    }
}

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

impl PartialEq for IVec {
    fn eq(&self, other: &IVec) -> bool {
        self.deref() == other.deref()
    }
}

impl<'a, T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.deref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.deref() == other
    }
}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "IVec( {:?} )", self.deref())
    }
}

pub(crate) mod ser {
    use super::IVec;

    use std::ops::Deref;

    use serde::de::{Deserialize, Deserializer};
    use serde::ser::Serializer;

    pub(crate) fn serialize<S>(
        data: &[u8; 16],
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let iv = IVec { data: *data };
        let ivr: &[u8] = iv.deref();
        serializer.collect_seq(ivr)
    }

    pub(crate) fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<[u8; 16], D::Error>
    where
        D: Deserializer<'de>,
    {
        let v = Vec::<u8>::deserialize(deserializer)?;
        let iv: IVec = v.into();
        let data: [u8; 16] = iv.data;
        std::mem::forget(iv);
        Ok(data)
    }
}

#[test]
fn ivec_usage() {
    let iv1: IVec = vec![1, 2, 3].into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::new(vec![4; 128]);
    assert_eq!(iv2, vec![4; 128]);
}
<commit_msg>Fix use after free on IVec<commit_after>use super::*;

use std::{fmt, ops::Deref};

const INLINE_LEN_MASK: u8 = 0b0000_1111;
const KIND_MASK: u8 = 0b1111_0000;
const KIND_INLINE: u8 = 0b1000_0000;
const KIND_OWNED: u8 = 0b0100_0000;
const KIND_BORROWED: u8 = 0b0010_0000;

#[derive(Default, Ord, Eq, Serialize, Deserialize)]
pub(crate) struct IVec {
    #[serde(with = "ser")]
    data: [u8; 16],
}

impl IVec {
    pub(crate) fn new(v: Vec<u8>) -> IVec {
        if v.len() <= 15 {
            let sz = v.len() as u8;
            let tag = KIND_INLINE | sz;

            let mut data = [0u8; 16];
            data[15] = tag;
            data[0..v.len()].copy_from_slice(&v[0..v.len()]);

            IVec { data }
        } else {
            let bs = v.into_boxed_slice();
            let ptr: *mut _ = Box::into_raw(bs);
            let mut data: [u8; 16] =
                unsafe { std::mem::transmute(ptr) };

            assert_eq!(
                data[15], 0,
                "we incorrectly assumed that we could use \
                 the highest bits in the length field. please \
                 report this bug ASAP!"
            );

            data[15] = KIND_OWNED;

            IVec { data }
        }
    }

    pub(crate) fn take(&mut self) -> IVec {
        assert_ne!(
            self.data[15], KIND_BORROWED,
            "take called on Borrowed IVec"
        );
        let ret = IVec { data: self.data };
        if self.data[15] == KIND_OWNED {
            self.data[15] = KIND_BORROWED;
        }
        ret
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> IVec {
        IVec::new(v)
    }
}

impl Deref for IVec {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        let tag = self.data[15];
        let kind = tag & KIND_MASK;
        match kind {
            k if k == KIND_INLINE => {
                let base = self.data.as_ptr();
                let len = (tag & INLINE_LEN_MASK) as usize;
                unsafe { std::slice::from_raw_parts(base, len) }
            }
            k if (k == KIND_OWNED || k == KIND_BORROWED) => {
                let mut data: [u8; 16] = self.data;
                data[15] = 0;

                unsafe {
                    let ptr: *mut [u8] = std::mem::transmute(data);
                    &*ptr
                }
            }
            other => {
                panic!("unknown kind {}", other);
            }
        }
    }
}

impl Clone for IVec {
    fn clone(&self) -> IVec {
        self.deref().to_vec().into()
    }
}

impl Drop for IVec {
    fn drop(&mut self) {
        let tag = self.data[15];
        let kind = tag & KIND_MASK;
        match kind {
            k if k == KIND_OWNED => {
                let mut data = self.data.clone();
                data[15] = 0;
                unsafe {
                    let ptr: *mut [u8] = std::mem::transmute(data);
                    let b: Box<[u8]> = Box::from_raw(ptr);
                    drop(b);
                }
            }
            _ => {
                // no owned remote storage
            }
        }
    }
}

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

impl PartialEq for IVec {
    fn eq(&self, other: &IVec) -> bool {
        self.deref() == other.deref()
    }
}

impl<'a, T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.deref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.deref() == other
    }
}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "IVec( {:?} )", self.deref())
    }
}

pub(crate) mod ser {
    use super::{IVec, KIND_BORROWED, KIND_OWNED};

    use std::ops::Deref;

    use serde::de::{Deserialize, Deserializer};
    use serde::ser::Serializer;

    pub(crate) fn serialize<S>(
        data: &[u8; 16],
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut data: [u8; 16] = *data;
        if data[15] == KIND_OWNED {
            data[15] = KIND_BORROWED;
        }

        let iv = IVec { data: data };
        let ivr: &[u8] = iv.deref();
        serializer.collect_seq(ivr)
    }

    pub(crate) fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<[u8; 16], D::Error>
    where
        D: Deserializer<'de>,
    {
        let v = Vec::<u8>::deserialize(deserializer)?;
        let mut iv: IVec = v.into();
        let data: [u8; 16] = iv.data;
        iv.data[15] = KIND_BORROWED;
        Ok(data)
    }
}

#[test]
fn ivec_usage() {
    let iv1: IVec = vec![1, 2, 3].into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::new(vec![4; 128]);
    assert_eq!(iv2, vec![4; 128]);
}
<|endoftext|>


<commit_before>//! Defines types found in various posix_types.h files.
//!
//! If unsure, check include/uapi/asm-generic/posix_types.h **first**, then /arch/*/include/uapi/asm/posix_types.h
//!
//! For the best result, use http://lxr.free-electrons.com

#[cfg(any(target_arch="sparc", target_arch="parisc"))]
///A type that defines microseconds. Since you're using either SPARC or (pa)RISC, it is a c_int
pub type suseconds_t = ::c_int;

#[cfg(not(any(target_arch="sparc", target_arch="parisc")))]
///A type that defines microseconds. You're using a "regular" processor, so it is a c_long
pub type suseconds_t = ::c_long;

///A type that defines a clock ID. As of 4.1, this is always c_int
pub type clockid_t = ::c_int;

///A type that defines a Process or Thread Group ID
pub type pid_t = ::c_int;

///A type that defines a user ID
pub type uid_t = ::c_uint;

///A type that defines a group ID
pub type gid_t = ::c_uint;<commit_msg>Add __kernel_long_t and __kernel_ulong_t<commit_after>//! Defines types found in various posix_types.h files.
//!
//! If unsure, check include/uapi/asm-generic/posix_types.h **first**, then /arch/*/include/uapi/asm/posix_types.h
//!
//! For the best result, use http://lxr.free-electrons.com

#[cfg(any(target_arch="sparc", target_arch="parisc"))]
///A type that defines microseconds. Since you're using either SPARC or (pa)RISC, it is a c_int
pub type suseconds_t = ::c_int;

#[cfg(not(any(target_arch="sparc", target_arch="parisc")))]
///A type that defines microseconds. You're using a "regular" processor, so it is a c_long
pub type suseconds_t = ::c_long;

///A type that defines a clock ID. As of 4.1, this is always c_int
pub type clockid_t = ::c_int;

///A type that defines a Process or Thread Group ID
pub type pid_t = ::c_int;

///A type that defines a user ID
pub type uid_t = ::c_uint;

///A type that defines a group ID
pub type gid_t = ::c_uint;

#[cfg(target_arch="x86")]
///A kernel type for long, set to c_longlong snice you're on x86
pub type __kernel_long_t = ::c_longlong;

#[cfg(not(target_arch="x86"))]
///A kernel type for long, set to c_long since you're not on x86
pub type __kernel_long_t = ::c_long;

#[cfg(target_arch="x86")]
///A kernel type for ulong, set to c_ulonglong snice you're on x86
pub type __kernel_ulong_t = ::c_ulonglong;

#[cfg(not(target_arch="x86"))]
///A kernel type for ulong, set to c_ulong since you're not on x86
pub type __kernel_ulong_t = ::c_ulong;<|endoftext|>


<commit_before>use std::io::Read;
use std::io::BufReader;
use std::io::Error as IoError;

use color::{ColorType};
use image::{DecodingResult, ImageDecoder, ImageResult, ImageError};
extern crate byteorder;
use self::byteorder::{BigEndian, ByteOrder};

/// PPM decoder
pub struct PPMDecoder<R> {
    reader: BufReader<R>,
    width: u32,
    height: u32,
    maxwhite: u32,
}

impl<R: Read> PPMDecoder<R> {
    /// Create a new decoder that decodes from the stream ```r```
    pub fn new(read: R) -> ImageResult<PPMDecoder<R>> {
        let mut buf = BufReader::new(read);
        let mut magic: [u8; 2] = [0, 0];
        try!(buf.read_exact(&mut magic[..])); // Skip magic constant
        if magic[0] != b'P' || (magic[1] != b'3' && magic[1] != b'6') {
            return Err(ImageError::FormatError("Expected magic constant for ppm, P3 or P6".to_string()));
        }

        let width = try!(PPMDecoder::read_next_u32(&mut buf));
        let height = try!(PPMDecoder::read_next_u32(&mut buf));
        let maxwhite = try!(PPMDecoder::read_next_u32(&mut buf));

        Ok(PPMDecoder {
            reader: buf,
            width: width,
            height: height,
            maxwhite: maxwhite,
        })
    }

    /// Reads a string as well as a single whitespace after it, ignoring comments
    fn read_next_string(reader: &mut BufReader<R>) -> ImageResult<String> {
        let mut bytes = Vec::new();

        let mark_comments = reader
            .bytes()
            .scan(true, |partof, read| {
                let byte = match read {
                    Err(err) => return Some((*partof, Err(err))),
                    Ok(byte) => byte,
                };
                if *partof && byte == b'#' {
                    *partof = false;
                    return Some((false, Ok(byte)));
                } else if !*partof && (byte == b'\r' || byte == b'\n') {
                    *partof = true;
                    return Some((false, Ok(byte)));
                }
                return Some((*partof, Ok(byte)));
            });

        for (_, byte) in mark_comments.filter(|ref e| e.0) {
            match byte {
                Ok(b'\n') | Ok(b' ') | Ok(b'\r') | Ok(b'\t') => {
                    if !bytes.is_empty() {
                        break // We're done as we already have some content
                    }
                },
                Ok(byte) => {
                    bytes.push(byte);
                },
                Err(_) => break,
            }
        }

        if bytes.is_empty() {
            return Err(ImageError::FormatError("Unexpected eof".to_string()))
        }

        String::from_utf8(bytes).map_err(|_| ImageError::FormatError("Couldn't read preamble".to_string()))
    }

    fn read_next_u32(reader: &mut BufReader<R>) -> ImageResult<u32> {
        let s = try!(PPMDecoder::read_next_string(reader));
        s.parse::<u32>().map_err(|_| ImageError::FormatError("Couldn't read preamble".to_string()))
    }
}

impl<R: Read> ImageDecoder for PPMDecoder<R> {
    fn dimensions(&mut self) -> ImageResult<(u32, u32)> {
        Ok((self.width, self.height))
    }

    fn colortype(&mut self) -> ImageResult<ColorType> {
        match self.bytewidth() {
            1 => Ok(ColorType::RGB(8)),
            2 => Ok(ColorType::RGB(16)),
            _ => Err(ImageError::FormatError("Don't know how to decode PPM with more than 16 bits".to_string())),
        }
    }

    fn row_len(&mut self) -> ImageResult<usize> {
        Ok((self.width*3*self.bytewidth()) as usize)
    }

    fn read_scanline(&mut self, _buf: &mut [u8]) -> ImageResult<u32> {
        unimplemented!();
    }

    fn read_image(&mut self) -> ImageResult<DecodingResult> {
        let opt_size = self.width.checked_mul(self.height)
            .map_or(None, |v| v.checked_mul(3))
            .map_or(None, |v| v.checked_mul(self.bytewidth()));

        let size = match opt_size {
            Some(v) => v,
            None => return Err(ImageError::DimensionError),
        };

        let mut data = vec![0 as u8; size as usize];

        match self.reader.read_exact(&mut data) {
            Ok(_) => {},
            Err(e) => return Err(ImageError::IoError(e)),
        };

        if self.bytewidth() == 1 {
            Ok(DecodingResult::U8(data))
        } else {
            let mut out = vec![0 as u16; (self.width*self.height*3) as usize];
            for (o, i) in out.chunks_mut(1).zip(data.chunks(2)) {
                o[0] = BigEndian::read_u16(i);
            }
            Ok(DecodingResult::U16(out))
        }
    }
}

impl<R: Read> PPMDecoder<R> {
    fn bytewidth(&self) -> u32 {
        if self.maxwhite < 256 { 1 } else { 2 }
    }
}

/// Tests parsing binary buffers were written based on and validated against `identify` from
/// ImageMagick (https://www.imagemagick.org/script/identify.php).
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn minimal_form() {
        // Violates current specification (October 2016 ) but accepted by both netpbm and ImageMagick
        decode_minimal_image(&b"P61 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123\xFF"[..]); // Too long should not be an issue
    }

    #[test]
    fn comment_in_token() {
        decode_minimal_image(&b"P6 1 1 2#comment\n55 123"[..]); // Terminating LF
        decode_minimal_image(&b"P6 1 1 2#comment\r55 123"[..]); // Terminating CR
        decode_minimal_image(&b"P6 1 1#comment\n 255 123"[..]); // Comment after token
        decode_minimal_image(&b"P6 1 1 #comment\n255 123"[..]); // Comment before token
        decode_minimal_image(&b"P6#comment\n 1 1 255 123"[..]); // Begin of header
        decode_minimal_image(&b"P6 1 1 255#comment\n 123"[..]); // End of header
    }

    #[test]
    fn whitespace() {
        decode_minimal_image(&b"P6\x091\x091\x09255\x09123"[..]); // TAB
        decode_minimal_image(&b"P6\x0a1\x0a1\x0a255\x0a123"[..]); // LF
        decode_minimal_image(&b"P6\x0b1\x0b1\x0b255\x0b123"[..]); // VT
        decode_minimal_image(&b"P6\x0c1\x0c1\x0c255\x0c123"[..]); // FF
        decode_minimal_image(&b"P6\x0d1\x0d1\x0d255\x0d123"[..]); // CR
        // Spaces tested before
        decode_minimal_image(&b"P61\x09\x0a\x0b\x0c\x0d1 255 123"[..]); // All whitespace, combined
    }

    /// Tests for decoding error, assuming `encoded` is ppm encoding for the very simplistic image
    /// containing a single pixel with one byte values (1, 2, 3).
    fn decode_minimal_image(encoded: &[u8]) {
        let content = vec![49 as u8, 50, 51];
        let mut decoder = super::PPMDecoder::new(encoded).unwrap();

        assert_eq!(decoder.dimensions().unwrap(), (1, 1));
        assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
        assert_eq!(decoder.row_len().unwrap(), 3);
        assert_eq!(decoder.bytewidth(), 1);

        match decoder.read_image().unwrap() {
            DecodingResult::U8(image) => assert_eq!(image, content),
            _ => assert!(false),
        }
    }
}
<commit_msg>Add missing whitespace characters<commit_after>use std::io::Read;
use std::io::BufReader;
use std::io::Error as IoError;

use color::{ColorType};
use image::{DecodingResult, ImageDecoder, ImageResult, ImageError};
extern crate byteorder;
use self::byteorder::{BigEndian, ByteOrder};

/// PPM decoder
pub struct PPMDecoder<R> {
    reader: BufReader<R>,
    width: u32,
    height: u32,
    maxwhite: u32,
}

impl<R: Read> PPMDecoder<R> {
    /// Create a new decoder that decodes from the stream ```r```
    pub fn new(read: R) -> ImageResult<PPMDecoder<R>> {
        let mut buf = BufReader::new(read);
        let mut magic: [u8; 2] = [0, 0];
        try!(buf.read_exact(&mut magic[..])); // Skip magic constant
        if magic[0] != b'P' || (magic[1] != b'3' && magic[1] != b'6') {
            return Err(ImageError::FormatError("Expected magic constant for ppm, P3 or P6".to_string()));
        }

        let width = try!(PPMDecoder::read_next_u32(&mut buf));
        let height = try!(PPMDecoder::read_next_u32(&mut buf));
        let maxwhite = try!(PPMDecoder::read_next_u32(&mut buf));

        Ok(PPMDecoder {
            reader: buf,
            width: width,
            height: height,
            maxwhite: maxwhite,
        })
    }

    /// Reads a string as well as a single whitespace after it, ignoring comments
    fn read_next_string(reader: &mut BufReader<R>) -> ImageResult<String> {
        let mut bytes = Vec::new();

        let mark_comments = reader
            .bytes()
            .scan(true, |partof, read| {
                let byte = match read {
                    Err(err) => return Some((*partof, Err(err))),
                    Ok(byte) => byte,
                };
                if *partof && byte == b'#' {
                    *partof = false;
                    return Some((false, Ok(byte)));
                } else if !*partof && (byte == b'\r' || byte == b'\n') {
                    *partof = true;
                    return Some((false, Ok(byte)));
                }
                return Some((*partof, Ok(byte)));
            });

        for (_, byte) in mark_comments.filter(|ref e| e.0) {
            match byte {
                Ok(b'\t') | Ok(b'\n') | Ok(b'\x0b') | Ok(b'\x0c') | Ok(b'\r') | Ok(b' ') => {
                    if !bytes.is_empty() {
                        break // We're done as we already have some content
                    }
                },
                Ok(byte) => {
                    bytes.push(byte);
                },
                Err(_) => break,
            }
        }

        if bytes.is_empty() {
            return Err(ImageError::FormatError("Unexpected eof".to_string()))
        }

        String::from_utf8(bytes).map_err(|_| ImageError::FormatError("Couldn't read preamble".to_string()))
    }

    fn read_next_u32(reader: &mut BufReader<R>) -> ImageResult<u32> {
        let s = try!(PPMDecoder::read_next_string(reader));
        s.parse::<u32>().map_err(|_| ImageError::FormatError("Couldn't read preamble".to_string()))
    }
}

impl<R: Read> ImageDecoder for PPMDecoder<R> {
    fn dimensions(&mut self) -> ImageResult<(u32, u32)> {
        Ok((self.width, self.height))
    }

    fn colortype(&mut self) -> ImageResult<ColorType> {
        match self.bytewidth() {
            1 => Ok(ColorType::RGB(8)),
            2 => Ok(ColorType::RGB(16)),
            _ => Err(ImageError::FormatError("Don't know how to decode PPM with more than 16 bits".to_string())),
        }
    }

    fn row_len(&mut self) -> ImageResult<usize> {
        Ok((self.width*3*self.bytewidth()) as usize)
    }

    fn read_scanline(&mut self, _buf: &mut [u8]) -> ImageResult<u32> {
        unimplemented!();
    }

    fn read_image(&mut self) -> ImageResult<DecodingResult> {
        let opt_size = self.width.checked_mul(self.height)
            .map_or(None, |v| v.checked_mul(3))
            .map_or(None, |v| v.checked_mul(self.bytewidth()));

        let size = match opt_size {
            Some(v) => v,
            None => return Err(ImageError::DimensionError),
        };

        let mut data = vec![0 as u8; size as usize];

        match self.reader.read_exact(&mut data) {
            Ok(_) => {},
            Err(e) => return Err(ImageError::IoError(e)),
        };

        if self.bytewidth() == 1 {
            Ok(DecodingResult::U8(data))
        } else {
            let mut out = vec![0 as u16; (self.width*self.height*3) as usize];
            for (o, i) in out.chunks_mut(1).zip(data.chunks(2)) {
                o[0] = BigEndian::read_u16(i);
            }
            Ok(DecodingResult::U16(out))
        }
    }
}

impl<R: Read> PPMDecoder<R> {
    fn bytewidth(&self) -> u32 {
        if self.maxwhite < 256 { 1 } else { 2 }
    }
}

/// Tests parsing binary buffers were written based on and validated against `identify` from
/// ImageMagick (https://www.imagemagick.org/script/identify.php).
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn minimal_form() {
        // Violates current specification (October 2016 ) but accepted by both netpbm and ImageMagick
        decode_minimal_image(&b"P61 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123\xFF"[..]); // Too long should not be an issue
    }

    #[test]
    fn comment_in_token() {
        decode_minimal_image(&b"P6 1 1 2#comment\n55 123"[..]); // Terminating LF
        decode_minimal_image(&b"P6 1 1 2#comment\r55 123"[..]); // Terminating CR
        decode_minimal_image(&b"P6 1 1#comment\n 255 123"[..]); // Comment after token
        decode_minimal_image(&b"P6 1 1 #comment\n255 123"[..]); // Comment before token
        decode_minimal_image(&b"P6#comment\n 1 1 255 123"[..]); // Begin of header
        decode_minimal_image(&b"P6 1 1 255#comment\n 123"[..]); // End of header
    }

    #[test]
    fn whitespace() {
        decode_minimal_image(&b"P6\x091\x091\x09255\x09123"[..]); // TAB
        decode_minimal_image(&b"P6\x0a1\x0a1\x0a255\x0a123"[..]); // LF
        decode_minimal_image(&b"P6\x0b1\x0b1\x0b255\x0b123"[..]); // VT
        decode_minimal_image(&b"P6\x0c1\x0c1\x0c255\x0c123"[..]); // FF
        decode_minimal_image(&b"P6\x0d1\x0d1\x0d255\x0d123"[..]); // CR
        // Spaces tested before
        decode_minimal_image(&b"P61\x09\x0a\x0b\x0c\x0d1 255 123"[..]); // All whitespace, combined
    }

    /// Tests for decoding error, assuming `encoded` is ppm encoding for the very simplistic image
    /// containing a single pixel with one byte values (1, 2, 3).
    fn decode_minimal_image(encoded: &[u8]) {
        let content = vec![49 as u8, 50, 51];
        let mut decoder = super::PPMDecoder::new(encoded).unwrap();

        assert_eq!(decoder.dimensions().unwrap(), (1, 1));
        assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
        assert_eq!(decoder.row_len().unwrap(), 3);
        assert_eq!(decoder.bytewidth(), 1);

        match decoder.read_image().unwrap() {
            DecodingResult::U8(image) => assert_eq!(image, content),
            _ => assert!(false),
        }
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use syntax::ast::*;
use std::ops::Deref;
use syntax::ext::quote::rt::Span;
use utils::span_note_and_lint;

/// **What it does:** Checks for
///  - () being assigned to a variable
///  - () being passed to a function
///
/// **Why is this bad?** It is extremely unlikely that a user intended to
/// assign '()' to valiable. Instead,
/// Unit is what a block evaluates to when it returns nothing. This is
/// typically caused by a trailing
///   unintended semicolon.
///
/// **Known problems:** None.
///
/// **Example:**
/// * `let x = {"foo" ;}` when the user almost certainly intended `let x
/// ={"foo"}`

declare_lint! {
    pub UNIT_EXPR,
    Warn,
    "unintended assignment or use of a unit typed value"
}

#[derive(Copy, Clone)]
pub struct UnitExpr;

impl LintPass for UnitExpr {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNIT_EXPR)
    }
}

impl EarlyLintPass for UnitExpr {
    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
        if let ExprKind::Assign(ref _left, ref right) = expr.node {
            if let Some(span) = is_unit_expr(right) {
                span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon");
            }
        }
        if let ExprKind::MethodCall(ref _left, ref args) = expr.node {
            for ref arg in args {
                if let Some(span) = is_unit_expr(arg) {
                span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon");
                }
            }
        }
        if let ExprKind::Call(_, ref args) = expr.node {
            for ref arg in args {
                if let Some(span) = is_unit_expr(arg) {
                span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon");
                }
            }
        }
    }

    fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) {
        if let StmtKind::Local(ref local) = stmt.node {
            if local.pat.node == PatKind::Wild {
                return;
            }
            if let Some(ref expr) = local.init {
                if let Some(span) = is_unit_expr(expr) {
                span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon");
                }
            }
        }
    }
}
fn is_unit_expr(expr: &Expr) -> Option<Span> {
    match expr.node {
        ExprKind::Block(ref block) => if check_last_stmt_in_block(block) {
            return Some(block.stmts[block.stmts.len() - 1].span.clone());
        } else {
            return None;
        },
        ExprKind::If(_, ref then, ref else_) => {
            let check_then = check_last_stmt_in_block(then);
            if let Some(ref else_) = *else_ {
                let check_else = is_unit_expr(else_.deref());
                if let Some(ref expr_else) = check_else {
                    return Some(expr_else.clone());
                }
            }
            if check_then {
                return Some(expr.span.clone());
            } else {
                return None;
            }
        },
        ExprKind::Match(ref _pattern, ref arms) => {
            for ref arm in arms {
                if let Some(expr) = is_unit_expr(&arm.body) {
                    return Some(expr);
                }
            }
            return None;
        },
        _ => return None,
    }
}

fn check_last_stmt_in_block(block: &Block) -> bool {
    let ref final_stmt = &block.stmts[block.stmts.len() - 1];
    if let StmtKind::Expr(_) = final_stmt.node {
        return false;
    } else {
        return true;
    }
}
<commit_msg>Don't trigger lint on break or return<commit_after>use rustc::lint::*;
use syntax::ast::*;
use std::ops::Deref;
use syntax::ext::quote::rt::Span;
use utils::span_note_and_lint;

/// **What it does:** Checks for
///  - () being assigned to a variable
///  - () being passed to a function
///
/// **Why is this bad?** It is extremely unlikely that a user intended to
/// assign '()' to valiable. Instead,
/// Unit is what a block evaluates to when it returns nothing. This is
/// typically caused by a trailing
///   unintended semicolon.
///
/// **Known problems:** None.
///
/// **Example:**
/// * `let x = {"foo" ;}` when the user almost certainly intended `let x
/// ={"foo"}`

declare_lint! {
    pub UNIT_EXPR,
    Warn,
    "unintended assignment or use of a unit typed value"
}

#[derive(Copy, Clone)]
pub struct UnitExpr;

impl LintPass for UnitExpr {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNIT_EXPR)
    }
}

impl EarlyLintPass for UnitExpr {
    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
        if let ExprKind::Assign(ref _left, ref right) = expr.node {
            if let Some(span) = is_unit_expr(right) {
                span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon");
            }
        }
        if let ExprKind::MethodCall(ref _left, ref args) = expr.node {
            for ref arg in args {
                if let Some(span) = is_unit_expr(arg) {
                span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon");
                }
            }
        }
        if let ExprKind::Call(_, ref args) = expr.node {
            for ref arg in args {
                if let Some(span) = is_unit_expr(arg) {
                span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon");
                }
            }
        }
    }

    fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) {
        if let StmtKind::Local(ref local) = stmt.node {
            if local.pat.node == PatKind::Wild {
                return;
            }
            if let Some(ref expr) = local.init {
                if let Some(span) = is_unit_expr(expr) {
                span_note_and_lint(cx, UNIT_EXPR, expr.span,"This expression assigns the Unit type ()",span,"Consider removing the trailing semicolon");
                }
            }
        }
    }
}
fn is_unit_expr(expr: &Expr) -> Option<Span> {
    match expr.node {
        ExprKind::Block(ref block) => if check_last_stmt_in_block(block) {
            return Some(block.stmts[block.stmts.len() - 1].span.clone());
        } else {
            return None;
        },
        ExprKind::If(_, ref then, ref else_) => {
            let check_then = check_last_stmt_in_block(then);
            if let Some(ref else_) = *else_ {
                let check_else = is_unit_expr(else_.deref());
                if let Some(ref expr_else) = check_else {
                    return Some(expr_else.clone());
                }
            }
            if check_then {
                return Some(expr.span.clone());
            } else {
                return None;
            }
        },
        ExprKind::Match(ref _pattern, ref arms) => {
            for ref arm in arms {
                if let Some(expr) = is_unit_expr(&arm.body) {
                    return Some(expr);
                }
            }
            return None;
        },
        _ => return None,
    }
}

fn check_last_stmt_in_block(block: &Block) -> bool {
    let ref final_stmt = &block.stmts[block.stmts.len() - 1];

    match final_stmt.node{
        StmtKind::Expr(_) => return false,
        StmtKind::Semi(ref expr)=>{
               match expr.node{
                ExprKind::Break(_,_) => return false,
                ExprKind::Ret(_) => return false,
                _ => return true,
            }
        },
        _ => return true,
    }

}
<|endoftext|>


<commit_before>use std::path;
use std::ffi;

use super::sass;
use super::files;

use error::*;

#[derive(Debug, Clone, PartialEq, Default)]
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct AssetsBuilder {
    pub sass: sass::SassBuilder,
    pub source: Option<path::PathBuf>,
    pub ignore: Vec<String>,
    pub template_extensions: Vec<String>,
}

impl AssetsBuilder {
    pub fn build(self) -> Result<Assets> {
        let AssetsBuilder {
            sass,
            source,
            ignore,
            template_extensions,
        } = self;

        let sass = sass.build();

        let source = source.ok_or_else(|| "No asset source provided")?;

        let mut files = files::FilesBuilder::new(&source)?;
        for line in ignore {
            files.add_ignore(&line)?;
        }
        for ext in template_extensions {
            files.add_ignore(&format!("*.{}", ext))?;
        }
        let files = files.build()?;
        let assets = Assets {
            sass,
            files,
            source,
        };
        Ok(assets)
    }
}

#[derive(Debug)]
pub struct Assets {
    pub sass: sass::SassCompiler,
    pub files: files::Files,
    pub source: path::PathBuf,
}

impl Assets {
    pub fn source(&self) -> &path::Path {
        self.source.as_path()
    }

    pub fn files(&self) -> &files::Files {
        &self.files
    }

    pub fn populate<P: AsRef<path::Path>>(&self, dest: P) -> Result<()> {
        self.populate_path(dest.as_ref())
    }

    fn populate_path(&self, dest: &path::Path) -> Result<()> {
        for file_path in self.files() {
            if file_path.extension() == Some(ffi::OsStr::new("scss")) {
                self.sass.compile_file(&self.source, dest, file_path)?;
            } else {
                let rel_src = file_path
                    .strip_prefix(&self.source)
                    .expect("file was found under the root");
                files::copy_file(&file_path, dest.join(rel_src).as_path())?;
            }
        }

        Ok(())
    }
}
<commit_msg>refactor(assets): Remove duplicate code<commit_after>use std::path;
use std::ffi;

use super::sass;
use super::files;

use error::*;

#[derive(Debug, Clone, PartialEq, Default)]
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct AssetsBuilder {
    pub sass: sass::SassBuilder,
    pub source: Option<path::PathBuf>,
    pub ignore: Vec<String>,
    pub template_extensions: Vec<String>,
}

impl AssetsBuilder {
    pub fn build(self) -> Result<Assets> {
        let AssetsBuilder {
            sass,
            source,
            ignore,
            template_extensions,
        } = self;

        let sass = sass.build();

        let source = source.ok_or_else(|| "No asset source provided")?;

        let mut files = files::FilesBuilder::new(source)?;
        for line in ignore {
            files.add_ignore(&line)?;
        }
        for ext in template_extensions {
            files.add_ignore(&format!("*.{}", ext))?;
        }
        let files = files.build()?;
        let assets = Assets {
            sass,
            files,
        };
        Ok(assets)
    }
}

#[derive(Debug)]
pub struct Assets {
    sass: sass::SassCompiler,
    files: files::Files,
}

impl Assets {
    pub fn source(&self) -> &path::Path {
        self.files.root()
    }

    pub fn files(&self) -> &files::Files {
        &self.files
    }

    pub fn populate<P: AsRef<path::Path>>(&self, dest: P) -> Result<()> {
        self.populate_path(dest.as_ref())
    }

    fn populate_path(&self, dest: &path::Path) -> Result<()> {
        for file_path in self.files() {
            if file_path.extension() == Some(ffi::OsStr::new("scss")) {
                self.sass.compile_file(self.source(), dest, file_path)?;
            } else {
                let rel_src = file_path
                    .strip_prefix(self.source())
                    .expect("file was found under the root");
                files::copy_file(&file_path, dest.join(rel_src).as_path())?;
            }
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>extern crate find_folder;

use screen::{self, Screen, MainMenu};
use context::{Context, GameState};

use piston_window::{self, PistonWindow, WindowSettings};

type Screens = Vec<Box<screen::Screen>>;

pub struct Game {
    window: PistonWindow,
    context: Context,
    screens: Screens,
}

impl Game {
    pub fn new() -> Self {
        let window: PistonWindow = WindowSettings::new("rrthozopsi", [600, 600])
                                       .build()
                                       .unwrap();
        let mut context = Context {
            assets_path: find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap(),
            game_state: GameState::NotStarted,
        };
        let screens: Screens = vec![Box::new(MainMenu::new(&window, &mut context))];
        Game {
            window: window,
            screens: screens,
            context: context,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let screens = &mut self.screens;

        for window in &mut self.window {
            match window.event {
                Some(Event::Update(ref args)) => {
                    last(screens).on_update(&args);
                }
                Some(Event::Render(ref args)) => {
                    last(screens).on_draw(&args, &window);
                }
                Some(Event::Input(ref input)) => {
                    handle_input(screens, &input, &window, &mut self.context);
                    if screens.is_empty() {
                        // No screens - exit game.
                        return;
                    }
                }
                _ => {}
            }
        }
    }
}

fn last<'a>(vec: &'a mut Screens) -> &'a mut Box<screen::Screen> {
    vec.last_mut().unwrap()
}

fn handle_input(screens: &mut Screens, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) {
    for action in last(screens).on_input(&input, &window, context) {
        match action {
            screen::InputResult::PushScreen(new_screen) => {
                screens.push(new_screen);
            }
            screen::InputResult::PopScreen => {
                screens.pop();
            }
        }
    }
}
<commit_msg>Build fix<commit_after>extern crate find_folder;

use screen::{self, Screen, MainMenu};
use context::{Context, GameState};

use piston_window::{self, PistonWindow, WindowSettings};

type Screens = Vec<Box<screen::Screen>>;

pub struct Game {
    window: PistonWindow,
    context: Context,
    screens: Screens,
}

impl Game {
    pub fn new() -> Self {
        let window: PistonWindow = WindowSettings::new("rrthozopsi", [600, 600])
                                       .build()
                                       .unwrap();
        let mut context = Context {
            assets_path: find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap(),
            game_state: GameState::NotStarted,
        };
        let screens: Screens = vec![Box::new(MainMenu::new(&window, &mut context))];
        Game {
            window: window,
            screens: screens,
            context: context,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let screens = &mut self.screens;

        for window in &mut self.window {
            match window.event {
                Some(Event::Update(ref args)) => {
                    last(screens).on_update(&args);
                }
                Some(Event::Render(ref args)) => {
                    last(screens).on_draw(&args, &window);
                }
                Some(Event::Input(ref input)) => {
                    handle_input(screens, &input, &window, &mut self.context);
                    if screens.is_empty() {
                        // No screens - exit game.
                        return;
                    }
                }
                _ => {}
            }
        }
    }
}

fn last<'a>(vec: &'a mut Screens) -> &'a mut Box<screen::Screen> {
    vec.last_mut().unwrap()
}

fn handle_input(screens: &mut Screens, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) {
    for action in last(screens).on_input(&input, &window, context) {
        match action {
            screen::InputResult::PushScreen(new_screen) => {
                screens.push(new_screen);
            }
            screen::InputResult::PopScreen => {
                screens.pop();
            }
            screen::InputResult::Exit => {}
        }
    }
}
<|endoftext|>


<commit_before>use ::screen;
use ::screen::Screen;

use piston_window;

pub struct Game {
    window: piston_window::PistonWindow,
    screens: Vec<Box<screen::Screen>>,
}

impl Game {
    pub fn new() -> Game {
        let window: piston_window::PistonWindow = piston_window::WindowSettings::new("rrthozopsi", [600, 600]).exit_on_esc(true).build().unwrap();
        let screens: Vec<Box<screen::Screen>> = vec![Box::new(screen::MainMenuScreen::new())];
        Game {
            window: window,
            screens: screens,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let mut screen = self.screens.last_mut().unwrap();

        // TODO: Remove clone?
        for window in &mut self.window {
            match window.event {
                Some(Event::Update(args)) => { screen.on_update(&args); }
                Some(Event::Render(args)) => { screen.on_draw(&args, &window); }
                Some(Event::Input(ref input)) => {
            	    let result = screen.on_input(&input, &window);
            	}
                _ => {}
            }
        }
    }
}
<commit_msg>TODO note<commit_after>use ::screen;
use ::screen::Screen;

use piston_window;

pub struct Game {
    window: piston_window::PistonWindow,
    screens: Vec<Box<screen::Screen>>,
}

impl Game {
    pub fn new() -> Game {
        let window: piston_window::PistonWindow = piston_window::WindowSettings::new("rrthozopsi", [600, 600]).exit_on_esc(true).build().unwrap();
        let screens: Vec<Box<screen::Screen>> = vec![Box::new(screen::MainMenuScreen::new())];
        Game {
            window: window,
            screens: screens,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let mut screen = self.screens.last_mut().unwrap();

        // TODO: Remove clone?
        for window in &mut self.window {
            match window.event {
                Some(Event::Update(args)) => { screen.on_update(&args); }
                Some(Event::Render(args)) => { screen.on_draw(&args, &window); }
                Some(Event::Input(ref input)) => {
            	    // TODO iter (for) over result.
            	    let result = screen.on_input(&input, &window);
            	}
                _ => {}
            }
        }
    }
}
<|endoftext|>