<commit_before>/// Gets the offset of a field. Used by container_of!
macro_rules! offset_of(
    ($ty:ty, $field:ident) => {
        &(*(0 as *const $ty)).$field as *const _ as usize
    }
);

/// Gets the parent struct from a pointer.
/// VERY unsafe. The parent struct _must_ be repr(C), and the
/// type passed to this macro _must_ match the type of the parent.
macro_rules! container_of (
    ($ptr: expr, $container: ty, $field: ident) => {
        ($ptr as *mut u8).offset(-(offset_of!($container, $field) as isize)) as *mut $container
    }
);

/// Iterates over a wl_list.
///
/// # Safety
/// It is not safe to delete an element while iterating over the list,
/// so don't do it!
macro_rules! wl_list_for_each {
    ($ptr: expr, $field: ident, ($pos: ident : $container: ty) => $body: block) => {
        let mut $pos: *mut $container;
        $pos = container_of!($ptr.next, $container, $field);
        loop {
            if &(*$pos).$field as *const _ == &$ptr as *const _ {
                break
            }
            { $body }
            $pos = container_of!((*$pos).$field.next, $container, $field);
        }
    }
}

/// Logs a message using wlroots' logging capability.
///
/// Example:
/// ```rust,no_run,ignore
/// #[macro_use]
/// use wlroots::log::{init_logging, L_DEBUG, L_ERROR};
///
/// // Call this once, at the beginning of your program.
/// init_logging(WLR_DEBUG, None);
///
/// wlr_log!(L_DEBUG, "Hello world");
/// wlr_log!(L_ERROR, "Could not {:#?} the {}", foo, bar);
/// ```
#[macro_export]
macro_rules! wlr_log {
    ($verb: expr, $($msg:tt)*) => {{
        /// Convert a literal string to a C string.
        /// Note: Does not check for internal nulls, nor does it do any conversions on
        /// the grapheme clustors. Just passes the bytes as is.
        /// So probably only works on ASCII.
        macro_rules! c_str {
            ($s:expr) => {
                concat!($s, "\0").as_ptr()
                    as *const $crate::wlroots_sys::libc::c_char
            }
        }
        use $crate::wlroots_sys::_wlr_log;
        use $crate::wlroots_sys::wlr_log_importance::*;
        use ::std::ffi::CString;
        unsafe {
            let fmt = CString::new(format!($($msg)*))
                .expect("Could not convert log message to C string");
            let raw = fmt.into_raw();
            _wlr_log($verb, c_str!("[%s:%lu] %s"),
                    c_str!(file!()), line!(), raw);
            // Deallocate string
            CString::from_raw(raw);
        }
    }}
}

/// Defines a new struct that contains a variable number of listeners that
/// will trigger unsafe user-defined callbacks.
///
/// The structure that is defined is repr(C), has one `data` field with the
/// given user type, and a field for each `$listener`.
///
/// Each `$listener` has a getter method that lets you get the pointer to the
/// listener. This method is unsafe, since it returns a raw pointer.
/// To use it correctly, you need to ensure that the data it refers to never
/// moves (e.g keep it in a box). The primary purpose of this method is to pass
/// the listener pointer to other methods to register it for a Wayland event.
/// **A listener can only be registered to one event at a time**.
///
/// Finally, it also takes in a body for each `$listener` that is called
/// every time the event that is later hooked up to it is fired.
/// This method is inherently unsafe, because the user data hasn't been cast
/// from the void pointer yet. It is the user's job to write this safely.
/// To highlight this fact, the body of the function must be prefixed with
/// `unsafe`.
///
/// # Example
/// ```rust,no_run,ignore
/// #[macro_use] extern crate wlroots;
/// extern crate wlroots_sys;
/// #[macro_use] extern crate wayland_sys;
/// extern crate libc;
///
/// use wlroots::InputDevice;
/// use wlroots_sys::wlr_input_device;
///
/// // Handles input addition and removal.
/// pub trait InputManagerHandler {
///     // Callback triggered when an input device is added.
///     fn input_added(&mut self, InputDevice);
/// }
///
/// wayland_listener!(
///     // The name of the structure that will be defined.
///     pub(crate) InputManager,
///     // The type that's stored in the `data` field.
///     // Note that we use a Box here to achieve dynamic dispatch,
///     // it's not required for this type to be in a box.
///     Box<InputManagerHandler>,
///     [
///         // Adds a new listener called `add_listener`.
///         // Adds an unsafe function called `add_notify` that is triggered
///         // whenever add_listener is activated from a Wayland event.
///         add_listener => add_notify: |this: &mut InputManager, data: *mut libc::c_void,| unsafe {
///             let ref mut manager = this.data;
///             // Call the method defined above, wrapping it in a safe interface.
///             // It is your job to ensure that the code in here doesn't trigger UB!
///             manager.input_added(InputDevice::from_ptr(data as *mut wlr_input_device))
///         };
///     ]
/// );
/// # fn main() {}
/// ```
///
/// # Unsafety
/// Note that the purpose of this macro is to make it easy to generate unsafe
/// boiler plate for using listeners with Rust data.
///
/// However, there are a few things this macro doesn't protect against.
///
/// First and foremost, the data cannot move. The listeners assume that the
/// structure will never move, so in order to defend against this the generated
/// `new` method returns a Box version. **Do not move out of the box**.
///
/// Second, this macro doesn't protect against the stored data being unsized.
/// Passing a pointer of unsized data to C is UB, don't do it.
macro_rules! wayland_listener {
    ($pub: vis $struct_name: ident, $data: ty, $([
        $($listener: ident => $listener_func: ident :
          |$($func_arg:ident: $func_type:ty,)*| unsafe $body: block;)*])+) => {
        #[repr(C)]
        #[doc(hidden)]
        $pub struct $struct_name {
            data: $data,
            $($($listener: $crate::wlroots_sys::wl_listener),*)*
        }

        impl $struct_name {
            pub(crate) fn new(data: $data) -> Box<$struct_name> {
                use $crate::wlroots_sys::server::WAYLAND_SERVER_HANDLE;
                Box::new($struct_name {
                    data,
                    $($($listener: unsafe {
                        // NOTE Rationale for zeroed memory:
                        // * Need to pass a pointer to wl_list_init
                        // * The list is initialized by Wayland, which doesn't "drop"
                        // * The listener is written to without dropping any of the data
                        let mut listener: $crate::wlroots_sys::wl_listener = ::std::mem::zeroed();
                        ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                      wl_list_init,
                                      &mut listener.link as *mut _ as _);
                        ::std::ptr::write(&mut listener.notify, Some($struct_name::$listener_func));
                        listener
                    }),*)*
                })
            }

            $($(pub(crate) unsafe extern "C" fn $listener(&mut self)
                                                   -> *mut $crate::wlroots_sys::wl_listener {
                &mut self.$listener as *mut _
            })*)*

            $($(pub(crate) unsafe extern "C" fn $listener_func(listener:
                                                        *mut $crate::wlroots_sys::wl_listener,
                                                        data: *mut $crate::libc::c_void) {
                let manager: &mut $struct_name = &mut (*container_of!(listener,
                                                                      $struct_name,
                                                                      $listener));
                $crate::utils::handle_unwind(
                    ::std::panic::catch_unwind(
                        ::std::panic::AssertUnwindSafe(|| {
                            (|$($func_arg: $func_type,)*| { $body })(manager, data)
                        })));
            })*)*
        }
    }
}

macro_rules! wayland_listener_static {
    (static mut $static_manager: ident;
     $(($manager: ident, $builder: ident):
       $([
           $(
               $([$($extra_callback_name: ident: $extra_callback_type: ty),+])*
               ($fn_type: ty, $listener: ident, $builder_func: ident) => ($notify: ident, $callback: ident):
               |$($func_arg: ident: $func_type: ty,)*| unsafe $body: block;
           )*
       ])+
     )+
    ) => {
        $(
            #[derive(Default)]
            #[allow(dead_code)]
            /// A builder of static functions to manage and create resources.
            ///
            /// Implement the functions with the necessary signature, pass them
            /// to the builder, and then give the builder to the necessary
            /// structure in order to utilize them (usually it's `compositor::Builder`).
            pub struct $builder {
                $($(pub(crate) $callback: ::std::option::Option<$fn_type>,)*
                  $($($($extra_callback_name: ::std::option::Option<$extra_callback_type>,)*)*)*)*
            }

            impl $builder {
                $($(
                    /// Uses the provided callback as the receiver for the
                    /// event the type signature describes.
                    pub fn $builder_func(mut self, $callback: $fn_type) -> Self {
                        self.$callback = ::std::option::Option::Some($callback);
                        self
                    }
                    $($(
                        /// Uses the provided callback as the receiver for the
                        /// event the type signature describes.
                        pub fn $extra_callback_name(mut self, $extra_callback_name: $extra_callback_type) -> Self {
                            self.$extra_callback_name = ::std::option::Option::Some($extra_callback_name);
                            self
                        }
                    )*)*
                )*)*
            }
        )*

        $(
            #[repr(C)]
            pub(crate) struct $manager {
                $($(
                    pub(crate) $listener: $crate::wlroots_sys::wl_listener,
                    $callback: ::std::option::Option<$fn_type>,
                    $($($extra_callback_name: ::std::option::Option<$extra_callback_type>),*)*
                )*)*
            }

            pub(crate) static mut $static_manager: $manager = $manager {
                $($(
                    $listener: $crate::wlroots_sys::wl_listener {
                        link: {
                            $crate::wlroots_sys::wl_list {
                                prev: ::std::ptr::null_mut(),
                                next: ::std::ptr::null_mut()}},
                        notify: ::std::option::Option::None },
                    $callback: ::std::option::Option::None,
                    $($($extra_callback_name: ::std::option::Option::None),*)*
                )*)*
            };

            impl $manager {
                /// Sets the functions on the builder as the global manager functions.
                ///
                /// # Safety
                /// Returns a mutable reference to static data, which is unsafe to have
                /// multiple of. Do all your mutation through this reference and don't
                /// call this function multiple times.
                pub(crate) unsafe fn build(builder: $builder) -> &'static mut $manager {
                    $($(
                        $static_manager.$listener = {
                            // NOTE Rationale for zeroed memory:
                            // * Need to pass a pointer to wl_list_init
                            // * The list is initialized by Wayland, which doesn't "drop"
                            // * The listener is written to without dropping any of the data
                            let mut listener: $crate::wlroots_sys::wl_listener = ::std::mem::zeroed();
                            use $crate::wlroots_sys::server::WAYLAND_SERVER_HANDLE;
                            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                          wl_list_init,
                                          &mut listener.link as *mut _ as _);
                            ::std::ptr::write(&mut listener.notify, std::option::Option::Some($notify));
                            listener
                        };
                        $static_manager.$callback = builder.$callback;
                        $($(
                            $static_manager.$extra_callback_name = builder.$extra_callback_name;
                        )*)*
                    )*)*
                    &mut $static_manager
                }
            }
        )*

        $(
            $(
                $(
                    unsafe extern "C" fn $notify(listener: *mut $crate::wlroots_sys::wl_listener,
                                                 data: *mut $crate::libc::c_void) {
                        let manager: &mut $manager = &mut *container_of!(listener,
                                                                         $manager,
                                                                         $listener);
                        $crate::utils::handle_unwind(
                            ::std::panic::catch_unwind(
                                ::std::panic::AssertUnwindSafe(|| {
                                    (|$($func_arg: $func_type,)*| { $body })(manager, data)
                                })))
                    }
                )*
            )*
        )*
    }
}

/// A convenience macro designed for use with Handle types.
///
/// This allows you to avoid the rightward drift of death that is often found
/// with heavily nested callback systems.
///
/// Any `HandleResult`s are flattened and the first one encountered is immediately
/// returned before any of the `$body` code is executed.
///
/// Order of evaluation is from left to right. It is possible to refer to the previous
/// result, as commonly found in Lisp's `let*` macro.
///
/// An example of simple use:
///
/// ```rust,ignore
/// with_handles!([(compositor: {compositor}),
///    (output: {&mut result.output_handle})] => {
///    ...
/// })
/// ```
///
/// A more complex use:
///
/// ```rust,ignore
/// with_handles!([(shell: {shell_handle}),
///    // Notice how we use the previous result to get the surface.
///    (surface: {shell.surface_handle})] => {
///    ...
/// })
/// ```
///
#[cfg(feature = "unstable")]
#[macro_export]
macro_rules! with_handles {
    ([($handle_name: ident: $unhandle_name: block)] => $body: block) => {
        $unhandle_name.run(|$handle_name| {
            $body
        })
    };
    ([($handle_name1: ident: $unhandle_name1: block),
      ($handle_name2: ident: $unhandle_name2: block),
      $($rest: tt)*] => $body: block) => {
        $unhandle_name1.run(|$handle_name1| {
            with_handles!([($handle_name2: $unhandle_name2), $($rest)*] => $body)
        }).and_then(|n: $crate::utils::HandleResult<_>| n)
    };
    ([($handle_name: ident: $unhandle_name: block), $($rest: tt)*] => $body: block) => {
        $unhandle_name.run(|$handle_name| {
            with_handles!([$($rest)*] => $body)
        }).and_then(|n: $crate::utils::HandleResult<_>| n)
    };
}
<commit_msg>Fixed OutputLayout and Cursor not being documented.<commit_after>/// Gets the offset of a field. Used by container_of!
macro_rules! offset_of(
    ($ty:ty, $field:ident) => {
        &(*(0 as *const $ty)).$field as *const _ as usize
    }
);

/// Gets the parent struct from a pointer.
/// VERY unsafe. The parent struct _must_ be repr(C), and the
/// type passed to this macro _must_ match the type of the parent.
macro_rules! container_of (
    ($ptr: expr, $container: ty, $field: ident) => {
        ($ptr as *mut u8).offset(-(offset_of!($container, $field) as isize)) as *mut $container
    }
);

/// Iterates over a wl_list.
///
/// # Safety
/// It is not safe to delete an element while iterating over the list,
/// so don't do it!
macro_rules! wl_list_for_each {
    ($ptr: expr, $field: ident, ($pos: ident : $container: ty) => $body: block) => {
        let mut $pos: *mut $container;
        $pos = container_of!($ptr.next, $container, $field);
        loop {
            if &(*$pos).$field as *const _ == &$ptr as *const _ {
                break
            }
            { $body }
            $pos = container_of!((*$pos).$field.next, $container, $field);
        }
    }
}

/// Logs a message using wlroots' logging capability.
///
/// Example:
/// ```rust,no_run,ignore
/// #[macro_use]
/// use wlroots::log::{init_logging, L_DEBUG, L_ERROR};
///
/// // Call this once, at the beginning of your program.
/// init_logging(WLR_DEBUG, None);
///
/// wlr_log!(L_DEBUG, "Hello world");
/// wlr_log!(L_ERROR, "Could not {:#?} the {}", foo, bar);
/// ```
#[macro_export]
macro_rules! wlr_log {
    ($verb: expr, $($msg:tt)*) => {{
        /// Convert a literal string to a C string.
        /// Note: Does not check for internal nulls, nor does it do any conversions on
        /// the grapheme clustors. Just passes the bytes as is.
        /// So probably only works on ASCII.
        macro_rules! c_str {
            ($s:expr) => {
                concat!($s, "\0").as_ptr()
                    as *const $crate::wlroots_sys::libc::c_char
            }
        }
        use $crate::wlroots_sys::_wlr_log;
        use $crate::wlroots_sys::wlr_log_importance::*;
        use ::std::ffi::CString;
        unsafe {
            let fmt = CString::new(format!($($msg)*))
                .expect("Could not convert log message to C string");
            let raw = fmt.into_raw();
            _wlr_log($verb, c_str!("[%s:%lu] %s"),
                    c_str!(file!()), line!(), raw);
            // Deallocate string
            CString::from_raw(raw);
        }
    }}
}

/// Defines a new struct that contains a variable number of listeners that
/// will trigger unsafe user-defined callbacks.
///
/// The structure that is defined is repr(C), has one `data` field with the
/// given user type, and a field for each `$listener`.
///
/// Each `$listener` has a getter method that lets you get the pointer to the
/// listener. This method is unsafe, since it returns a raw pointer.
/// To use it correctly, you need to ensure that the data it refers to never
/// moves (e.g keep it in a box). The primary purpose of this method is to pass
/// the listener pointer to other methods to register it for a Wayland event.
/// **A listener can only be registered to one event at a time**.
///
/// Finally, it also takes in a body for each `$listener` that is called
/// every time the event that is later hooked up to it is fired.
/// This method is inherently unsafe, because the user data hasn't been cast
/// from the void pointer yet. It is the user's job to write this safely.
/// To highlight this fact, the body of the function must be prefixed with
/// `unsafe`.
///
/// # Example
/// ```rust,no_run,ignore
/// #[macro_use] extern crate wlroots;
/// extern crate wlroots_sys;
/// #[macro_use] extern crate wayland_sys;
/// extern crate libc;
///
/// use wlroots::InputDevice;
/// use wlroots_sys::wlr_input_device;
///
/// // Handles input addition and removal.
/// pub trait InputManagerHandler {
///     // Callback triggered when an input device is added.
///     fn input_added(&mut self, InputDevice);
/// }
///
/// wayland_listener!(
///     // The name of the structure that will be defined.
///     pub(crate) InputManager,
///     // The type that's stored in the `data` field.
///     // Note that we use a Box here to achieve dynamic dispatch,
///     // it's not required for this type to be in a box.
///     Box<InputManagerHandler>,
///     [
///         // Adds a new listener called `add_listener`.
///         // Adds an unsafe function called `add_notify` that is triggered
///         // whenever add_listener is activated from a Wayland event.
///         add_listener => add_notify: |this: &mut InputManager, data: *mut libc::c_void,| unsafe {
///             let ref mut manager = this.data;
///             // Call the method defined above, wrapping it in a safe interface.
///             // It is your job to ensure that the code in here doesn't trigger UB!
///             manager.input_added(InputDevice::from_ptr(data as *mut wlr_input_device))
///         };
///     ]
/// );
/// # fn main() {}
/// ```
///
/// # Unsafety
/// Note that the purpose of this macro is to make it easy to generate unsafe
/// boiler plate for using listeners with Rust data.
///
/// However, there are a few things this macro doesn't protect against.
///
/// First and foremost, the data cannot move. The listeners assume that the
/// structure will never move, so in order to defend against this the generated
/// `new` method returns a Box version. **Do not move out of the box**.
///
/// Second, this macro doesn't protect against the stored data being unsized.
/// Passing a pointer of unsized data to C is UB, don't do it.
macro_rules! wayland_listener {
    ($pub: vis $struct_name: ident, $data: ty, $([
        $($listener: ident => $listener_func: ident :
          |$($func_arg:ident: $func_type:ty,)*| unsafe $body: block;)*])+) => {
        #[repr(C)]
        $pub struct $struct_name {
            data: $data,
            $($($listener: $crate::wlroots_sys::wl_listener),*)*
        }

        impl $struct_name {
            pub(crate) fn new(data: $data) -> Box<$struct_name> {
                use $crate::wlroots_sys::server::WAYLAND_SERVER_HANDLE;
                Box::new($struct_name {
                    data,
                    $($($listener: unsafe {
                        // NOTE Rationale for zeroed memory:
                        // * Need to pass a pointer to wl_list_init
                        // * The list is initialized by Wayland, which doesn't "drop"
                        // * The listener is written to without dropping any of the data
                        let mut listener: $crate::wlroots_sys::wl_listener = ::std::mem::zeroed();
                        ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                      wl_list_init,
                                      &mut listener.link as *mut _ as _);
                        ::std::ptr::write(&mut listener.notify, Some($struct_name::$listener_func));
                        listener
                    }),*)*
                })
            }

            $($(pub(crate) unsafe extern "C" fn $listener(&mut self)
                                                   -> *mut $crate::wlroots_sys::wl_listener {
                &mut self.$listener as *mut _
            })*)*

            $($(pub(crate) unsafe extern "C" fn $listener_func(listener:
                                                        *mut $crate::wlroots_sys::wl_listener,
                                                        data: *mut $crate::libc::c_void) {
                let manager: &mut $struct_name = &mut (*container_of!(listener,
                                                                      $struct_name,
                                                                      $listener));
                $crate::utils::handle_unwind(
                    ::std::panic::catch_unwind(
                        ::std::panic::AssertUnwindSafe(|| {
                            (|$($func_arg: $func_type,)*| { $body })(manager, data)
                        })));
            })*)*
        }
    }
}

macro_rules! wayland_listener_static {
    (static mut $static_manager: ident;
     $(($manager: ident, $builder: ident):
       $([
           $(
               $([$($extra_callback_name: ident: $extra_callback_type: ty),+])*
               ($fn_type: ty, $listener: ident, $builder_func: ident) => ($notify: ident, $callback: ident):
               |$($func_arg: ident: $func_type: ty,)*| unsafe $body: block;
           )*
       ])+
     )+
    ) => {
        $(
            #[derive(Default)]
            #[allow(dead_code)]
            /// A builder of static functions to manage and create resources.
            ///
            /// Implement the functions with the necessary signature, pass them
            /// to the builder, and then give the builder to the necessary
            /// structure in order to utilize them (usually it's `compositor::Builder`).
            pub struct $builder {
                $($(pub(crate) $callback: ::std::option::Option<$fn_type>,)*
                  $($($($extra_callback_name: ::std::option::Option<$extra_callback_type>,)*)*)*)*
            }

            impl $builder {
                $($(
                    /// Uses the provided callback as the receiver for the
                    /// event the type signature describes.
                    pub fn $builder_func(mut self, $callback: $fn_type) -> Self {
                        self.$callback = ::std::option::Option::Some($callback);
                        self
                    }
                    $($(
                        /// Uses the provided callback as the receiver for the
                        /// event the type signature describes.
                        pub fn $extra_callback_name(mut self, $extra_callback_name: $extra_callback_type) -> Self {
                            self.$extra_callback_name = ::std::option::Option::Some($extra_callback_name);
                            self
                        }
                    )*)*
                )*)*
            }
        )*

        $(
            #[repr(C)]
            pub(crate) struct $manager {
                $($(
                    pub(crate) $listener: $crate::wlroots_sys::wl_listener,
                    $callback: ::std::option::Option<$fn_type>,
                    $($($extra_callback_name: ::std::option::Option<$extra_callback_type>),*)*
                )*)*
            }

            pub(crate) static mut $static_manager: $manager = $manager {
                $($(
                    $listener: $crate::wlroots_sys::wl_listener {
                        link: {
                            $crate::wlroots_sys::wl_list {
                                prev: ::std::ptr::null_mut(),
                                next: ::std::ptr::null_mut()}},
                        notify: ::std::option::Option::None },
                    $callback: ::std::option::Option::None,
                    $($($extra_callback_name: ::std::option::Option::None),*)*
                )*)*
            };

            impl $manager {
                /// Sets the functions on the builder as the global manager functions.
                ///
                /// # Safety
                /// Returns a mutable reference to static data, which is unsafe to have
                /// multiple of. Do all your mutation through this reference and don't
                /// call this function multiple times.
                pub(crate) unsafe fn build(builder: $builder) -> &'static mut $manager {
                    $($(
                        $static_manager.$listener = {
                            // NOTE Rationale for zeroed memory:
                            // * Need to pass a pointer to wl_list_init
                            // * The list is initialized by Wayland, which doesn't "drop"
                            // * The listener is written to without dropping any of the data
                            let mut listener: $crate::wlroots_sys::wl_listener = ::std::mem::zeroed();
                            use $crate::wlroots_sys::server::WAYLAND_SERVER_HANDLE;
                            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                          wl_list_init,
                                          &mut listener.link as *mut _ as _);
                            ::std::ptr::write(&mut listener.notify, std::option::Option::Some($notify));
                            listener
                        };
                        $static_manager.$callback = builder.$callback;
                        $($(
                            $static_manager.$extra_callback_name = builder.$extra_callback_name;
                        )*)*
                    )*)*
                    &mut $static_manager
                }
            }
        )*

        $(
            $(
                $(
                    unsafe extern "C" fn $notify(listener: *mut $crate::wlroots_sys::wl_listener,
                                                 data: *mut $crate::libc::c_void) {
                        let manager: &mut $manager = &mut *container_of!(listener,
                                                                         $manager,
                                                                         $listener);
                        $crate::utils::handle_unwind(
                            ::std::panic::catch_unwind(
                                ::std::panic::AssertUnwindSafe(|| {
                                    (|$($func_arg: $func_type,)*| { $body })(manager, data)
                                })))
                    }
                )*
            )*
        )*
    }
}

/// A convenience macro designed for use with Handle types.
///
/// This allows you to avoid the rightward drift of death that is often found
/// with heavily nested callback systems.
///
/// Any `HandleResult`s are flattened and the first one encountered is immediately
/// returned before any of the `$body` code is executed.
///
/// Order of evaluation is from left to right. It is possible to refer to the previous
/// result, as commonly found in Lisp's `let*` macro.
///
/// An example of simple use:
///
/// ```rust,ignore
/// with_handles!([(compositor: {compositor}),
///    (output: {&mut result.output_handle})] => {
///    ...
/// })
/// ```
///
/// A more complex use:
///
/// ```rust,ignore
/// with_handles!([(shell: {shell_handle}),
///    // Notice how we use the previous result to get the surface.
///    (surface: {shell.surface_handle})] => {
///    ...
/// })
/// ```
///
#[cfg(feature = "unstable")]
#[macro_export]
macro_rules! with_handles {
    ([($handle_name: ident: $unhandle_name: block)] => $body: block) => {
        $unhandle_name.run(|$handle_name| {
            $body
        })
    };
    ([($handle_name1: ident: $unhandle_name1: block),
      ($handle_name2: ident: $unhandle_name2: block),
      $($rest: tt)*] => $body: block) => {
        $unhandle_name1.run(|$handle_name1| {
            with_handles!([($handle_name2: $unhandle_name2), $($rest)*] => $body)
        }).and_then(|n: $crate::utils::HandleResult<_>| n)
    };
    ([($handle_name: ident: $unhandle_name: block), $($rest: tt)*] => $body: block) => {
        $unhandle_name.run(|$handle_name| {
            with_handles!([$($rest)*] => $body)
        }).and_then(|n: $crate::utils::HandleResult<_>| n)
    };
}
<|endoftext|>


<commit_before>extern crate csv;
extern crate rustc_serialize;

mod distance;

use std::fs::File;
use csv::Reader;
use distance::*;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

#[derive(RustcDecodable)]
struct User {
    id: u32,
    location: String,
    age: u32,
}

#[derive(RustcDecodable)]
struct Book {
    isbn: String,
    title: String,
    author: String,
    pub_year: u32,
    publisher: String,
}

#[derive(RustcDecodable)]
struct Rating {
    user_id: u32,
    book_isbn: String,
    rating: u32,
}

fn distance(db: &mut HashMap<u32, HashMap<String, u32>>,
            a: u32,
            b: u32,
            func: fn(&Vec<f32>, &Vec<f32>) -> f32)
            -> f32 {
    let mut vec_a = Vec::new();
    let mut vec_b = Vec::new();

    match db.get(&a) {
        Some(mut a_ratings) => {
            for (isbn_a, &rating_a) in a_ratings.iter() {
                // print!("{} ", rating_a);
                if let Some(b_ratings) = db.get(&b) {
                    if let Some(val_b) = b_ratings.get(isbn_a) {
                        // print!("{} ", val_b);
                        vec_a.push(rating_a as f32);
                        vec_b.push(rating_a as f32);
                    } else {
                        vec_a.push(rating_a as f32);
                        vec_b.push(0.0);
                    }
                } else {
                    panic!("b is not found!");
                }
            }
        }
        None => {}
    }

    match db.get(&b) {
        Some(mut b_ratings) => {
            for (isbn_b, &rating_b) in b_ratings.iter() {
                if let Some(a_ratings) = db.get(&a) {}
                else {
                        vec_b.push(rating_b as f32);
                        vec_b.push(0.0);
                }
            }
        }
        None => {}
    }

    // println!("{:?}\n{:?}", vec_a, vec_b);

    // let a_ratings = db.get_mut(&a);
    // let b_ratings = db.get_mut(&b);

    // let mut vec_a = Vec::new();
    // let mut vec_b = Vec::new();

    // for (isbn_a, &rating_a) in a_ratings.iter() {
    //     if let Some(val_b) = vec_b.get_mut(isbn_a) {
    //         vec_a.push(rating_a as f32);
    //         vec_b.push(rating_a as f32);
    //     } else {
    //         vec_a.push(rating_a as f32);
    //         vec_b.push(0.0);
    //     }
    // }

    // for (&isbn_b, &rating_b) in b_ratings.iter() {
    //     match vec_a.get(isbn_b) {
    //         Some(val_b) => {}
    //         None => {
    //             vec_b.push(rating_b as f32);
    //             vec_a.push(0.0);
    //         }
    //     }
    // }

    func(&vec_a, &vec_b)
}

fn init_db_reader(path: &str) -> Reader<File> {
    let rdr = csv::Reader::from_file(path).unwrap();
    rdr
}

fn load_book_ratings() {
    /*********************LOAD RATINGS*********************/
    let mut rdr = init_db_reader("./data/BX-Dump/BX-Book-Ratings.csv").has_headers(false);
    let mut ratings: HashMap<u32, HashMap<String, u32>> = HashMap::new();

    let mut i = 0;
    for record in rdr.decode() {
        if i > 54000 {
            break;
        }
        i += 1;
        let rating: Rating = record.unwrap();

        match ratings.entry(rating.user_id) {
            Vacant(entry) => {
                let mut user_ratings = HashMap::new();
                user_ratings.insert(rating.book_isbn, rating.rating);
                entry.insert(user_ratings);
            }
            Occupied(entry) => {
                entry.into_mut().insert(rating.book_isbn, rating.rating);
            }
        }
    }

    println!("{}", distance(&mut ratings, 11676, 278418, cosine_dist));

    /*********************LOAD USERS*********************/
    // let mut rdr = init_db("./data/BX-Dump/BX-Users.csv").has_headers(false);

    // let mut i = 0;
    // for record in rdr.decode() {
    //     if i > 10 {
    //         break;
    //     }
    //     let user: User = record.unwrap();
    //     println!("{}: {} [{}]", user.id, user.location, user.age);

    //     i += 1;
    // }
    /****************************************************/
}

fn main() {
    load_book_ratings();
    println!("Hello, world!");
}
<commit_msg>Prettifying some code xD<commit_after>extern crate csv;
extern crate test;
extern crate rustc_serialize;

mod distance;

use std::fs::File;
use csv::Reader;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use distance::{manhattan_dist, pearson_coef, cosine_dist};
use test::Bencher;

#[derive(RustcDecodable)]
struct User {
    id: u32,
    location: String,
    age: u32,
}

#[derive(RustcDecodable)]
struct Book {
    isbn: String,
    title: String,
    author: String,
    pub_year: u32,
    publisher: String,
}

#[derive(RustcDecodable)]
struct Rating {
    user_id: u32,
    book_isbn: String,
    rating: u32,
}

fn distance(db: &mut HashMap<u32, HashMap<String, u32>>,
            a: u32,
            b: u32,
            func: fn(&Vec<f32>, &Vec<f32>) -> f32)
            -> f32 {
    let mut vec_a = Vec::new();
    let mut vec_b = Vec::new();

    match db.get(&a) {
        Some(mut a_ratings) => {
            for (isbn_a, &rating_a) in a_ratings.iter() {
                // print!("{} ", rating_a);
                if let Some(b_ratings) = db.get(&b) {
                    if let Some(rating_b) = b_ratings.get(isbn_a) {
                        // print!("{} ", val_b);
                        vec_a.push(rating_a as f32);
                        vec_b.push(*rating_b as f32);
                    } else {
                        vec_a.push(rating_a as f32);
                        vec_b.push(0.0);
                    }
                } else {
                    panic!("b is not found!");
                }
            }
        }
        None => {}
    }

    match db.get(&b) {
        Some(mut b_ratings) => {
            for (isbn_b, &rating_b) in b_ratings.iter() {
                if let Some(a_ratings) = db.get(&a) {
                    if let Some(_) = a_ratings.get(isbn_b) {
                    } else {
                        vec_b.push(rating_b as f32);
                        vec_a.push(0.0);
                    }
                } else {
                    panic!("a is not found!");
                }
            }
        }
        None => {}
    }

    func(&vec_a, &vec_b)
}

fn init_db_reader(path: &str) -> Reader<File> {
    let rdr = csv::Reader::from_file(path).unwrap();
    rdr
}

fn load_book_ratings() {
    /*********************LOAD RATINGS*********************/
    let mut rdr = init_db_reader("./data/BX-Dump/BX-Book-Ratings.csv").has_headers(false);
    let mut ratings: HashMap<u32, HashMap<String, u32>> = HashMap::new();

    // let mut i = 0;
    for record in rdr.decode() {
        // if i > 54000 {
        //     break;
        // }
        // i += 1;
        let rating: Rating = record.unwrap();

        match ratings.entry(rating.user_id) {
            Vacant(entry) => {
                let mut user_ratings = HashMap::new();
                user_ratings.insert(rating.book_isbn, rating.rating);
                entry.insert(user_ratings);
            }
            Occupied(entry) => {
                entry.into_mut().insert(rating.book_isbn, rating.rating);
            }
        }
    }

    println!("{}", distance(&mut ratings, 11676, 278418, cosine_dist));
    println!("{}", distance(&mut ratings, 11676, 278418, manhattan_dist));
    println!("{}", distance(&mut ratings, 11676, 278418, pearson_coef));

    /*********************LOAD USERS*********************/
    /****************************************************/
}

fn main() {
    load_book_ratings();
    println!("Hello, world!");
}
<|endoftext|>


<commit_before>use byteorder::{ByteOrder, NativeEndian, ReadBytesExt, WriteBytesExt};
use std::collections::{btree_map, BTreeMap, HashMap};
use std::collections::Bound::{Included, Excluded};
use std::mem;
use std::ptr;

use error::{EvalError, EvalResult};
use primval::PrimVal;

pub struct Memory {
    alloc_map: HashMap<u64, Allocation>,
    next_id: u64,
    pub pointer_size: usize,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AllocId(u64);

#[derive(Debug)]
pub struct Allocation {
    pub bytes: Vec<u8>,
    pub relocations: BTreeMap<usize, AllocId>,
    // TODO(tsion): undef mask
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Pointer {
    pub alloc_id: AllocId,
    pub offset: usize,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct FieldRepr {
    pub offset: usize,
    pub size: usize,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Repr {
    /// Representation for a non-aggregate type such as a boolean, integer, character or pointer.
    Primitive {
        size: usize
    },

    /// The representation for aggregate types including structs, enums, and tuples.
    Aggregate {
        /// The size of the discriminant (an integer). Should be between 0 and 8. Always 0 for
        /// structs and tuples.
        discr_size: usize,

        /// The size of the entire aggregate, including the discriminant.
        size: usize,

        /// The representations of the contents of each variant.
        variants: Vec<Vec<FieldRepr>>,
    },

    Array {
        elem_size: usize,

        /// Number of elements.
        length: usize,
    },
}

impl Memory {
    pub fn new() -> Self {
        Memory {
            alloc_map: HashMap::new(),
            next_id: 0,

            // TODO(tsion): Should this be host's or target's usize?
            pointer_size: mem::size_of::<usize>(),
        }
    }

    pub fn allocate(&mut self, size: usize) -> Pointer {
        let id = AllocId(self.next_id);
        let alloc = Allocation { bytes: vec![0; size], relocations: BTreeMap::new() };
        self.alloc_map.insert(self.next_id, alloc);
        self.next_id += 1;
        Pointer {
            alloc_id: id,
            offset: 0,
        }
    }

    pub fn get(&self, id: AllocId) -> EvalResult<&Allocation> {
        self.alloc_map.get(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    pub fn get_mut(&mut self, id: AllocId) -> EvalResult<&mut Allocation> {
        self.alloc_map.get_mut(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    fn get_bytes(&self, ptr: Pointer, size: usize) -> EvalResult<&[u8]> {
        try!(self.check_readable_bytes(ptr, size));
        try!(self.get(ptr.alloc_id)).checked_slice(ptr.offset, size)
    }

    fn get_bytes_mut(&mut self, ptr: Pointer, size: usize) -> EvalResult<&mut [u8]> {
        try!(self.clear_relocations(ptr, size));
        try!(self.get_mut(ptr.alloc_id)).checked_slice_mut(ptr.offset, size)
    }

    fn check_readable_bytes(&self, ptr: Pointer, size: usize) -> EvalResult<()> {
        if try!(self.relocations(ptr, size)).count() == 0 {
            // TODO(tsion): Track and check for undef bytes.
            Ok(())
        } else {
            Err(EvalError::ReadPointerAsBytes)
        }
    }

    fn relocations(&self, ptr: Pointer, size: usize)
        -> EvalResult<btree_map::Range<usize, AllocId>>
    {
        let start = ptr.offset.saturating_sub(self.pointer_size - 1);
        let end = ptr.offset + size;
        let alloc = try!(self.get(ptr.alloc_id));
        Ok(alloc.relocations.range(Included(&start), Excluded(&end)))
    }

    fn check_relocation_edges(&self, ptr: Pointer, size: usize) -> EvalResult<()> {
        let overlapping_start = try!(self.relocations(ptr, 0)).count();
        let overlapping_end = try!(self.relocations(ptr.offset(size as isize), 0)).count();
        if overlapping_start + overlapping_end == 0 {
            Ok(())
        } else {
            Err(EvalError::ReadPointerAsBytes)
        }
    }

    fn clear_relocations(&mut self, ptr: Pointer, size: usize) -> EvalResult<()> {
        let keys: Vec<_> = try!(self.relocations(ptr, size)).map(|(&k, _)| k).collect();
        let alloc = try!(self.get_mut(ptr.alloc_id));
        for k in keys {
            alloc.relocations.remove(&k);
        }
        Ok(())
    }

    fn copy_relocations(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<()> {
        let relocations: Vec<_> = try!(self.get_mut(src.alloc_id)).relocations
            .range(Included(&src.offset), Excluded(&(src.offset + size)))
            .map(|(&offset, &alloc_id)| {
                // Update relocation offsets for the new positions in the destination allocation.
                (offset + dest.offset - src.offset, alloc_id)
            }).collect();
        try!(self.get_mut(dest.alloc_id)).relocations.extend(relocations);
        Ok(())
    }

    pub fn copy(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<()> {
        // TODO(tsion): Track and check for undef bytes.
        try!(self.check_relocation_edges(src, size));

        let src_bytes = {
            let alloc = try!(self.get(src.alloc_id));
            try!(alloc.checked_slice(src.offset, size)).as_ptr()
        };
        let dest_bytes = try!(self.get_bytes_mut(dest, size)).as_mut_ptr();

        // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
        // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
        // `dest` could possibly overlap.
        unsafe {
            if src.alloc_id == dest.alloc_id {
                ptr::copy(src_bytes, dest_bytes, size);
            } else {
                ptr::copy_nonoverlapping(src_bytes, dest_bytes, size);
            }
        }

        self.copy_relocations(src, dest, size)
    }

    pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<()> {
        self.get_bytes_mut(ptr, src.len()).map(|dest| dest.clone_from_slice(src))
    }

    pub fn read_ptr(&self, ptr: Pointer) -> EvalResult<Pointer> {
        let alloc = try!(self.get(ptr.alloc_id));
        let mut bytes = try!(alloc.checked_slice(ptr.offset, self.pointer_size));
        let offset = bytes.read_uint::<NativeEndian>(self.pointer_size).unwrap() as usize;

        match alloc.relocations.get(&ptr.offset) {
            Some(&alloc_id) => Ok(Pointer { alloc_id: alloc_id, offset: offset }),
            None => Err(EvalError::ReadBytesAsPointer),
        }
    }

    pub fn write_ptr(&mut self, dest: Pointer, ptr: Pointer) -> EvalResult<()> {
        {
            let size = self.pointer_size;
            let mut bytes = try!(self.get_bytes_mut(dest, size));
            bytes.write_uint::<NativeEndian>(ptr.offset as u64, size).unwrap();
        }
        try!(self.get_mut(dest.alloc_id)).relocations.insert(dest.offset, ptr.alloc_id);
        Ok(())
    }

    pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<()> {
        let pointer_size = self.pointer_size;
        match val {
            PrimVal::Bool(b) => self.write_bool(ptr, b),
            PrimVal::I8(n)   => self.write_int(ptr, n as i64, 1),
            PrimVal::I16(n)  => self.write_int(ptr, n as i64, 2),
            PrimVal::I32(n)  => self.write_int(ptr, n as i64, 4),
            PrimVal::I64(n)  => self.write_int(ptr, n as i64, 8),
            PrimVal::U8(n)   => self.write_uint(ptr, n as u64, 1),
            PrimVal::U16(n)  => self.write_uint(ptr, n as u64, 2),
            PrimVal::U32(n)  => self.write_uint(ptr, n as u64, 4),
            PrimVal::U64(n)  => self.write_uint(ptr, n as u64, 8),
            PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, pointer_size),
            PrimVal::AbstractPtr(_p) => unimplemented!(),
        }
    }

    pub fn read_bool(&self, ptr: Pointer) -> EvalResult<bool> {
        let bytes = try!(self.get_bytes(ptr, 1));
        match bytes[0] {
            0 => Ok(false),
            1 => Ok(true),
            _ => Err(EvalError::InvalidBool),
        }
    }

    pub fn write_bool(&mut self, ptr: Pointer, b: bool) -> EvalResult<()> {
        self.get_bytes_mut(ptr, 1).map(|bytes| bytes[0] = b as u8)
    }

    pub fn read_int(&self, ptr: Pointer, size: usize) -> EvalResult<i64> {
        self.get_bytes(ptr, size).map(|mut b| b.read_int::<NativeEndian>(size).unwrap())
    }

    pub fn write_int(&mut self, ptr: Pointer, n: i64, size: usize) -> EvalResult<()> {
        self.get_bytes_mut(ptr, size).map(|mut b| b.write_int::<NativeEndian>(n, size).unwrap())
    }

    pub fn read_uint(&self, ptr: Pointer, size: usize) -> EvalResult<u64> {
        self.get_bytes(ptr, size).map(|mut b| b.read_uint::<NativeEndian>(size).unwrap())
    }

    pub fn write_uint(&mut self, ptr: Pointer, n: u64, size: usize) -> EvalResult<()> {
        self.get_bytes_mut(ptr, size).map(|mut b| b.write_uint::<NativeEndian>(n, size).unwrap())
    }

    pub fn read_isize(&self, ptr: Pointer) -> EvalResult<i64> {
        self.read_int(ptr, self.pointer_size)
    }

    pub fn write_isize(&mut self, ptr: Pointer, n: i64) -> EvalResult<()> {
        let size = self.pointer_size;
        self.write_int(ptr, n, size)
    }

    pub fn read_usize(&self, ptr: Pointer) -> EvalResult<u64> {
        self.read_uint(ptr, self.pointer_size)
    }

    pub fn write_usize(&mut self, ptr: Pointer, n: u64) -> EvalResult<()> {
        let size = self.pointer_size;
        self.write_uint(ptr, n, size)
    }
}

impl Allocation {
    fn checked_slice(&self, offset: usize, size: usize) -> EvalResult<&[u8]> {
        let start = offset;
        let end = start + size;
        if start <= self.bytes.len() && end <= self.bytes.len() {
            Ok(&self.bytes[start..end])
        } else {
            Err(EvalError::PointerOutOfBounds)
        }
    }

    fn checked_slice_mut(&mut self, offset: usize, size: usize) -> EvalResult<&mut [u8]> {
        let start = offset;
        let end = start + size;
        if start <= self.bytes.len() && end <= self.bytes.len() {
            Ok(&mut self.bytes[start..end])
        } else {
            Err(EvalError::PointerOutOfBounds)
        }
    }
}

impl Pointer {
    pub fn offset(self, i: isize) -> Self {
        Pointer { offset: (self.offset as isize + i) as usize, ..self }
    }
}

impl Repr {
    pub fn size(&self) -> usize {
        match *self {
            Repr::Primitive { size } => size,
            Repr::Aggregate { size, .. } => size,
            Repr::Array { elem_size, length } => elem_size * length,
        }
    }
}
<commit_msg>Use Box<[u8]> instead of Vec<u8> for allocations.<commit_after>use byteorder::{ByteOrder, NativeEndian, ReadBytesExt, WriteBytesExt};
use std::collections::{btree_map, BTreeMap, HashMap};
use std::collections::Bound::{Included, Excluded};
use std::mem;
use std::ptr;

use error::{EvalError, EvalResult};
use primval::PrimVal;

pub struct Memory {
    alloc_map: HashMap<u64, Allocation>,
    next_id: u64,
    pub pointer_size: usize,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AllocId(u64);

#[derive(Debug)]
pub struct Allocation {
    pub bytes: Box<[u8]>,
    pub relocations: BTreeMap<usize, AllocId>,
    // TODO(tsion): undef mask
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Pointer {
    pub alloc_id: AllocId,
    pub offset: usize,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct FieldRepr {
    pub offset: usize,
    pub size: usize,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Repr {
    /// Representation for a non-aggregate type such as a boolean, integer, character or pointer.
    Primitive {
        size: usize
    },

    /// The representation for aggregate types including structs, enums, and tuples.
    Aggregate {
        /// The size of the discriminant (an integer). Should be between 0 and 8. Always 0 for
        /// structs and tuples.
        discr_size: usize,

        /// The size of the entire aggregate, including the discriminant.
        size: usize,

        /// The representations of the contents of each variant.
        variants: Vec<Vec<FieldRepr>>,
    },

    Array {
        elem_size: usize,

        /// Number of elements.
        length: usize,
    },
}

impl Memory {
    pub fn new() -> Self {
        Memory {
            alloc_map: HashMap::new(),
            next_id: 0,

            // TODO(tsion): Should this be host's or target's usize?
            pointer_size: mem::size_of::<usize>(),
        }
    }

    pub fn allocate(&mut self, size: usize) -> Pointer {
        let id = AllocId(self.next_id);
        let alloc = Allocation {
            bytes: vec![0; size].into_boxed_slice(),
            relocations: BTreeMap::new(),
        };
        self.alloc_map.insert(self.next_id, alloc);
        self.next_id += 1;
        Pointer {
            alloc_id: id,
            offset: 0,
        }
    }

    pub fn get(&self, id: AllocId) -> EvalResult<&Allocation> {
        self.alloc_map.get(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    pub fn get_mut(&mut self, id: AllocId) -> EvalResult<&mut Allocation> {
        self.alloc_map.get_mut(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    fn get_bytes(&self, ptr: Pointer, size: usize) -> EvalResult<&[u8]> {
        try!(self.check_readable_bytes(ptr, size));
        try!(self.get(ptr.alloc_id)).checked_slice(ptr.offset, size)
    }

    fn get_bytes_mut(&mut self, ptr: Pointer, size: usize) -> EvalResult<&mut [u8]> {
        try!(self.clear_relocations(ptr, size));
        try!(self.get_mut(ptr.alloc_id)).checked_slice_mut(ptr.offset, size)
    }

    fn check_readable_bytes(&self, ptr: Pointer, size: usize) -> EvalResult<()> {
        if try!(self.relocations(ptr, size)).count() == 0 {
            // TODO(tsion): Track and check for undef bytes.
            Ok(())
        } else {
            Err(EvalError::ReadPointerAsBytes)
        }
    }

    fn relocations(&self, ptr: Pointer, size: usize)
        -> EvalResult<btree_map::Range<usize, AllocId>>
    {
        let start = ptr.offset.saturating_sub(self.pointer_size - 1);
        let end = ptr.offset + size;
        let alloc = try!(self.get(ptr.alloc_id));
        Ok(alloc.relocations.range(Included(&start), Excluded(&end)))
    }

    fn check_relocation_edges(&self, ptr: Pointer, size: usize) -> EvalResult<()> {
        let overlapping_start = try!(self.relocations(ptr, 0)).count();
        let overlapping_end = try!(self.relocations(ptr.offset(size as isize), 0)).count();
        if overlapping_start + overlapping_end == 0 {
            Ok(())
        } else {
            Err(EvalError::ReadPointerAsBytes)
        }
    }

    fn clear_relocations(&mut self, ptr: Pointer, size: usize) -> EvalResult<()> {
        let keys: Vec<_> = try!(self.relocations(ptr, size)).map(|(&k, _)| k).collect();
        let alloc = try!(self.get_mut(ptr.alloc_id));
        for k in keys {
            alloc.relocations.remove(&k);
        }
        Ok(())
    }

    fn copy_relocations(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<()> {
        let relocations: Vec<_> = try!(self.get_mut(src.alloc_id)).relocations
            .range(Included(&src.offset), Excluded(&(src.offset + size)))
            .map(|(&offset, &alloc_id)| {
                // Update relocation offsets for the new positions in the destination allocation.
                (offset + dest.offset - src.offset, alloc_id)
            }).collect();
        try!(self.get_mut(dest.alloc_id)).relocations.extend(relocations);
        Ok(())
    }

    pub fn copy(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<()> {
        // TODO(tsion): Track and check for undef bytes.
        try!(self.check_relocation_edges(src, size));

        let src_bytes = {
            let alloc = try!(self.get(src.alloc_id));
            try!(alloc.checked_slice(src.offset, size)).as_ptr()
        };
        let dest_bytes = try!(self.get_bytes_mut(dest, size)).as_mut_ptr();

        // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
        // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
        // `dest` could possibly overlap.
        unsafe {
            if src.alloc_id == dest.alloc_id {
                ptr::copy(src_bytes, dest_bytes, size);
            } else {
                ptr::copy_nonoverlapping(src_bytes, dest_bytes, size);
            }
        }

        self.copy_relocations(src, dest, size)
    }

    pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<()> {
        self.get_bytes_mut(ptr, src.len()).map(|dest| dest.clone_from_slice(src))
    }

    pub fn read_ptr(&self, ptr: Pointer) -> EvalResult<Pointer> {
        let alloc = try!(self.get(ptr.alloc_id));
        let mut bytes = try!(alloc.checked_slice(ptr.offset, self.pointer_size));
        let offset = bytes.read_uint::<NativeEndian>(self.pointer_size).unwrap() as usize;

        match alloc.relocations.get(&ptr.offset) {
            Some(&alloc_id) => Ok(Pointer { alloc_id: alloc_id, offset: offset }),
            None => Err(EvalError::ReadBytesAsPointer),
        }
    }

    pub fn write_ptr(&mut self, dest: Pointer, ptr: Pointer) -> EvalResult<()> {
        {
            let size = self.pointer_size;
            let mut bytes = try!(self.get_bytes_mut(dest, size));
            bytes.write_uint::<NativeEndian>(ptr.offset as u64, size).unwrap();
        }
        try!(self.get_mut(dest.alloc_id)).relocations.insert(dest.offset, ptr.alloc_id);
        Ok(())
    }

    pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<()> {
        let pointer_size = self.pointer_size;
        match val {
            PrimVal::Bool(b) => self.write_bool(ptr, b),
            PrimVal::I8(n)   => self.write_int(ptr, n as i64, 1),
            PrimVal::I16(n)  => self.write_int(ptr, n as i64, 2),
            PrimVal::I32(n)  => self.write_int(ptr, n as i64, 4),
            PrimVal::I64(n)  => self.write_int(ptr, n as i64, 8),
            PrimVal::U8(n)   => self.write_uint(ptr, n as u64, 1),
            PrimVal::U16(n)  => self.write_uint(ptr, n as u64, 2),
            PrimVal::U32(n)  => self.write_uint(ptr, n as u64, 4),
            PrimVal::U64(n)  => self.write_uint(ptr, n as u64, 8),
            PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, pointer_size),
            PrimVal::AbstractPtr(_p) => unimplemented!(),
        }
    }

    pub fn read_bool(&self, ptr: Pointer) -> EvalResult<bool> {
        let bytes = try!(self.get_bytes(ptr, 1));
        match bytes[0] {
            0 => Ok(false),
            1 => Ok(true),
            _ => Err(EvalError::InvalidBool),
        }
    }

    pub fn write_bool(&mut self, ptr: Pointer, b: bool) -> EvalResult<()> {
        self.get_bytes_mut(ptr, 1).map(|bytes| bytes[0] = b as u8)
    }

    pub fn read_int(&self, ptr: Pointer, size: usize) -> EvalResult<i64> {
        self.get_bytes(ptr, size).map(|mut b| b.read_int::<NativeEndian>(size).unwrap())
    }

    pub fn write_int(&mut self, ptr: Pointer, n: i64, size: usize) -> EvalResult<()> {
        self.get_bytes_mut(ptr, size).map(|mut b| b.write_int::<NativeEndian>(n, size).unwrap())
    }

    pub fn read_uint(&self, ptr: Pointer, size: usize) -> EvalResult<u64> {
        self.get_bytes(ptr, size).map(|mut b| b.read_uint::<NativeEndian>(size).unwrap())
    }

    pub fn write_uint(&mut self, ptr: Pointer, n: u64, size: usize) -> EvalResult<()> {
        self.get_bytes_mut(ptr, size).map(|mut b| b.write_uint::<NativeEndian>(n, size).unwrap())
    }

    pub fn read_isize(&self, ptr: Pointer) -> EvalResult<i64> {
        self.read_int(ptr, self.pointer_size)
    }

    pub fn write_isize(&mut self, ptr: Pointer, n: i64) -> EvalResult<()> {
        let size = self.pointer_size;
        self.write_int(ptr, n, size)
    }

    pub fn read_usize(&self, ptr: Pointer) -> EvalResult<u64> {
        self.read_uint(ptr, self.pointer_size)
    }

    pub fn write_usize(&mut self, ptr: Pointer, n: u64) -> EvalResult<()> {
        let size = self.pointer_size;
        self.write_uint(ptr, n, size)
    }
}

impl Allocation {
    fn checked_slice(&self, offset: usize, size: usize) -> EvalResult<&[u8]> {
        let start = offset;
        let end = start + size;
        if start <= self.bytes.len() && end <= self.bytes.len() {
            Ok(&self.bytes[start..end])
        } else {
            Err(EvalError::PointerOutOfBounds)
        }
    }

    fn checked_slice_mut(&mut self, offset: usize, size: usize) -> EvalResult<&mut [u8]> {
        let start = offset;
        let end = start + size;
        if start <= self.bytes.len() && end <= self.bytes.len() {
            Ok(&mut self.bytes[start..end])
        } else {
            Err(EvalError::PointerOutOfBounds)
        }
    }
}

impl Pointer {
    pub fn offset(self, i: isize) -> Self {
        Pointer { offset: (self.offset as isize + i) as usize, ..self }
    }
}

impl Repr {
    pub fn size(&self) -> usize {
        match *self {
            Repr::Primitive { size } => size,
            Repr::Aggregate { size, .. } => size,
            Repr::Array { elem_size, length } => elem_size * length,
        }
    }
}
<|endoftext|>


<commit_before>//! Posix Message Queue functions
//!
//! [Further reading and details on the C API](http://man7.org/linux/man-pages/man7/mq_overview.7.html)

use {Errno, Result};

use libc::{self, c_char,c_long,mode_t,mqd_t,size_t};
use std::ffi::CString;
use sys::stat::Mode;
use std::mem;

libc_bitflags!{
    flags MQ_OFlag: libc::c_int {
        O_RDONLY,
        O_WRONLY,
        O_RDWR,
        O_CREAT,
        O_EXCL,
        O_NONBLOCK,
        O_CLOEXEC,
    }
}

libc_bitflags!{
    flags FdFlag: libc::c_int {
        FD_CLOEXEC,
    }
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct MqAttr {
    mq_attr: libc::mq_attr
}

impl PartialEq<MqAttr> for MqAttr {
    fn eq(&self, other: &MqAttr) -> bool {
        let self_attr = self.mq_attr;
        let other_attr = other.mq_attr;
        self_attr.mq_flags == other_attr.mq_flags &&
            self_attr.mq_maxmsg == other_attr.mq_maxmsg &&
            self_attr.mq_msgsize == other_attr.mq_msgsize &&
            self_attr.mq_curmsgs == other_attr.mq_curmsgs
    }
}

impl MqAttr {
    pub fn new(mq_flags: c_long, mq_maxmsg: c_long, mq_msgsize: c_long, mq_curmsgs: c_long) -> MqAttr {
        let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
        attr.mq_flags = mq_flags;
        attr.mq_maxmsg = mq_maxmsg;
        attr.mq_msgsize = mq_msgsize;
        attr.mq_curmsgs = mq_curmsgs;
        MqAttr{mq_attr: attr}
    }

    pub fn flags(&self) -> c_long {
        self.mq_attr.mq_flags
    }
}

pub fn mq_open(name: &CString, oflag: MQ_OFlag, mode: Mode, attr: Option<&MqAttr>) -> Result<mqd_t> {
    let res = match attr {
        Some(mq_attr) => {
            unsafe { libc::mq_open(name.as_ptr(), oflag.bits(), mode.bits() as mode_t, &mq_attr.mq_attr as *const libc::mq_attr) }
        },
        None => {
            unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) }
        }
    };
    Errno::result(res)
}

pub fn mq_unlink(name: &CString) -> Result<()> {
    let res = unsafe { libc::mq_unlink(name.as_ptr()) };
    Errno::result(res).map(drop)
}

pub fn mq_close(mqdes: mqd_t) -> Result<()>  {
    let res = unsafe { libc::mq_close(mqdes) };
    Errno::result(res).map(drop)
}

pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Result<usize> {
    let len = message.len() as size_t;
    let res = unsafe { libc::mq_receive(mqdes, message.as_mut_ptr() as *mut c_char, len, msg_prio as *mut u32) };
    Errno::result(res).map(|r| r as usize)
}

pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
    let res = unsafe { libc::mq_send(mqdes, message.as_ptr() as *const c_char, message.len(), msq_prio) };
    Errno::result(res).map(drop)
}

pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
    let res = unsafe { libc::mq_getattr(mqd, &mut attr) };
    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
}

/// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored
/// Returns the old attributes
/// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()` convenience functions as they are easier to use
///
/// [Further reading](http://man7.org/linux/man-pages/man3/mq_setattr.3.html)
pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
    let res = unsafe { libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, &mut attr) };
    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
}

/// Convenience function.
/// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
/// Returns the old attributes
pub fn mq_set_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
    let oldattr = try!(mq_getattr(mqd));
    let newattr = MqAttr::new(O_NONBLOCK.bits() as c_long, oldattr.mq_attr.mq_maxmsg, oldattr.mq_attr.mq_msgsize, oldattr.mq_attr.mq_curmsgs);
    mq_setattr(mqd, &newattr)
}

/// Convenience function.
/// Removes `O_NONBLOCK` attribute for a given message queue descriptor
/// Returns the old attributes
pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
    let oldattr = try!(mq_getattr(mqd));
    let newattr = MqAttr::new(0, oldattr.mq_attr.mq_maxmsg, oldattr.mq_attr.mq_msgsize, oldattr.mq_attr.mq_curmsgs);
    mq_setattr(mqd, &newattr)
}
<commit_msg>Run rustfmt on mqueue.rs<commit_after>//! Posix Message Queue functions
//!
//! [Further reading and details on the C API](http://man7.org/linux/man-pages/man7/mq_overview.7.html)

use {Errno, Result};

use libc::{self, c_char, c_long, mode_t, mqd_t, size_t};
use std::ffi::CString;
use sys::stat::Mode;
use std::mem;

libc_bitflags!{
    flags MQ_OFlag: libc::c_int {
        O_RDONLY,
        O_WRONLY,
        O_RDWR,
        O_CREAT,
        O_EXCL,
        O_NONBLOCK,
        O_CLOEXEC,
    }
}

libc_bitflags!{
    flags FdFlag: libc::c_int {
        FD_CLOEXEC,
    }
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct MqAttr {
    mq_attr: libc::mq_attr,
}

impl PartialEq<MqAttr> for MqAttr {
    fn eq(&self, other: &MqAttr) -> bool {
        let self_attr = self.mq_attr;
        let other_attr = other.mq_attr;
        self_attr.mq_flags == other_attr.mq_flags && self_attr.mq_maxmsg == other_attr.mq_maxmsg &&
        self_attr.mq_msgsize == other_attr.mq_msgsize &&
        self_attr.mq_curmsgs == other_attr.mq_curmsgs
    }
}

impl MqAttr {
    pub fn new(mq_flags: c_long,
               mq_maxmsg: c_long,
               mq_msgsize: c_long,
               mq_curmsgs: c_long)
               -> MqAttr {
        let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
        attr.mq_flags = mq_flags;
        attr.mq_maxmsg = mq_maxmsg;
        attr.mq_msgsize = mq_msgsize;
        attr.mq_curmsgs = mq_curmsgs;
        MqAttr { mq_attr: attr }
    }

    pub fn flags(&self) -> c_long {
        self.mq_attr.mq_flags
    }
}

pub fn mq_open(name: &CString,
               oflag: MQ_OFlag,
               mode: Mode,
               attr: Option<&MqAttr>)
               -> Result<mqd_t> {
    let res = match attr {
        Some(mq_attr) => unsafe {
            libc::mq_open(name.as_ptr(),
                          oflag.bits(),
                          mode.bits() as mode_t,
                          &mq_attr.mq_attr as *const libc::mq_attr)
        },
        None => unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) },
    };
    Errno::result(res)
}

pub fn mq_unlink(name: &CString) -> Result<()> {
    let res = unsafe { libc::mq_unlink(name.as_ptr()) };
    Errno::result(res).map(drop)
}

pub fn mq_close(mqdes: mqd_t) -> Result<()> {
    let res = unsafe { libc::mq_close(mqdes) };
    Errno::result(res).map(drop)
}

pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Result<usize> {
    let len = message.len() as size_t;
    let res = unsafe {
        libc::mq_receive(mqdes,
                         message.as_mut_ptr() as *mut c_char,
                         len,
                         msg_prio as *mut u32)
    };
    Errno::result(res).map(|r| r as usize)
}

pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
    let res = unsafe {
        libc::mq_send(mqdes,
                      message.as_ptr() as *const c_char,
                      message.len(),
                      msq_prio)
    };
    Errno::result(res).map(drop)
}

pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
    let res = unsafe { libc::mq_getattr(mqd, &mut attr) };
    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
}

/// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored
/// Returns the old attributes
/// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()` convenience functions as they are easier to use
///
/// [Further reading](http://man7.org/linux/man-pages/man3/mq_setattr.3.html)
pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
    let res = unsafe { libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, &mut attr) };
    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
}

/// Convenience function.
/// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
/// Returns the old attributes
pub fn mq_set_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
    let oldattr = try!(mq_getattr(mqd));
    let newattr = MqAttr::new(O_NONBLOCK.bits() as c_long,
                              oldattr.mq_attr.mq_maxmsg,
                              oldattr.mq_attr.mq_msgsize,
                              oldattr.mq_attr.mq_curmsgs);
    mq_setattr(mqd, &newattr)
}

/// Convenience function.
/// Removes `O_NONBLOCK` attribute for a given message queue descriptor
/// Returns the old attributes
pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
    let oldattr = try!(mq_getattr(mqd));
    let newattr = MqAttr::new(0,
                              oldattr.mq_attr.mq_maxmsg,
                              oldattr.mq_attr.mq_msgsize,
                              oldattr.mq_attr.mq_curmsgs);
    mq_setattr(mqd, &newattr)
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 fd developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use crate::exit_codes::ExitCode;
use crate::internal::opts::FdOptions;
use lscolors::{LsColors, Style};

use std::borrow::Cow;
use std::io::{self, StdoutLock, Write};
use std::path::{Component, Path, PathBuf};
use std::process;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;

use ansi_term;

/// Remove the `./` prefix from a path.
fn strip_current_dir(pathbuf: &PathBuf) -> &Path {
    let mut iter = pathbuf.components();
    let mut iter_next = iter.clone();
    if iter_next.next() == Some(Component::CurDir) {
        iter.next();
    }
    iter.as_path()
}

pub fn print_entry(
    stdout: &mut StdoutLock,
    entry: &PathBuf,
    config: &FdOptions,
    wants_to_quit: &Arc<AtomicBool>,
) {
    let path = if entry.is_absolute() {
        entry.as_path()
    } else {
        strip_current_dir(entry)
    };

    let r = if let Some(ref ls_colors) = config.ls_colors {
        print_entry_colorized(stdout, path, config, ls_colors, &wants_to_quit)
    } else {
        print_entry_uncolorized(stdout, path, config)
    };

    if r.is_err() {
        // Probably a broken pipe. Exit gracefully.
        process::exit(ExitCode::GeneralError.into());
    }
}

fn replace_path_separator<'a>(config: &FdOptions, str: Cow<'a, str>) -> Cow<'a, str> {
    match &config.path_separator {
        None => str,
        Some(sep) => Cow::from(str.replace(std::path::MAIN_SEPARATOR, &sep)),
    }
}

fn print_entry_colorized(
    stdout: &mut StdoutLock,
    path: &Path,
    config: &FdOptions,
    ls_colors: &LsColors,
    wants_to_quit: &Arc<AtomicBool>,
) -> io::Result<()> {
    let default_style = ansi_term::Style::default();

    // Traverse the path and colorize each component
    for (component, style) in ls_colors.style_for_path_components(path) {
        let style = style
            .map(Style::to_ansi_term_style)
            .unwrap_or(default_style);

        let path_string = component.to_string_lossy();
        let path_string = replace_path_separator(&config, path_string);
        write!(stdout, "{}", style.paint(path_string))?;

        if wants_to_quit.load(Ordering::Relaxed) {
            writeln!(stdout)?;
            process::exit(ExitCode::KilledBySigint.into());
        }
    }

    if config.null_separator {
        write!(stdout, "\0")
    } else {
        writeln!(stdout)
    }
}

fn print_entry_uncolorized(
    stdout: &mut StdoutLock,
    path: &Path,
    config: &FdOptions,
) -> io::Result<()> {
    let separator = if config.null_separator { "\0" } else { "\n" };

    let path_str = path.to_string_lossy();
    let path_str = replace_path_separator(&config, path_str);
    write!(stdout, "{}{}", path_str, separator)
}
<commit_msg>Use existing Cow pointer<commit_after>// Copyright (c) 2017 fd developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use crate::exit_codes::ExitCode;
use crate::internal::opts::FdOptions;
use lscolors::{LsColors, Style};

use std::borrow::Cow;
use std::io::{self, StdoutLock, Write};
use std::path::{Component, Path, PathBuf};
use std::process;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;

use ansi_term;

/// Remove the `./` prefix from a path.
fn strip_current_dir(pathbuf: &PathBuf) -> &Path {
    let mut iter = pathbuf.components();
    let mut iter_next = iter.clone();
    if iter_next.next() == Some(Component::CurDir) {
        iter.next();
    }
    iter.as_path()
}

pub fn print_entry(
    stdout: &mut StdoutLock,
    entry: &PathBuf,
    config: &FdOptions,
    wants_to_quit: &Arc<AtomicBool>,
) {
    let path = if entry.is_absolute() {
        entry.as_path()
    } else {
        strip_current_dir(entry)
    };

    let r = if let Some(ref ls_colors) = config.ls_colors {
        print_entry_colorized(stdout, path, config, ls_colors, &wants_to_quit)
    } else {
        print_entry_uncolorized(stdout, path, config)
    };

    if r.is_err() {
        // Probably a broken pipe. Exit gracefully.
        process::exit(ExitCode::GeneralError.into());
    }
}

fn replace_path_separator<'a>(config: &FdOptions, path: &mut Cow<'a, str>) {
    match &config.path_separator {
        None => {}
        Some(sep) => {
            *path.to_mut() = path.replace(std::path::MAIN_SEPARATOR, &sep);
        }
    }
}

fn print_entry_colorized(
    stdout: &mut StdoutLock,
    path: &Path,
    config: &FdOptions,
    ls_colors: &LsColors,
    wants_to_quit: &Arc<AtomicBool>,
) -> io::Result<()> {
    let default_style = ansi_term::Style::default();

    // Traverse the path and colorize each component
    for (component, style) in ls_colors.style_for_path_components(path) {
        let style = style
            .map(Style::to_ansi_term_style)
            .unwrap_or(default_style);

        let mut path_string = component.to_string_lossy();
        replace_path_separator(&config, &mut path_string);
        write!(stdout, "{}", style.paint(path_string))?;

        if wants_to_quit.load(Ordering::Relaxed) {
            writeln!(stdout)?;
            process::exit(ExitCode::KilledBySigint.into());
        }
    }

    if config.null_separator {
        write!(stdout, "\0")
    } else {
        writeln!(stdout)
    }
}

fn print_entry_uncolorized(
    stdout: &mut StdoutLock,
    path: &Path,
    config: &FdOptions,
) -> io::Result<()> {
    let separator = if config.null_separator { "\0" } else { "\n" };

    let mut path_str = path.to_string_lossy();
    replace_path_separator(&config, &mut path_str);
    write!(stdout, "{}{}", path_str, separator)
}
<|endoftext|>


<commit_before>use tokenizer::Tokenizer;
use event::{Event, Rule};
use std::collections::HashMap;

fn substitute_variables<'a>(value: &'a str, substitutions: &'a HashMap<String, String>) -> String {
    value.split(' ').map(|value_part|
        match substitutions.get(value_part) {
            Some(v) => &v[..],
            None => value_part,
        }
    ).collect::<Vec<_>>().connect(" ")
}

pub fn nested(tokenizer: &mut Tokenizer) -> String {
    let mut output = String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables: HashMap<String, String> = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => format!("{} ", name),
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!("{{\n  {}: {};", name, real_value),
                    _ => format!("\n  {}: {};", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!(" }}\n"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn compressed(tokenizer: &mut Tokenizer) -> String {
    let mut output =  String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => {
                match last {
                    Event::Selector(_) => format!(" {}", name),
                    _ => format!("{}", name),
                }
            },
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!("{{{}:{}", name, real_value),
                    Event::Property(_, _) => format!(";{}:{}", name, real_value),
                    _ => format!("{}:{}", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!("}}"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn expanded<'a, I>(tokenizer: &mut I) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut parents = Vec::new();
    expanded_inner(tokenizer, &mut parents)
}

fn expanded_inner<'a, I>(tokenizer: &mut I, parents: &mut Vec<String>) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut last = Event::End(Rule::SassRule);
    let mut variables = HashMap::new();
    let mut current = String::from_str("");
    let mut properties = String::from_str("");
    let mut children = String::from_str("");

    while let Some(token) = tokenizer.next() {
        match token.clone() {
            Event::Start(_) => {
                match children.len() {
                    0 => children = expanded_inner(tokenizer, parents),
                    _ => {
                        children.push_str("\n\n");
                        children.push_str(&expanded_inner(tokenizer, parents)[..]);
                    },
                };
            },
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => {
                parents.push((*name).to_string());
                match last {
                    Event::Selector(_) => current.push_str(&format!(" {}", name)[..]),
                    Event::End(_) => current.push_str(&format!("{}", name)[..]),
                    _ => current.push_str(&format!("{}", name)[..]),
                }
            },
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => properties.push_str(&format!(" {{\n  {}: {};", name, real_value)[..]),
                    _ => properties.push_str(&format!("\n  {}: {};", name, real_value)[..]),
                }
            },
            Event::End(_) => {
                match (properties.len(), children.len()) {
                    (0, 0) => current.push_str("\n}"),
                    (_, 0) => {
                        current.push_str(&properties[..]);
                        current.push_str("\n}");
                    },
                    (0, _) => {
                        current.push_str(" ");
                        current.push_str(&children[..]);
                    },
                    (_, _) => {
                        current.push_str(&properties[..]);
                        current.push_str("\n}\n");
                        current.push_str(&parents.connect(" "));
                        current.push_str(" ");
                        current.push_str(&children[..]);
                    },
                }
                parents.pop();
                return current
            },
        };

        last = token;
    }
    children
}

pub fn compact(tokenizer: &mut Tokenizer) -> String {
    let mut output =  String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => {
                match last {
                    Event::Selector(_) => format!(" {}", name),
                    Event::End(_) => format!("\n{}", name),
                    _ => format!("{}", name),
                }
            },
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!(" {{ {}: {};", name, real_value),
                    _ => format!(" {}: {};", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!(" }}"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn debug(tokenizer: &mut Tokenizer) -> String {
    let mut output = String::from_str("");
    let mut current = String::from_str("");

    while let Some(token) = tokenizer.next() {
        current.push_str(&format!("{:?}\n", token)[..]);
        match token {
            Event::End(_) => {
                output.push_str(&current[..]);
                current = String::from_str("");
            },
            _ => {},
        }
    }
    output
}
<commit_msg>Use VariableMapper in expanded output<commit_after>use tokenizer::Tokenizer;
use event::{Event, Rule};
use variable_mapper::VariableMapper;
use std::collections::HashMap;

fn substitute_variables<'a>(value: &'a str, substitutions: &'a HashMap<String, String>) -> String {
    value.split(' ').map(|value_part|
        match substitutions.get(value_part) {
            Some(v) => &v[..],
            None => value_part,
        }
    ).collect::<Vec<_>>().connect(" ")
}

pub fn nested(tokenizer: &mut Tokenizer) -> String {
    let mut output = String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables: HashMap<String, String> = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => format!("{} ", name),
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!("{{\n  {}: {};", name, real_value),
                    _ => format!("\n  {}: {};", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!(" }}\n"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn compressed(tokenizer: &mut Tokenizer) -> String {
    let mut output =  String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => {
                match last {
                    Event::Selector(_) => format!(" {}", name),
                    _ => format!("{}", name),
                }
            },
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!("{{{}:{}", name, real_value),
                    Event::Property(_, _) => format!(";{}:{}", name, real_value),
                    _ => format!("{}:{}", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!("}}"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn expanded<'a, I>(tokenizer: &mut I) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut parents = Vec::new();
    let mut vm = VariableMapper::new(tokenizer);
    expanded_inner(&mut vm, &mut parents)
}

fn expanded_inner<'a, I>(tokenizer: &mut I, parents: &mut Vec<String>) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut last = Event::End(Rule::SassRule);
    let mut current = String::from_str("");
    let mut properties = String::from_str("");
    let mut children = String::from_str("");

    while let Some(token) = tokenizer.next() {
        match token.clone() {
            Event::Start(_) => {
                match children.len() {
                    0 => children = expanded_inner(tokenizer, parents),
                    _ => {
                        children.push_str("\n\n");
                        children.push_str(&expanded_inner(tokenizer, parents)[..]);
                    },
                };
            },
            Event::Selector(name) => {
                parents.push((*name).to_string());
                match last {
                    Event::Selector(_) => current.push_str(&format!(" {}", name)[..]),
                    Event::End(_) => current.push_str(&format!("{}", name)[..]),
                    _ => current.push_str(&format!("{}", name)[..]),
                }
            },
            Event::Property(name, value) => {
                match last {
                    Event::Selector(_) => properties.push_str(&format!(" {{\n  {}: {};", name, value)[..]),
                    _ => properties.push_str(&format!("\n  {}: {};", name, value)[..]),
                }
            },
            Event::End(_) => {
                match (properties.len(), children.len()) {
                    (0, 0) => current.push_str("\n}"),
                    (_, 0) => {
                        current.push_str(&properties[..]);
                        current.push_str("\n}");
                    },
                    (0, _) => {
                        current.push_str(" ");
                        current.push_str(&children[..]);
                    },
                    (_, _) => {
                        current.push_str(&properties[..]);
                        current.push_str("\n}\n");
                        current.push_str(&parents.connect(" "));
                        current.push_str(" ");
                        current.push_str(&children[..]);
                    },
                }
                parents.pop();
                return current
            },
            Event::Variable(..) => unreachable!(),
        };

        last = token;
    }
    children
}

pub fn compact(tokenizer: &mut Tokenizer) -> String {
    let mut output =  String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => {
                match last {
                    Event::Selector(_) => format!(" {}", name),
                    Event::End(_) => format!("\n{}", name),
                    _ => format!("{}", name),
                }
            },
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!(" {{ {}: {};", name, real_value),
                    _ => format!(" {}: {};", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!(" }}"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn debug(tokenizer: &mut Tokenizer) -> String {
    let mut output = String::from_str("");
    let mut current = String::from_str("");

    while let Some(token) = tokenizer.next() {
        current.push_str(&format!("{:?}\n", token)[..]);
        match token {
            Event::End(_) => {
                output.push_str(&current[..]);
                current = String::from_str("");
            },
            _ => {},
        }
    }
    output
}
<|endoftext|>