<commit_before>//! Server-side Wayland connector
//!
//! # Overview
//!
//! Setting up the listening socket is done by the `create_display`
//! function, providing you a `Display` object and an `EventLoop`.
//!
//! On the event loop, you'll be able to register the globals
//! you want to advertize, as well as handlers for all ressources
//! created by the clients.
//!
//! You then integrate the wayland event loop in your main event
//! loop to run your compositor.
//!
//! # Implementation and event loop
//!
//! This crate mirrors the callback-oriented design of the
//! Wayland C library by using implementation structs: each wayland
//! type defines an `Implementation` struct in its module, with
//! one function field for each possible event this object can receive.
//!
//! When registering an object on an event loop, you need to provide an
//! implementation for this object. You can also provide some
//! "implementation data": a value that will be provided as second
//! argument to all the callback methods of your implementation.
//!
//! A typical use of implementation data is to store here one or more
//! state tokens to access some part of the shared state from your
//! callback.
//!
//! ## Example of implementation
//!
//! You can register your wayland objects to an event queue:
//!
//! ```ignore
//! event_loop.register(&my_object, implementation, impl_data);
//! ```
//!
//! A given wayland object can only be registered to an event
//! loop at a given time, re-registering it will overwrite
//! the previous configuration.
//!
//! Objects can be registered to event loop using the `&EventLoopHandle`
//! argument, available from withing an event callback.
//!
//! ## Globals definition
//!
//! Some wayland objects are special and can be directly created by the
//! clients from their registry. To handle them your must declare
//! which globals you want to make available to your clients, like this:
//!
//! ```ignore
//! event_loop.register_global(version, callback, idata);
//! ```
//!
//! Where `callback` is a function or non-capturing closure, provided as
//! an implementation for when this global is instanciated by a client.
//! See the method documentation for details.
//!
//! ## Event loop integration
//!
//! Once the setup phase is done, you can integrate the
//! event loop in the main event loop of your program.
//!
//! Either all you need is for it to run indefinitely (external
//! events are checked in an other thread?):
//!
//! ```ignore
//! event_loop.run();
//! ```
//!
//! Or you can integrate it with more control:
//!
//! ```ignore
//! loop {
//!     // flush events to client sockets
//!     display.flush_clients();
//!     // receive request from clients and dispatch them
//!     // blocking if no request is pending for at most
//!     // 10ms
//!     event_loop.dispatch(Some(10)).unwrap();
//!     // then you can check events from other sources if
//!     // you need to
//! }
//! ```
//!
//! # Protocols integration
//!
//! This crate provides the basic primitives as well as the
//! core wayland protocol (in the `protocol` module), but
//! other protocols can be integrated from XML descriptions.
//!
//! The the crate `wayland_scanner` and its documentation for
//! details about how to do so.

#![warn(missing_docs)]

#[macro_use]
extern crate bitflags;
extern crate libc;
extern crate nix;
#[macro_use]
extern crate wayland_sys;

pub use client::Client;
pub use display::{create_display, Display};
pub use event_loop::{resource_is_registered, EventLoop, EventLoopHandle, Global, GlobalCallback,
                     RegisterStatus, State, StateToken};
pub use generated::interfaces as protocol_interfaces;
pub use generated::server as protocol;
use wayland_sys::common::{wl_argument, wl_interface};
use wayland_sys::server::*;

mod client;
mod display;
mod event_loop;
mod event_sources;

pub mod sources {
    //! Secondary event sources
    // This module contains the types & traits to work with
    // different kind of event sources that can be registered to and
    // event loop, other than the wayland protocol sockets.

    pub use event_sources::{FdEventSource, FdEventSourceImpl};
    pub use event_sources::{FdInterest, READ, WRITE};
    pub use event_sources::{SignalEventSource, SignalEventSourceImpl};
    pub use event_sources::{TimerEventSource, TimerEventSourceImpl};
}

/// Common routines for wayland resource objects.
///
/// All wayland objects automatically implement this trait
/// as generated by the scanner.
///
/// It is mostly used for internal use by the library, and you
/// should only need these methods for interfacing with C library
/// working on wayland objects.
pub unsafe trait Resource {
    /// Pointer to the underlying wayland proxy object
    fn ptr(&self) -> *mut wl_resource;
    /// Create an instance from a wayland pointer
    ///
    /// The pointer must refer to a valid wayland resource
    /// of the appropriate interface, but that have not yet
    /// been seen by the library.
    ///
    /// The library will take control of the object (notably
    /// overwrite its user_data).
    unsafe fn from_ptr_new(*mut wl_resource) -> Self;
    /// Create an instance from a wayland pointer
    ///
    /// The pointer must refer to a valid wayland resource
    /// of the appropriate interface. The library will detect if the
    /// resource is already managed by it or not. If it is not, this
    /// resource will be considered as "unmanaged", and should then
    /// be handled with care.
    unsafe fn from_ptr_initialized(*mut wl_resource) -> Self;
    /// Pointer to the interface representation
    fn interface_ptr() -> *const wl_interface;
    /// Internal wayland name of this interface
    fn interface_name() -> &'static str;
    /// Max version of this interface supported
    fn supported_version() -> u32;
    /// Current version of the interface this resource is instantiated with
    fn version(&self) -> i32;
    /// Check if the resource behind this handle is actually still alive
    fn status(&self) -> Liveness;
    /// Check of two handles are actually the same wayland object
    ///
    /// Returns `false` if any of the objects has already been destroyed
    fn equals(&self, &Self) -> bool;
    /// Set a pointer associated as user data on this resource
    ///
    /// All handles to the same wayland object share the same user data pointer.
    ///
    /// The get/set operations are atomic, no more guarantee is given. If you need
    /// to synchronise access to this data, it is your responsibility to add a Mutex
    /// or any other similar mechanism.
    fn set_user_data(&self, ptr: *mut ());
    /// Get the pointer associated as user data on this resource
    ///
    /// All handles to the same wayland object share the same user data pointer.
    ///
    /// See `set_user_data` for synchronisation guarantee.
    fn get_user_data(&self) -> *mut ();
    /// Posts a protocol error to this resource
    ///
    /// The error code can be obtained from the various `Error` enums of the protocols.
    ///
    /// An error is fatal to the client that caused it.
    fn post_error(&self, error_code: u32, msg: String) {
        // If `str` contains an interior null, the actuall transmitted message will
        // be truncated at this point.
        unsafe {
            let cstring = ::std::ffi::CString::from_vec_unchecked(msg.into());
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_resource_post_error,
                self.ptr(),
                error_code,
                cstring.as_ptr()
            )
        }
    }
    /// Clone this resource handle
    ///
    /// Will only succeed if the resource is managed by this library and
    /// is still alive.
    fn clone(&self) -> Option<Self>
    where
        Self: Sized,
    {
        if self.status() == Liveness::Alive {
            Some(unsafe { self.clone_unchecked() })
        } else {
            None
        }
    }
    /// Unsafely clone this resource handle
    ///
    /// This function is unsafe because if the resource is unmanaged, the lib
    /// has no knowledge of its lifetime, and cannot ensure that the new handle
    /// will not outlive the object.
    unsafe fn clone_unchecked(&self) -> Self;
}

/// Common trait for wayland objects that can be registered to an EventQueue
pub unsafe trait Implementable<ID: 'static>: Resource {
    /// The type containing the implementation for the event callbacks
    type Implementation: PartialEq + Copy + 'static;
    #[doc(hidden)]
    unsafe fn __dispatch_msg(&self, client: &Client, opcode: u32, args: *const wl_argument)
                             -> Result<(), ()>;
}

/// Possible outcome of the call of a event on a resource
#[derive(Debug)]
pub enum EventResult<T> {
    /// Message has been buffered and will be sent to client
    Sent(T),
    /// This resource is already destroyed, request has been ignored
    Destroyed,
}

impl<T> EventResult<T> {
    /// Assert that result is successfull and extract the value.
    ///
    /// Panics with provided error message if the result was `Destroyed`.
    pub fn expect(self, error: &str) -> T {
        match self {
            EventResult::Sent(v) => v,
            EventResult::Destroyed => panic!("{}", error),
        }
    }
}

/// Represents the state of liveness of a wayland object
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Liveness {
    /// This object is alive and events can be sent to it
    Alive,
    /// This object is dead, sending it events will do nothing and
    /// return and error.
    Dead,
    /// This object is not managed by `wayland-server`, you can send it events
    /// but this might crash the program if it was actually dead.
    Unmanaged,
}

mod generated {
    #![allow(dead_code, non_camel_case_types, unused_unsafe, unused_variables)]
    #![allow(non_upper_case_globals, non_snake_case, unused_imports)]
    #![allow(missing_docs)]

    pub mod interfaces {
        //! Interfaces for the core protocol
        // You might need them for the bindings generated for protocol extensions
        include!(concat!(env!("OUT_DIR"), "/wayland_interfaces.rs"));
    }

    pub mod server {
        //! The wayland core protocol
        // This module contains all objects of the core wayland protocol.
        //
        // It has been generated from the `wayland.xml` protocol file
        // using `wayland_scanner`.
        // Imports that need to be available to submodules
        // but should not be in public API.
        // Will be fixable with pub(restricted).

        #[doc(hidden)]
        pub use super::interfaces;
        #[doc(hidden)]
        pub use {Client, EventLoopHandle, EventResult, Implementable, Liveness, Resource};

        include!(concat!(env!("OUT_DIR"), "/wayland_api.rs"));
    }
}

pub mod sys {
    //! Reexports of types and objects from wayland-sys

    pub use wayland_sys::common::*;
    pub use wayland_sys::server::*;
}
<commit_msg>server: add Resource::same_client_as<commit_after>//! Server-side Wayland connector
//!
//! # Overview
//!
//! Setting up the listening socket is done by the `create_display`
//! function, providing you a `Display` object and an `EventLoop`.
//!
//! On the event loop, you'll be able to register the globals
//! you want to advertize, as well as handlers for all ressources
//! created by the clients.
//!
//! You then integrate the wayland event loop in your main event
//! loop to run your compositor.
//!
//! # Implementation and event loop
//!
//! This crate mirrors the callback-oriented design of the
//! Wayland C library by using implementation structs: each wayland
//! type defines an `Implementation` struct in its module, with
//! one function field for each possible event this object can receive.
//!
//! When registering an object on an event loop, you need to provide an
//! implementation for this object. You can also provide some
//! "implementation data": a value that will be provided as second
//! argument to all the callback methods of your implementation.
//!
//! A typical use of implementation data is to store here one or more
//! state tokens to access some part of the shared state from your
//! callback.
//!
//! ## Example of implementation
//!
//! You can register your wayland objects to an event queue:
//!
//! ```ignore
//! event_loop.register(&my_object, implementation, impl_data);
//! ```
//!
//! A given wayland object can only be registered to an event
//! loop at a given time, re-registering it will overwrite
//! the previous configuration.
//!
//! Objects can be registered to event loop using the `&EventLoopHandle`
//! argument, available from withing an event callback.
//!
//! ## Globals definition
//!
//! Some wayland objects are special and can be directly created by the
//! clients from their registry. To handle them your must declare
//! which globals you want to make available to your clients, like this:
//!
//! ```ignore
//! event_loop.register_global(version, callback, idata);
//! ```
//!
//! Where `callback` is a function or non-capturing closure, provided as
//! an implementation for when this global is instanciated by a client.
//! See the method documentation for details.
//!
//! ## Event loop integration
//!
//! Once the setup phase is done, you can integrate the
//! event loop in the main event loop of your program.
//!
//! Either all you need is for it to run indefinitely (external
//! events are checked in an other thread?):
//!
//! ```ignore
//! event_loop.run();
//! ```
//!
//! Or you can integrate it with more control:
//!
//! ```ignore
//! loop {
//!     // flush events to client sockets
//!     display.flush_clients();
//!     // receive request from clients and dispatch them
//!     // blocking if no request is pending for at most
//!     // 10ms
//!     event_loop.dispatch(Some(10)).unwrap();
//!     // then you can check events from other sources if
//!     // you need to
//! }
//! ```
//!
//! # Protocols integration
//!
//! This crate provides the basic primitives as well as the
//! core wayland protocol (in the `protocol` module), but
//! other protocols can be integrated from XML descriptions.
//!
//! The the crate `wayland_scanner` and its documentation for
//! details about how to do so.

#![warn(missing_docs)]

#[macro_use]
extern crate bitflags;
extern crate libc;
extern crate nix;
#[macro_use]
extern crate wayland_sys;

pub use client::Client;
pub use display::{create_display, Display};
pub use event_loop::{resource_is_registered, EventLoop, EventLoopHandle, Global, GlobalCallback,
                     RegisterStatus, State, StateToken};
pub use generated::interfaces as protocol_interfaces;
pub use generated::server as protocol;
use wayland_sys::common::{wl_argument, wl_interface};
use wayland_sys::server::*;

mod client;
mod display;
mod event_loop;
mod event_sources;

pub mod sources {
    //! Secondary event sources
    // This module contains the types & traits to work with
    // different kind of event sources that can be registered to and
    // event loop, other than the wayland protocol sockets.

    pub use event_sources::{FdEventSource, FdEventSourceImpl};
    pub use event_sources::{FdInterest, READ, WRITE};
    pub use event_sources::{SignalEventSource, SignalEventSourceImpl};
    pub use event_sources::{TimerEventSource, TimerEventSourceImpl};
}

/// Common routines for wayland resource objects.
///
/// All wayland objects automatically implement this trait
/// as generated by the scanner.
///
/// It is mostly used for internal use by the library, and you
/// should only need these methods for interfacing with C library
/// working on wayland objects.
pub unsafe trait Resource {
    /// Pointer to the underlying wayland proxy object
    fn ptr(&self) -> *mut wl_resource;
    /// Create an instance from a wayland pointer
    ///
    /// The pointer must refer to a valid wayland resource
    /// of the appropriate interface, but that have not yet
    /// been seen by the library.
    ///
    /// The library will take control of the object (notably
    /// overwrite its user_data).
    unsafe fn from_ptr_new(*mut wl_resource) -> Self;
    /// Create an instance from a wayland pointer
    ///
    /// The pointer must refer to a valid wayland resource
    /// of the appropriate interface. The library will detect if the
    /// resource is already managed by it or not. If it is not, this
    /// resource will be considered as "unmanaged", and should then
    /// be handled with care.
    unsafe fn from_ptr_initialized(*mut wl_resource) -> Self;
    /// Pointer to the interface representation
    fn interface_ptr() -> *const wl_interface;
    /// Internal wayland name of this interface
    fn interface_name() -> &'static str;
    /// Max version of this interface supported
    fn supported_version() -> u32;
    /// Current version of the interface this resource is instantiated with
    fn version(&self) -> i32;
    /// Check if the resource behind this handle is actually still alive
    fn status(&self) -> Liveness;
    /// Check of two handles are actually the same wayland object
    ///
    /// Returns `false` if any of the objects has already been destroyed
    fn equals(&self, &Self) -> bool;
    /// Set a pointer associated as user data on this resource
    ///
    /// All handles to the same wayland object share the same user data pointer.
    ///
    /// The get/set operations are atomic, no more guarantee is given. If you need
    /// to synchronise access to this data, it is your responsibility to add a Mutex
    /// or any other similar mechanism.
    fn set_user_data(&self, ptr: *mut ());
    /// Get the pointer associated as user data on this resource
    ///
    /// All handles to the same wayland object share the same user data pointer.
    ///
    /// See `set_user_data` for synchronisation guarantee.
    fn get_user_data(&self) -> *mut ();
    /// Posts a protocol error to this resource
    ///
    /// The error code can be obtained from the various `Error` enums of the protocols.
    ///
    /// An error is fatal to the client that caused it.
    fn post_error(&self, error_code: u32, msg: String) {
        // If `str` contains an interior null, the actuall transmitted message will
        // be truncated at this point.
        unsafe {
            let cstring = ::std::ffi::CString::from_vec_unchecked(msg.into());
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_resource_post_error,
                self.ptr(),
                error_code,
                cstring.as_ptr()
            )
        }
    }
    /// Clone this resource handle
    ///
    /// Will only succeed if the resource is managed by this library and
    /// is still alive.
    fn clone(&self) -> Option<Self>
    where
        Self: Sized,
    {
        if self.status() == Liveness::Alive {
            Some(unsafe { self.clone_unchecked() })
        } else {
            None
        }
    }
    /// Unsafely clone this resource handle
    ///
    /// This function is unsafe because if the resource is unmanaged, the lib
    /// has no knowledge of its lifetime, and cannot ensure that the new handle
    /// will not outlive the object.
    unsafe fn clone_unchecked(&self) -> Self;
    /// Checks wether this resource and the other are from the same client
    ///
    /// Returns `true` if both are alive and belong to the same client, `false`
    /// otherwise.
    fn same_client_as<R: Resource>(&self, other: &R) -> bool {
        // comparing client pointers for equality is only meaningfull
        // if resources are alive
        if !(self.status() == Liveness::Alive && other.status() == Liveness::Alive) {
            false
        } else {
            let my_client = unsafe { ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_resource_get_client,
                self.ptr()
            ) };
            let other_client = unsafe { ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_resource_get_client,
                other.ptr()
            ) };
            my_client == other_client
        }
    }
}

/// Common trait for wayland objects that can be registered to an EventQueue
pub unsafe trait Implementable<ID: 'static>: Resource {
    /// The type containing the implementation for the event callbacks
    type Implementation: PartialEq + Copy + 'static;
    #[doc(hidden)]
    unsafe fn __dispatch_msg(&self, client: &Client, opcode: u32, args: *const wl_argument)
                             -> Result<(), ()>;
}

/// Possible outcome of the call of a event on a resource
#[derive(Debug)]
pub enum EventResult<T> {
    /// Message has been buffered and will be sent to client
    Sent(T),
    /// This resource is already destroyed, request has been ignored
    Destroyed,
}

impl<T> EventResult<T> {
    /// Assert that result is successfull and extract the value.
    ///
    /// Panics with provided error message if the result was `Destroyed`.
    pub fn expect(self, error: &str) -> T {
        match self {
            EventResult::Sent(v) => v,
            EventResult::Destroyed => panic!("{}", error),
        }
    }
}

/// Represents the state of liveness of a wayland object
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Liveness {
    /// This object is alive and events can be sent to it
    Alive,
    /// This object is dead, sending it events will do nothing and
    /// return and error.
    Dead,
    /// This object is not managed by `wayland-server`, you can send it events
    /// but this might crash the program if it was actually dead.
    Unmanaged,
}

mod generated {
    #![allow(dead_code, non_camel_case_types, unused_unsafe, unused_variables)]
    #![allow(non_upper_case_globals, non_snake_case, unused_imports)]
    #![allow(missing_docs)]

    pub mod interfaces {
        //! Interfaces for the core protocol
        // You might need them for the bindings generated for protocol extensions
        include!(concat!(env!("OUT_DIR"), "/wayland_interfaces.rs"));
    }

    pub mod server {
        //! The wayland core protocol
        // This module contains all objects of the core wayland protocol.
        //
        // It has been generated from the `wayland.xml` protocol file
        // using `wayland_scanner`.
        // Imports that need to be available to submodules
        // but should not be in public API.
        // Will be fixable with pub(restricted).

        #[doc(hidden)]
        pub use super::interfaces;
        #[doc(hidden)]
        pub use {Client, EventLoopHandle, EventResult, Implementable, Liveness, Resource};

        include!(concat!(env!("OUT_DIR"), "/wayland_api.rs"));
    }
}

pub mod sys {
    //! Reexports of types and objects from wayland-sys

    pub use wayland_sys::common::*;
    pub use wayland_sys::server::*;
}
<|endoftext|>


<commit_before>use crate::utils::{
    has_drop, in_macro, is_copy, match_type, paths, snippet_opt, span_lint_hir, span_lint_hir_and_then,
    walk_ptrs_ty_depth,
};
use if_chain::if_chain;
use matches::matches;
use rustc::hir::intravisit::FnKind;
use rustc::hir::{def_id, Body, FnDecl, HirId};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::mir::{
    self, traversal,
    visit::{MutatingUseContext, PlaceContext, Visitor},
    TerminatorKind,
};
use rustc::ty::{self, Ty};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use std::convert::TryFrom;
use syntax::source_map::{BytePos, Span};

macro_rules! unwrap_or_continue {
    ($x:expr) => {
        match $x {
            Some(x) => x,
            None => continue,
        }
    };
}

declare_clippy_lint! {
    /// **What it does:** Checks for a redudant `clone()` (and its relatives) which clones an owned
    /// value that is going to be dropped without further use.
    ///
    /// **Why is this bad?** It is not always possible for the compiler to eliminate useless
    /// allocations and deallocations generated by redundant `clone()`s.
    ///
    /// **Known problems:**
    ///
    /// * Suggestions made by this lint could require NLL to be enabled.
    /// * False-positive if there is a borrow preventing the value from moving out.
    ///
    /// ```rust
    /// let x = String::new();
    ///
    /// let y = &x;
    ///
    /// foo(x.clone()); // This lint suggests to remove this `clone()`
    /// ```
    ///
    /// **Example:**
    /// ```rust
    /// {
    ///     let x = Foo::new();
    ///     call(x.clone());
    ///     call(x.clone()); // this can just pass `x`
    /// }
    ///
    /// ["lorem", "ipsum"].join(" ").to_string()
    ///
    /// Path::new("/a/b").join("c").to_path_buf()
    /// ```
    pub REDUNDANT_CLONE,
    nursery,
    "`clone()` of an owned value that is going to be dropped immediately"
}

declare_lint_pass!(RedundantClone => [REDUNDANT_CLONE]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
    #[allow(clippy::too_many_lines)]
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        _: FnKind<'tcx>,
        _: &'tcx FnDecl,
        body: &'tcx Body,
        _: Span,
        _: HirId,
    ) {
        let def_id = cx.tcx.hir().body_owner_def_id(body.id());
        let mir = cx.tcx.optimized_mir(def_id);

        for (bb, bbdata) in mir.basic_blocks().iter_enumerated() {
            let terminator = bbdata.terminator();

            if in_macro(terminator.source_info.span) {
                continue;
            }

            // Give up on loops
            if terminator.successors().any(|s| *s == bb) {
                continue;
            }

            let (fn_def_id, arg, arg_ty, _) = unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind));

            let from_borrow = cx.match_def_path(fn_def_id, &paths::CLONE_TRAIT_METHOD)
                || cx.match_def_path(fn_def_id, &paths::TO_OWNED_METHOD)
                || (cx.match_def_path(fn_def_id, &paths::TO_STRING_METHOD) && match_type(cx, arg_ty, &paths::STRING));

            let from_deref = !from_borrow
                && (cx.match_def_path(fn_def_id, &paths::PATH_TO_PATH_BUF)
                    || cx.match_def_path(fn_def_id, &paths::OS_STR_TO_OS_STRING));

            if !from_borrow && !from_deref {
                continue;
            }

            // _1 in MIR `{ _2 = &_1; clone(move _2); }` or `{ _2 = _1; to_path_buf(_2); } (from_deref)
            // In case of `from_deref`, `arg` is already a reference since it is `deref`ed in the previous
            // block.
            let (cloned, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(
                cx,
                mir,
                arg,
                from_borrow,
                bbdata.statements.iter()
            ));

            if from_borrow && cannot_move_out {
                continue;
            }

            // _1 in MIR `{ _2 = &_1; _3 = deref(move _2); } -> { _4 = _3; to_path_buf(move _4); }`
            let referent = if from_deref {
                let ps = mir.predecessors_for(bb);
                if ps.len() != 1 {
                    continue;
                }
                let pred_terminator = mir[ps[0]].terminator();

                let pred_arg = if_chain! {
                    if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, Some(res))) =
                        is_call_with_ref_arg(cx, mir, &pred_terminator.kind);
                    if *res == mir::Place::Base(mir::PlaceBase::Local(cloned));
                    if cx.match_def_path(pred_fn_def_id, &paths::DEREF_TRAIT_METHOD);
                    if match_type(cx, pred_arg_ty, &paths::PATH_BUF)
                        || match_type(cx, pred_arg_ty, &paths::OS_STRING);
                    then {
                        pred_arg
                    } else {
                        continue;
                    }
                };

                let (local, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(
                    cx,
                    mir,
                    pred_arg,
                    true,
                    mir[ps[0]].statements.iter()
                ));
                if cannot_move_out {
                    continue;
                }
                local
            } else {
                cloned
            };

            let used_later = traversal::ReversePostorder::new(&mir, bb).skip(1).any(|(tbb, tdata)| {
                // Give up on loops
                if tdata.terminator().successors().any(|s| *s == bb) {
                    return true;
                }

                let mut vis = LocalUseVisitor {
                    local: referent,
                    used_other_than_drop: false,
                };
                vis.visit_basic_block_data(tbb, tdata);
                vis.used_other_than_drop
            });

            if !used_later {
                let span = terminator.source_info.span;
                let node = if let mir::ClearCrossCrate::Set(scope_local_data) = &mir.source_scope_local_data {
                    scope_local_data[terminator.source_info.scope].lint_root
                } else {
                    unreachable!()
                };

                if_chain! {
                    if let Some(snip) = snippet_opt(cx, span);
                    if let Some(dot) = snip.rfind('.');
                    then {
                        let sugg_span = span.with_lo(
                            span.lo() + BytePos(u32::try_from(dot).unwrap())
                        );

                        span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |db| {
                            db.span_suggestion(
                                sugg_span,
                                "remove this",
                                String::new(),
                                Applicability::MaybeIncorrect,
                            );
                            db.span_note(
                                span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())),
                                "this value is dropped without further use",
                            );
                        });
                    } else {
                        span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone");
                    }
                }
            }
        }
    }
}

/// If `kind` is `y = func(x: &T)` where `T: !Copy`, returns `(DefId of func, x, T, y)`.
fn is_call_with_ref_arg<'tcx>(
    cx: &LateContext<'_, 'tcx>,
    mir: &'tcx mir::Mir<'tcx>,
    kind: &'tcx mir::TerminatorKind<'tcx>,
) -> Option<(def_id::DefId, mir::Local, Ty<'tcx>, Option<&'tcx mir::Place<'tcx>>)> {
    if_chain! {
        if let TerminatorKind::Call { func, args, destination, .. } = kind;
        if args.len() == 1;
        if let mir::Operand::Move(mir::Place::Base(mir::PlaceBase::Local(local))) = &args[0];
        if let ty::FnDef(def_id, _) = func.ty(&*mir, cx.tcx).sty;
        if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx));
        if !is_copy(cx, inner_ty);
        then {
            Some((def_id, *local, inner_ty, destination.as_ref().map(|(dest, _)| dest)))
        } else {
            None
        }
    }
}

type CannotMoveOut = bool;

/// Finds the first `to = (&)from`, and returns
/// ``Some((from, [`true` if `from` cannot be moved out]))``.
fn find_stmt_assigns_to<'a, 'tcx: 'a>(
    cx: &LateContext<'_, 'tcx>,
    mir: &mir::Mir<'tcx>,
    to: mir::Local,
    by_ref: bool,
    stmts: impl DoubleEndedIterator<Item = &'a mir::Statement<'tcx>>,
) -> Option<(mir::Local, CannotMoveOut)> {
    stmts
        .rev()
        .find_map(|stmt| {
            if let mir::StatementKind::Assign(mir::Place::Base(mir::PlaceBase::Local(local)), v) = &stmt.kind {
                if *local == to {
                    return Some(v);
                }
            }

            None
        })
        .and_then(|v| {
            if by_ref {
                if let mir::Rvalue::Ref(_, _, ref place) = **v {
                    return base_local_and_movability(cx, mir, place);
                }
            } else if let mir::Rvalue::Use(mir::Operand::Copy(ref place)) = **v {
                return base_local_and_movability(cx, mir, place);
            }
            None
        })
}

/// Extracts and returns the undermost base `Local` of given `place`. Returns `place` itself
/// if it is already a `Local`.
///
/// Also reports whether given `place` cannot be moved out.
fn base_local_and_movability<'tcx>(
    cx: &LateContext<'_, 'tcx>,
    mir: &mir::Mir<'tcx>,
    mut place: &mir::Place<'tcx>,
) -> Option<(mir::Local, CannotMoveOut)> {
    use rustc::mir::Place::*;
    use rustc::mir::PlaceBase;

    // Dereference. You cannot move things out from a borrowed value.
    let mut deref = false;
    // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509.
    let mut field = false;

    loop {
        match place {
            Base(PlaceBase::Local(local)) => return Some((*local, deref || field)),
            Projection(proj) => {
                place = &proj.base;
                deref = deref || matches!(proj.elem, mir::ProjectionElem::Deref);
                if !field && matches!(proj.elem, mir::ProjectionElem::Field(..)) {
                    field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).ty);
                }
            },
            _ => return None,
        }
    }
}

struct LocalUseVisitor {
    local: mir::Local,
    used_other_than_drop: bool,
}

impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor {
    fn visit_basic_block_data(&mut self, block: mir::BasicBlock, data: &mir::BasicBlockData<'tcx>) {
        let statements = &data.statements;
        for (statement_index, statement) in statements.iter().enumerate() {
            self.visit_statement(block, statement, mir::Location { block, statement_index });

            // Once flagged, skip remaining statements
            if self.used_other_than_drop {
                return;
            }
        }

        self.visit_terminator(
            block,
            data.terminator(),
            mir::Location {
                block,
                statement_index: statements.len(),
            },
        );
    }

    fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext<'tcx>, _: mir::Location) {
        match ctx {
            PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_) => return,
            _ => {},
        }

        if *local == self.local {
            self.used_other_than_drop = true;
        }
    }
}
<commit_msg>Rustup to rustc 1.36.0-nightly (f843ad60e 2019-04-30)<commit_after>use crate::utils::{
    has_drop, in_macro, is_copy, match_type, paths, snippet_opt, span_lint_hir, span_lint_hir_and_then,
    walk_ptrs_ty_depth,
};
use if_chain::if_chain;
use matches::matches;
use rustc::hir::intravisit::FnKind;
use rustc::hir::{def_id, Body, FnDecl, HirId};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::mir::{
    self, traversal,
    visit::{MutatingUseContext, PlaceContext, Visitor},
    TerminatorKind,
};
use rustc::ty::{self, Ty};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use std::convert::TryFrom;
use syntax::source_map::{BytePos, Span};

macro_rules! unwrap_or_continue {
    ($x:expr) => {
        match $x {
            Some(x) => x,
            None => continue,
        }
    };
}

declare_clippy_lint! {
    /// **What it does:** Checks for a redudant `clone()` (and its relatives) which clones an owned
    /// value that is going to be dropped without further use.
    ///
    /// **Why is this bad?** It is not always possible for the compiler to eliminate useless
    /// allocations and deallocations generated by redundant `clone()`s.
    ///
    /// **Known problems:**
    ///
    /// * Suggestions made by this lint could require NLL to be enabled.
    /// * False-positive if there is a borrow preventing the value from moving out.
    ///
    /// ```rust
    /// let x = String::new();
    ///
    /// let y = &x;
    ///
    /// foo(x.clone()); // This lint suggests to remove this `clone()`
    /// ```
    ///
    /// **Example:**
    /// ```rust
    /// {
    ///     let x = Foo::new();
    ///     call(x.clone());
    ///     call(x.clone()); // this can just pass `x`
    /// }
    ///
    /// ["lorem", "ipsum"].join(" ").to_string()
    ///
    /// Path::new("/a/b").join("c").to_path_buf()
    /// ```
    pub REDUNDANT_CLONE,
    nursery,
    "`clone()` of an owned value that is going to be dropped immediately"
}

declare_lint_pass!(RedundantClone => [REDUNDANT_CLONE]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
    #[allow(clippy::too_many_lines)]
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        _: FnKind<'tcx>,
        _: &'tcx FnDecl,
        body: &'tcx Body,
        _: Span,
        _: HirId,
    ) {
        let def_id = cx.tcx.hir().body_owner_def_id(body.id());
        let mir = cx.tcx.optimized_mir(def_id);

        for (bb, bbdata) in mir.basic_blocks().iter_enumerated() {
            let terminator = bbdata.terminator();

            if in_macro(terminator.source_info.span) {
                continue;
            }

            // Give up on loops
            if terminator.successors().any(|s| *s == bb) {
                continue;
            }

            let (fn_def_id, arg, arg_ty, _) = unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind));

            let from_borrow = cx.match_def_path(fn_def_id, &paths::CLONE_TRAIT_METHOD)
                || cx.match_def_path(fn_def_id, &paths::TO_OWNED_METHOD)
                || (cx.match_def_path(fn_def_id, &paths::TO_STRING_METHOD) && match_type(cx, arg_ty, &paths::STRING));

            let from_deref = !from_borrow
                && (cx.match_def_path(fn_def_id, &paths::PATH_TO_PATH_BUF)
                    || cx.match_def_path(fn_def_id, &paths::OS_STR_TO_OS_STRING));

            if !from_borrow && !from_deref {
                continue;
            }

            // _1 in MIR `{ _2 = &_1; clone(move _2); }` or `{ _2 = _1; to_path_buf(_2); } (from_deref)
            // In case of `from_deref`, `arg` is already a reference since it is `deref`ed in the previous
            // block.
            let (cloned, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(
                cx,
                mir,
                arg,
                from_borrow,
                bbdata.statements.iter()
            ));

            if from_borrow && cannot_move_out {
                continue;
            }

            // _1 in MIR `{ _2 = &_1; _3 = deref(move _2); } -> { _4 = _3; to_path_buf(move _4); }`
            let referent = if from_deref {
                let ps = mir.predecessors_for(bb);
                if ps.len() != 1 {
                    continue;
                }
                let pred_terminator = mir[ps[0]].terminator();

                let pred_arg = if_chain! {
                    if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, Some(res))) =
                        is_call_with_ref_arg(cx, mir, &pred_terminator.kind);
                    if *res == mir::Place::Base(mir::PlaceBase::Local(cloned));
                    if cx.match_def_path(pred_fn_def_id, &paths::DEREF_TRAIT_METHOD);
                    if match_type(cx, pred_arg_ty, &paths::PATH_BUF)
                        || match_type(cx, pred_arg_ty, &paths::OS_STRING);
                    then {
                        pred_arg
                    } else {
                        continue;
                    }
                };

                let (local, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(
                    cx,
                    mir,
                    pred_arg,
                    true,
                    mir[ps[0]].statements.iter()
                ));
                if cannot_move_out {
                    continue;
                }
                local
            } else {
                cloned
            };

            let used_later = traversal::ReversePostorder::new(&mir, bb).skip(1).any(|(tbb, tdata)| {
                // Give up on loops
                if tdata.terminator().successors().any(|s| *s == bb) {
                    return true;
                }

                let mut vis = LocalUseVisitor {
                    local: referent,
                    used_other_than_drop: false,
                };
                vis.visit_basic_block_data(tbb, tdata);
                vis.used_other_than_drop
            });

            if !used_later {
                let span = terminator.source_info.span;
                let node = if let mir::ClearCrossCrate::Set(scope_local_data) = &mir.source_scope_local_data {
                    scope_local_data[terminator.source_info.scope].lint_root
                } else {
                    unreachable!()
                };

                if_chain! {
                    if let Some(snip) = snippet_opt(cx, span);
                    if let Some(dot) = snip.rfind('.');
                    then {
                        let sugg_span = span.with_lo(
                            span.lo() + BytePos(u32::try_from(dot).unwrap())
                        );

                        span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |db| {
                            db.span_suggestion(
                                sugg_span,
                                "remove this",
                                String::new(),
                                Applicability::MaybeIncorrect,
                            );
                            db.span_note(
                                span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())),
                                "this value is dropped without further use",
                            );
                        });
                    } else {
                        span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone");
                    }
                }
            }
        }
    }
}

/// If `kind` is `y = func(x: &T)` where `T: !Copy`, returns `(DefId of func, x, T, y)`.
fn is_call_with_ref_arg<'tcx>(
    cx: &LateContext<'_, 'tcx>,
    mir: &'tcx mir::Mir<'tcx>,
    kind: &'tcx mir::TerminatorKind<'tcx>,
) -> Option<(def_id::DefId, mir::Local, Ty<'tcx>, Option<&'tcx mir::Place<'tcx>>)> {
    if_chain! {
        if let TerminatorKind::Call { func, args, destination, .. } = kind;
        if args.len() == 1;
        if let mir::Operand::Move(mir::Place::Base(mir::PlaceBase::Local(local))) = &args[0];
        if let ty::FnDef(def_id, _) = func.ty(&*mir, cx.tcx).sty;
        if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx));
        if !is_copy(cx, inner_ty);
        then {
            Some((def_id, *local, inner_ty, destination.as_ref().map(|(dest, _)| dest)))
        } else {
            None
        }
    }
}

type CannotMoveOut = bool;

/// Finds the first `to = (&)from`, and returns
/// ``Some((from, [`true` if `from` cannot be moved out]))``.
fn find_stmt_assigns_to<'a, 'tcx: 'a>(
    cx: &LateContext<'_, 'tcx>,
    mir: &mir::Mir<'tcx>,
    to: mir::Local,
    by_ref: bool,
    stmts: impl DoubleEndedIterator<Item = &'a mir::Statement<'tcx>>,
) -> Option<(mir::Local, CannotMoveOut)> {
    stmts
        .rev()
        .find_map(|stmt| {
            if let mir::StatementKind::Assign(mir::Place::Base(mir::PlaceBase::Local(local)), v) = &stmt.kind {
                if *local == to {
                    return Some(v);
                }
            }

            None
        })
        .and_then(|v| {
            if by_ref {
                if let mir::Rvalue::Ref(_, _, ref place) = **v {
                    return base_local_and_movability(cx, mir, place);
                }
            } else if let mir::Rvalue::Use(mir::Operand::Copy(ref place)) = **v {
                return base_local_and_movability(cx, mir, place);
            }
            None
        })
}

/// Extracts and returns the undermost base `Local` of given `place`. Returns `place` itself
/// if it is already a `Local`.
///
/// Also reports whether given `place` cannot be moved out.
fn base_local_and_movability<'tcx>(
    cx: &LateContext<'_, 'tcx>,
    mir: &mir::Mir<'tcx>,
    mut place: &mir::Place<'tcx>,
) -> Option<(mir::Local, CannotMoveOut)> {
    use rustc::mir::Place::*;
    use rustc::mir::PlaceBase;

    // Dereference. You cannot move things out from a borrowed value.
    let mut deref = false;
    // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509.
    let mut field = false;

    loop {
        match place {
            Base(PlaceBase::Local(local)) => return Some((*local, deref || field)),
            Projection(proj) => {
                place = &proj.base;
                deref = deref || matches!(proj.elem, mir::ProjectionElem::Deref);
                if !field && matches!(proj.elem, mir::ProjectionElem::Field(..)) {
                    field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).ty);
                }
            },
            _ => return None,
        }
    }
}

struct LocalUseVisitor {
    local: mir::Local,
    used_other_than_drop: bool,
}

impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor {
    fn visit_basic_block_data(&mut self, block: mir::BasicBlock, data: &mir::BasicBlockData<'tcx>) {
        let statements = &data.statements;
        for (statement_index, statement) in statements.iter().enumerate() {
            self.visit_statement(statement, mir::Location { block, statement_index });

            // Once flagged, skip remaining statements
            if self.used_other_than_drop {
                return;
            }
        }

        self.visit_terminator(
            data.terminator(),
            mir::Location {
                block,
                statement_index: statements.len(),
            },
        );
    }

    fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext, _: mir::Location) {
        match ctx {
            PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_) => return,
            _ => {},
        }

        if *local == self.local {
            self.used_other_than_drop = true;
        }
    }
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate fuse;
extern crate libc;
extern crate regex;
extern crate rustc_serialize;
extern crate time;
extern crate users;

use libc::ENOSYS;
use chrono::*;
use fuse::{Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyDirectory, ReplyEmpty};
use rustc_serialize::json;
use std::path::Path;

use std::ffi::OsStr;

use fs;
use fs::inode;
use gd;
use object;

use fs::helpers::{create_inode_directory_attributes, create_inode_file_attributes};

pub struct GoodDataFS {
    pub client: gd::GoodDataClient,
    pub users_cache: users::UsersCache,
}

impl Drop for GoodDataFS {
    fn drop(&mut self) {
        println!("Unmounting GoodData Filesystem");
    }
}

#[allow(dead_code)]
impl GoodDataFS {
    pub fn client(&self) -> &gd::GoodDataClient {
        &self.client
    }

    pub fn get_projects_dir_attributes(&self) -> fuse::FileAttr {
        create_inode_directory_attributes(fs::constants::INODE_PROJECTS)
    }

    pub fn get_root_dir_attributes(&self) -> fuse::FileAttr {
        create_inode_directory_attributes(fs::constants::INODE_ROOT)
    }

    pub fn get_user_json_attributes(&self) -> fuse::FileAttr {
        let json = format!("{}\n",
                           json::as_pretty_json(&self.client.user()).to_string());

        let user = json::decode::<object::AccountSetting>(&json);

        let ts = UTC.datetime_from_str(&user.unwrap().accountSetting.updated.unwrap()[..],
                               "%Y-%m-%d %H:%M:%S")
            .unwrap()
            .timestamp();

        let updated = time::Timespec::new(ts, 0);

        create_inode_file_attributes(fs::constants::INODE_USER, json.len() as u64, updated)
    }

    pub fn get_projects_json_attributes(&self) -> fuse::FileAttr {
        let json = format!("{}\n",
                           json::as_pretty_json(&self.client.projects()).to_string());

        create_inode_file_attributes(fs::constants::INODE_PROJECTS_JSON,
                                     json.len() as u64,
                                     fs::constants::DEFAULT_CREATE_TIME)
    }
}

impl Filesystem for GoodDataFS {
    fn getattr(&mut self, req: &Request, ino: u64, reply: ReplyAttr) {
        let inode = inode::Inode::deserialize(ino);
        println!("GoodDataFS::getattr() - Getting attributes {} - {:?}",
                 ino,
                 inode);

        match ino {
            fs::constants::INODE_ROOT => fs::root::getattr(self, req, ino, reply),
            fs::constants::INODE_PROJECTS => fs::projects::getattr(self, req, ino, reply),
            fs::constants::INODE_PROJECTS_JSON => {
                reply.attr(&fs::constants::DEFAULT_TTL,
                           &self.get_projects_json_attributes())
            }
            fs::constants::INODE_USER => {
                reply.attr(&fs::constants::DEFAULT_TTL,
                           &self.get_user_json_attributes())
            }
            _ => {
                if inode.project > 0 && inode.reserved == 0 {
                    fs::projects::getattr(self, req, ino, reply)
                } else if inode.project > 0 {
                    fs::project::getattr(self, req, ino, reply)
                } else {
                    println!("getattr() - HAPR")
                }
            }
        }
    }

    fn lookup(&mut self, req: &Request, parent: u64, name: &Path, reply: ReplyEntry) {
        let parent_inode = inode::Inode::deserialize(parent);
        println!("GoodDataFS::lookup() - Looking up parent {} - {:?}, path: {}",
                 parent,
                 parent_inode,
                 name.to_str().unwrap());

        match parent {
            fs::constants::INODE_ROOT => fs::root::lookup(self, req, parent, name, reply),
            fs::constants::INODE_PROJECTS => fs::projects::lookup(self, req, parent, name, reply),
            _ => {
                if parent_inode.project > 0 {
                    fs::project::lookup(self, req, parent, name, reply)
                }
            }
        }
    }

    fn read(&mut self,
            req: &Request,
            ino: u64,
            fh: u64,
            offset: u64,
            size: u32,
            reply: ReplyData) {

        match ino {
            fs::constants::INODE_PROJECTS_JSON => {
                let json = format!("{}\n",
                                   json::as_pretty_json(&self.client.projects()).to_string());
                // let json: String = fs.client.projects().clone().unwrap().into();
                reply.data(&json.as_bytes()[offset as usize..]);
            }
            fs::constants::INODE_USER => {
                let json: String = self.client.user().clone().unwrap().into();
                reply.data(&json.as_bytes()[offset as usize..]);
            }
            _ => {
                let inode = inode::Inode::deserialize(ino);
                if inode.project > 0 {
                    fs::project::read(self, req, ino, fh, offset, size, reply);
                } else {
                    println!("read() - HAPR")
                }
            }
        }
    }

    fn readdir(&mut self, req: &Request, ino: u64, fh: u64, offset: u64, reply: ReplyDirectory) {
        let inode = inode::Inode::deserialize(ino);
        println!("GoodDataFS::readdir() - Reading inode {} - {:?}, fh: {}, offset: {}",
                 ino,
                 inode,
                 fh,
                 offset);

        match ino {
            fs::constants::INODE_ROOT => {
                if offset == 0 {
                    fs::root::readdir(self, req, ino, fh, offset, reply)
                }
            }
            fs::constants::INODE_PROJECTS => {
                if offset == 0 {
                    fs::projects::readdir(self, req, ino, fh, offset, reply)
                }
            }
            _ => {
                let inode: fs::inode::Inode = fs::inode::Inode::deserialize(ino);
                if inode.project > 0 {
                    fs::project::readdir(self, req, ino, fh, offset, reply)
                }
            }
        }
    }

    fn mkdir (&mut self, _req: &Request, parent: u64, name: &Path, _mode: u32, reply: ReplyEntry) {
        let parent_inode = inode::Inode::deserialize(parent);
        println!("GoodDataFS::mkdir() - Making dir in parent {} - {:?}, path: {}",
                 parent,
                 parent_inode,
                 name.to_str().unwrap());
        match parent {
            fs::constants::INODE_PROJECTS => fs::projects::create(self, name, reply),
            _ => reply.error(ENOSYS)
        }
    }

    fn rmdir (&mut self, _req: &Request, parent: u64, name: &Path, reply: ReplyEmpty) {
        let parent_inode = inode::Inode::deserialize(parent);
        println!("GoodDataFS::rmdir() - Removing dir in parent {} - {:?}, path: {}",
                 parent,
                 parent_inode,
                 name.to_str().unwrap());
        match parent {
            fs::constants::INODE_PROJECTS => fs::projects::delete(self, name, reply),
            _ => reply.error(ENOSYS)
        }
    }
}

impl GoodDataFS {
    pub fn mount(self, mountpoint: String) {
        const VERSION: &'static str = env!("CARGO_PKG_VERSION");
        println!("Mounting GoodData as Filesystem ({}), mountpoint: {}",
                 VERSION,
                 mountpoint);

        fuse::mount(self, &mountpoint, &[&OsStr::new("debug")]);
    }
}
<commit_msg>Fix formatting<commit_after>extern crate chrono;
extern crate fuse;
extern crate libc;
extern crate regex;
extern crate rustc_serialize;
extern crate time;
extern crate users;

use libc::ENOSYS;
use chrono::*;
use fuse::{Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyDirectory, ReplyEmpty};
use rustc_serialize::json;
use std::path::Path;

use std::ffi::OsStr;

use fs;
use fs::inode;
use gd;
use object;

use fs::helpers::{create_inode_directory_attributes, create_inode_file_attributes};

pub struct GoodDataFS {
    pub client: gd::GoodDataClient,
    pub users_cache: users::UsersCache,
}

impl Drop for GoodDataFS {
    fn drop(&mut self) {
        println!("Unmounting GoodData Filesystem");
    }
}

#[allow(dead_code)]
impl GoodDataFS {
    pub fn client(&self) -> &gd::GoodDataClient {
        &self.client
    }

    pub fn get_projects_dir_attributes(&self) -> fuse::FileAttr {
        create_inode_directory_attributes(fs::constants::INODE_PROJECTS)
    }

    pub fn get_root_dir_attributes(&self) -> fuse::FileAttr {
        create_inode_directory_attributes(fs::constants::INODE_ROOT)
    }

    pub fn get_user_json_attributes(&self) -> fuse::FileAttr {
        let json = format!("{}\n",
                           json::as_pretty_json(&self.client.user()).to_string());

        let user = json::decode::<object::AccountSetting>(&json);

        let ts = UTC.datetime_from_str(&user.unwrap().accountSetting.updated.unwrap()[..],
                               "%Y-%m-%d %H:%M:%S")
            .unwrap()
            .timestamp();

        let updated = time::Timespec::new(ts, 0);

        create_inode_file_attributes(fs::constants::INODE_USER, json.len() as u64, updated)
    }

    pub fn get_projects_json_attributes(&self) -> fuse::FileAttr {
        let json = format!("{}\n",
                           json::as_pretty_json(&self.client.projects()).to_string());

        create_inode_file_attributes(fs::constants::INODE_PROJECTS_JSON,
                                     json.len() as u64,
                                     fs::constants::DEFAULT_CREATE_TIME)
    }
}

impl Filesystem for GoodDataFS {
    fn getattr(&mut self, req: &Request, ino: u64, reply: ReplyAttr) {
        let inode = inode::Inode::deserialize(ino);
        println!("GoodDataFS::getattr() - Getting attributes {} - {:?}",
                 ino,
                 inode);

        match ino {
            fs::constants::INODE_ROOT => fs::root::getattr(self, req, ino, reply),
            fs::constants::INODE_PROJECTS => fs::projects::getattr(self, req, ino, reply),
            fs::constants::INODE_PROJECTS_JSON => {
                reply.attr(&fs::constants::DEFAULT_TTL,
                           &self.get_projects_json_attributes())
            }
            fs::constants::INODE_USER => {
                reply.attr(&fs::constants::DEFAULT_TTL,
                           &self.get_user_json_attributes())
            }
            _ => {
                if inode.project > 0 && inode.reserved == 0 {
                    fs::projects::getattr(self, req, ino, reply)
                } else if inode.project > 0 {
                    fs::project::getattr(self, req, ino, reply)
                } else {
                    println!("getattr() - HAPR")
                }
            }
        }
    }

    fn lookup(&mut self, req: &Request, parent: u64, name: &Path, reply: ReplyEntry) {
        let parent_inode = inode::Inode::deserialize(parent);
        println!("GoodDataFS::lookup() - Looking up parent {} - {:?}, path: {}",
                 parent,
                 parent_inode,
                 name.to_str().unwrap());

        match parent {
            fs::constants::INODE_ROOT => fs::root::lookup(self, req, parent, name, reply),
            fs::constants::INODE_PROJECTS => fs::projects::lookup(self, req, parent, name, reply),
            _ => {
                if parent_inode.project > 0 {
                    fs::project::lookup(self, req, parent, name, reply)
                }
            }
        }
    }

    fn read(&mut self,
            req: &Request,
            ino: u64,
            fh: u64,
            offset: u64,
            size: u32,
            reply: ReplyData) {

        match ino {
            fs::constants::INODE_PROJECTS_JSON => {
                let json = format!("{}\n",
                                   json::as_pretty_json(&self.client.projects()).to_string());
                // let json: String = fs.client.projects().clone().unwrap().into();
                reply.data(&json.as_bytes()[offset as usize..]);
            }
            fs::constants::INODE_USER => {
                let json: String = self.client.user().clone().unwrap().into();
                reply.data(&json.as_bytes()[offset as usize..]);
            }
            _ => {
                let inode = inode::Inode::deserialize(ino);
                if inode.project > 0 {
                    fs::project::read(self, req, ino, fh, offset, size, reply);
                } else {
                    println!("read() - HAPR")
                }
            }
        }
    }

    fn readdir(&mut self, req: &Request, ino: u64, fh: u64, offset: u64, reply: ReplyDirectory) {
        let inode = inode::Inode::deserialize(ino);
        println!("GoodDataFS::readdir() - Reading inode {} - {:?}, fh: {}, offset: {}",
                 ino,
                 inode,
                 fh,
                 offset);

        match ino {
            fs::constants::INODE_ROOT => {
                if offset == 0 {
                    fs::root::readdir(self, req, ino, fh, offset, reply)
                }
            }
            fs::constants::INODE_PROJECTS => {
                if offset == 0 {
                    fs::projects::readdir(self, req, ino, fh, offset, reply)
                }
            }
            _ => {
                let inode: fs::inode::Inode = fs::inode::Inode::deserialize(ino);
                if inode.project > 0 {
                    fs::project::readdir(self, req, ino, fh, offset, reply)
                }
            }
        }
    }

    fn mkdir(&mut self, _req: &Request, parent: u64, name: &Path, _mode: u32, reply: ReplyEntry) {
        let parent_inode = inode::Inode::deserialize(parent);
        println!("GoodDataFS::mkdir() - Making dir in parent {} - {:?}, path: {}",
                 parent,
                 parent_inode,
                 name.to_str().unwrap());
        match parent {
            fs::constants::INODE_PROJECTS => fs::projects::create(self, name, reply),
            _ => reply.error(ENOSYS),
        }
    }

    fn rmdir(&mut self, _req: &Request, parent: u64, name: &Path, reply: ReplyEmpty) {
        let parent_inode = inode::Inode::deserialize(parent);
        println!("GoodDataFS::rmdir() - Removing dir in parent {} - {:?}, path: {}",
                 parent,
                 parent_inode,
                 name.to_str().unwrap());
        match parent {
            fs::constants::INODE_PROJECTS => fs::projects::delete(self, name, reply),
            _ => reply.ok(),
        }
    }
}

impl GoodDataFS {
    pub fn mount(self, mountpoint: String) {
        const VERSION: &'static str = env!("CARGO_PKG_VERSION");
        println!("Mounting GoodData as Filesystem ({}), mountpoint: {}",
                 VERSION,
                 mountpoint);

        fuse::mount(self, &mountpoint, &[&OsStr::new("debug")]);
    }
}
<|endoftext|>


<commit_before>//! Definition of the `Result` (immediately finished) combinator

use core::result;

use {Future, Poll, Async};

/// A future representing a value that is immediately ready.
///
/// Created by the `result` function.
#[derive(Debug, Clone)]
#[must_use = "futures do nothing unless polled"]
// TODO: rename this to `Result` on the next major version
pub struct FutureResult<T, E> {
    inner: Option<result::Result<T, E>>,
}

/// Creates a new "leaf future" which will resolve with the given result.
///
/// The returned future represents a computation which is finished immediately.
/// This can be useful with the `finished` and `failed` base future types to
/// convert an immediate value to a future to interoperate elsewhere.
///
/// # Examples
///
/// ```
/// use futures::future::*;
///
/// let future_of_1 = result::<u32, u32>(Ok(1));
/// let future_of_err_2 = result::<u32, u32>(Err(2));
/// ```
pub fn result<T, E>(r: result::Result<T, E>) -> FutureResult<T, E> {
    FutureResult { inner: Some(r) }
}

/// Creates a "leaf future" from an immediate value of a finished and
/// successful computation.
///
/// The returned future is similar to `result` where it will immediately run a
/// scheduled callback with the provided value.
///
/// # Examples
///
/// ```
/// use futures::future::*;
///
/// let future_of_1 = ok::<u32, u32>(1);
/// ```
pub fn ok<T, E>(t: T) -> FutureResult<T, E> {
    result(Ok(t))
}

/// Creates a "leaf future" from an immediate value of a failed computation.
///
/// The returned future is similar to `result` where it will immediately run a
/// scheduled callback with the provided value.
///
/// # Examples
///
/// ```
/// use futures::future::*;
///
/// let future_of_err_1 = err::<u32, u32>(1);
/// ```
pub fn err<T, E>(e: E) -> FutureResult<T, E> {
    result(Err(e))
}

impl<T, E> Future for FutureResult<T, E> {
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<T, E> {
        self.inner.take().expect("cannot poll Result twice").map(Async::Ready)
    }
}
<commit_msg>Implement From<Result<T, E>> for FutureResult<commit_after>//! Definition of the `Result` (immediately finished) combinator

use core::result;

use {Future, Poll, Async};

/// A future representing a value that is immediately ready.
///
/// Created by the `result` function.
#[derive(Debug, Clone)]
#[must_use = "futures do nothing unless polled"]
// TODO: rename this to `Result` on the next major version
pub struct FutureResult<T, E> {
    inner: Option<result::Result<T, E>>,
}

/// Creates a new "leaf future" which will resolve with the given result.
///
/// The returned future represents a computation which is finished immediately.
/// This can be useful with the `finished` and `failed` base future types to
/// convert an immediate value to a future to interoperate elsewhere.
///
/// # Examples
///
/// ```
/// use futures::future::*;
///
/// let future_of_1 = result::<u32, u32>(Ok(1));
/// let future_of_err_2 = result::<u32, u32>(Err(2));
/// ```
pub fn result<T, E>(r: result::Result<T, E>) -> FutureResult<T, E> {
    FutureResult { inner: Some(r) }
}

/// Creates a "leaf future" from an immediate value of a finished and
/// successful computation.
///
/// The returned future is similar to `result` where it will immediately run a
/// scheduled callback with the provided value.
///
/// # Examples
///
/// ```
/// use futures::future::*;
///
/// let future_of_1 = ok::<u32, u32>(1);
/// ```
pub fn ok<T, E>(t: T) -> FutureResult<T, E> {
    result(Ok(t))
}

/// Creates a "leaf future" from an immediate value of a failed computation.
///
/// The returned future is similar to `result` where it will immediately run a
/// scheduled callback with the provided value.
///
/// # Examples
///
/// ```
/// use futures::future::*;
///
/// let future_of_err_1 = err::<u32, u32>(1);
/// ```
pub fn err<T, E>(e: E) -> FutureResult<T, E> {
    result(Err(e))
}

impl<T, E> Future for FutureResult<T, E> {
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<T, E> {
        self.inner.take().expect("cannot poll Result twice").map(Async::Ready)
    }
}

impl<T, E> From<Result<T, E>> for FutureResult<T, E> {
    fn from(r: Result<T, E>) -> Self {
        result(r)
    }
}
<|endoftext|>


<commit_before>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! use futures::future::*;
//!
//! let future = ok::<_, bool>(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *shared1.wait().unwrap());
//! assert_eq!(6, *shared2.wait().unwrap());
//! ```

use std::mem;
use std::sync::{Arc, Mutex, TryLockError};
use std::sync::atomic::{AtomicBool, Ordering};
use std::ops::Deref;
use std::collections::HashMap;

use {Future, Poll, Async};
use task;

/// A future that is cloneable and can be polled in multiple threads.
/// Use Future::shared() method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F: Future> {
    id: u64,
    inner: Arc<Inner<F>>,
}

struct Inner<F: Future> {
    next_clone_id: Mutex<u64>,

    /// Only ever `Some` when `state` is `Waiting`. This is not part of the `State`
    /// enum because we want to be able to call `poll()` on the original future
    /// without holding a lock on `state`.
    original_future: Mutex<Option<F>>,

    state: Mutex<State<F>>,
}

enum State<F: Future> {
    Waiting(Arc<Unparker>),
    Done(Result<Arc<F::Item>, Arc<F::Error>>),
}

impl<F> Shared<F>
    where F: Future
{
    /// Creates a new `Shared` from another future.
    pub fn new(future: F) -> Self {
        Shared {
            id: 0,
            inner: Arc::new(
                Inner {
                    next_clone_id: Mutex::new(1),
                    original_future: Mutex::new(Some(future)),
                    state: Mutex::new(State::Waiting(Arc::new(Unparker::new()))),
                }),
        }
    }
}

impl<F> Future for Shared<F>
    where F: Future
{
    type Item = SharedItem<F::Item>;
    type Error = SharedError<F::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let state = self.inner.state.lock().unwrap();
        let (mut original_future, event) = match *state {
            State::Waiting(ref unparker) => {
                match self.inner.original_future.try_lock() {
                    Ok(original_future) => {
                        if unparker.original_future_needs_poll.swap(false, Ordering::SeqCst) {
                            (original_future, task::UnparkEvent::new(unparker.clone(), 0))
                        } else {
                            unparker.insert(self.id, task::park());
                            return Ok(Async::NotReady)
                        }
                    }
                    Err(TryLockError::WouldBlock) => {
                        // A clone of this `Shared`, possibly on the current thread, holds the mutex.
                        // The mutex will become unlocked again after that clone finishes calling
                        // original_future.poll(). We yield and then try again, in hopes that
                        // the original_future.poll() call finishes quickly.
                        //
                        // TODO(perf): Is there a better way to deal with the case where the poll()
                        // does not finish quickly? Does the kind of situation where that might
                        // matter actually arise much in practice?
                        task::park().unpark();
                        return Ok(Async::NotReady)
                    }
                    Err(TryLockError::Poisoned(e)) => {
                        panic!("poisoned mutex: {:?}", e)
                    }
                }
            }
            State::Done(ref r) => {
                match *r {
                    Ok(ref v) => return Ok(SharedItem { item: v.clone() }.into()),
                    Err(ref e) => return Err(SharedError { error: e.clone() }.into()),
                }
            }
        };
        drop(state);

        let done_val = match *original_future {
            Some(ref mut future) => {
                match task::with_unpark_event(event, || future.poll()) {
                    Ok(Async::NotReady) => return Ok(Async::NotReady),
                    Ok(Async::Ready(v)) => Ok(Arc::new(v)),
                    Err(e) => Err(Arc::new(e)),
                }
            }
            None => unreachable!(),
        };

        // We can now drop the original future to free up any resources it holds.
        original_future.take();
        drop(original_future);

        let mut state = self.inner.state.lock().unwrap();
        match mem::replace(&mut *state, State::Done(done_val.clone())) {
            State::Waiting(ref unparker) => unparker.unpark(),
            _ => unreachable!(),
        }
        drop(state);

        match done_val {
            Ok(v) => Ok(SharedItem { item: v }.into()),
            Err(e) => Err(SharedError { error: e }.into()),
        }
    }
}

impl<F> Clone for Shared<F>
    where F: Future
{
    fn clone(&self) -> Self {
        let mut next_clone_id = self.inner.next_clone_id.lock().unwrap();
        let clone_id = *next_clone_id;
        *next_clone_id += 1;
        Shared {
            id: clone_id,
            inner: self.inner.clone(),
        }
    }
}

impl<F: Future> Drop for Shared<F> {
    fn drop(&mut self) {
        if let Ok(state) = self.inner.state.lock() {
            match *state {
                State::Waiting(ref unparker) => {
                    unparker.remove(self.id);
                }
                State::Done(_) => (),
            }
        }
    }
}

/// A wrapped item of the original future that is clonable and implements Deref
/// for ease of use.
#[derive(Debug)]
pub struct SharedItem<T> {
    item: Arc<T>,
}

impl<T> Deref for SharedItem<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.item.as_ref()
    }
}

/// A wrapped error of the original future that is clonable and implements Deref
/// for ease of use.
#[derive(Debug)]
pub struct SharedError<E> {
    error: Arc<E>,
}

impl<E> Deref for SharedError<E> {
    type Target = E;

    fn deref(&self) -> &E {
        &self.error.as_ref()
    }
}

/// An `EventSet` implementation for passing to `with_unpark_event()` when a `Shared`
/// polls its underlying future. Usually, the purpose of an `EventSet` implementation
/// is to gather precise information about what triggered an unpark, but that is *not*
/// what this implementation does. Instead, it uses `EventSet::insert()` as a hook
/// to unpark a set of waiting tasks.
struct Unparker {
    original_future_needs_poll: AtomicBool,

    /// Tasks that need to be unparked once the original future resolves.
    tasks: Mutex<HashMap<u64, task::Task>>,
}

impl task::EventSet for Unparker {
    fn insert(&self, _id: usize) {
        // The original future is ready to get polled again.
        self.unpark();
    }
}

impl Unparker {
    fn new() -> Unparker {
        Unparker {
            original_future_needs_poll: AtomicBool::new(true),
            tasks: Mutex::new(HashMap::new()),
        }
    }

    fn insert(&self, idx: u64, task: task::Task) {
        self.tasks.lock().unwrap().insert(idx, task);
    }

    fn remove(&self, idx: u64) {
        self.tasks.lock().unwrap().remove(&idx);
    }

    fn unpark(&self) {
        self.original_future_needs_poll.store(true, Ordering::SeqCst);
        let tasks = ::std::mem::replace(&mut *self.tasks.lock().unwrap(), HashMap::new());
        for (_, task) in tasks {
            task.unpark();
        }
    }
}
<commit_msg>avoid panic-on-poisoned in Unparker::remove()<commit_after>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! use futures::future::*;
//!
//! let future = ok::<_, bool>(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *shared1.wait().unwrap());
//! assert_eq!(6, *shared2.wait().unwrap());
//! ```

use std::mem;
use std::sync::{Arc, Mutex, TryLockError};
use std::sync::atomic::{AtomicBool, Ordering};
use std::ops::Deref;
use std::collections::HashMap;

use {Future, Poll, Async};
use task;

/// A future that is cloneable and can be polled in multiple threads.
/// Use Future::shared() method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F: Future> {
    id: u64,
    inner: Arc<Inner<F>>,
}

struct Inner<F: Future> {
    next_clone_id: Mutex<u64>,

    /// Only ever `Some` when `state` is `Waiting`. This is not part of the `State`
    /// enum because we want to be able to call `poll()` on the original future
    /// without holding a lock on `state`.
    original_future: Mutex<Option<F>>,

    state: Mutex<State<F>>,
}

enum State<F: Future> {
    Waiting(Arc<Unparker>),
    Done(Result<Arc<F::Item>, Arc<F::Error>>),
}

impl<F> Shared<F>
    where F: Future
{
    /// Creates a new `Shared` from another future.
    pub fn new(future: F) -> Self {
        Shared {
            id: 0,
            inner: Arc::new(
                Inner {
                    next_clone_id: Mutex::new(1),
                    original_future: Mutex::new(Some(future)),
                    state: Mutex::new(State::Waiting(Arc::new(Unparker::new()))),
                }),
        }
    }
}

impl<F> Future for Shared<F>
    where F: Future
{
    type Item = SharedItem<F::Item>;
    type Error = SharedError<F::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let state = self.inner.state.lock().unwrap();
        let (mut original_future, event) = match *state {
            State::Waiting(ref unparker) => {
                match self.inner.original_future.try_lock() {
                    Ok(original_future) => {
                        if unparker.original_future_needs_poll.swap(false, Ordering::SeqCst) {
                            (original_future, task::UnparkEvent::new(unparker.clone(), 0))
                        } else {
                            unparker.insert(self.id, task::park());
                            return Ok(Async::NotReady)
                        }
                    }
                    Err(TryLockError::WouldBlock) => {
                        // A clone of this `Shared`, possibly on the current thread, holds the mutex.
                        // The mutex will become unlocked again after that clone finishes calling
                        // original_future.poll(). We yield and then try again, in hopes that
                        // the original_future.poll() call finishes quickly.
                        //
                        // TODO(perf): Is there a better way to deal with the case where the poll()
                        // does not finish quickly? Does the kind of situation where that might
                        // matter actually arise much in practice?
                        task::park().unpark();
                        return Ok(Async::NotReady)
                    }
                    Err(TryLockError::Poisoned(e)) => {
                        panic!("poisoned mutex: {:?}", e)
                    }
                }
            }
            State::Done(ref r) => {
                match *r {
                    Ok(ref v) => return Ok(SharedItem { item: v.clone() }.into()),
                    Err(ref e) => return Err(SharedError { error: e.clone() }.into()),
                }
            }
        };
        drop(state);

        let done_val = match *original_future {
            Some(ref mut future) => {
                match task::with_unpark_event(event, || future.poll()) {
                    Ok(Async::NotReady) => return Ok(Async::NotReady),
                    Ok(Async::Ready(v)) => Ok(Arc::new(v)),
                    Err(e) => Err(Arc::new(e)),
                }
            }
            None => unreachable!(),
        };

        // We can now drop the original future to free up any resources it holds.
        original_future.take();
        drop(original_future);

        let mut state = self.inner.state.lock().unwrap();
        match mem::replace(&mut *state, State::Done(done_val.clone())) {
            State::Waiting(ref unparker) => unparker.unpark(),
            _ => unreachable!(),
        }
        drop(state);

        match done_val {
            Ok(v) => Ok(SharedItem { item: v }.into()),
            Err(e) => Err(SharedError { error: e }.into()),
        }
    }
}

impl<F> Clone for Shared<F>
    where F: Future
{
    fn clone(&self) -> Self {
        let mut next_clone_id = self.inner.next_clone_id.lock().unwrap();
        let clone_id = *next_clone_id;
        *next_clone_id += 1;
        Shared {
            id: clone_id,
            inner: self.inner.clone(),
        }
    }
}

impl<F: Future> Drop for Shared<F> {
    fn drop(&mut self) {
        if let Ok(state) = self.inner.state.lock() {
            match *state {
                State::Waiting(ref unparker) => {
                    unparker.remove(self.id);
                }
                State::Done(_) => (),
            }
        }
    }
}

/// A wrapped item of the original future that is clonable and implements Deref
/// for ease of use.
#[derive(Debug)]
pub struct SharedItem<T> {
    item: Arc<T>,
}

impl<T> Deref for SharedItem<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.item.as_ref()
    }
}

/// A wrapped error of the original future that is clonable and implements Deref
/// for ease of use.
#[derive(Debug)]
pub struct SharedError<E> {
    error: Arc<E>,
}

impl<E> Deref for SharedError<E> {
    type Target = E;

    fn deref(&self) -> &E {
        &self.error.as_ref()
    }
}

/// An `EventSet` implementation for passing to `with_unpark_event()` when a `Shared`
/// polls its underlying future. Usually, the purpose of an `EventSet` implementation
/// is to gather precise information about what triggered an unpark, but that is *not*
/// what this implementation does. Instead, it uses `EventSet::insert()` as a hook
/// to unpark a set of waiting tasks.
struct Unparker {
    original_future_needs_poll: AtomicBool,

    /// Tasks that need to be unparked once the original future resolves.
    tasks: Mutex<HashMap<u64, task::Task>>,
}

impl task::EventSet for Unparker {
    fn insert(&self, _id: usize) {
        // The original future is ready to get polled again.
        self.unpark();
    }
}

impl Unparker {
    fn new() -> Unparker {
        Unparker {
            original_future_needs_poll: AtomicBool::new(true),
            tasks: Mutex::new(HashMap::new()),
        }
    }

    fn insert(&self, idx: u64, task: task::Task) {
        self.tasks.lock().unwrap().insert(idx, task);
    }

    fn remove(&self, idx: u64) {
        if let Ok(mut tasks) = self.tasks.lock() {
            tasks.remove(&idx);
        }
    }

    fn unpark(&self) {
        self.original_future_needs_poll.store(true, Ordering::SeqCst);
        let tasks = ::std::mem::replace(&mut *self.tasks.lock().unwrap(), HashMap::new());
        for (_, task) in tasks {
            task.unpark();
        }
    }
}
<|endoftext|>


<commit_before>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! use futures::future::*;
//!
//! let future = ok::<_, bool>(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *shared1.wait().unwrap());
//! assert_eq!(6, *shared2.wait().unwrap());
//! ```

use {Future, Poll, Async};
use executor::{self, Spawn, Unpark};
use task::{self, Task};

use std::{fmt, mem, ops};
use std::cell::UnsafeCell;
use std::sync::{Arc, Mutex};
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::collections::HashMap;

/// A future that is cloneable and can be polled in multiple threads.
/// Use Future::shared() method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F: Future> {
    inner: Arc<Inner<F>>,
    waiter: usize,
}

impl<F> fmt::Debug for Shared<F>
    where F: Future + fmt::Debug,
          F::Item: fmt::Debug,
          F::Error: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Shared")
            .field("inner", &self.inner)
            .field("waiter", &self.waiter)
            .finish()
    }
}

struct Inner<F: Future> {
    next_clone_id: AtomicUsize,
    future: UnsafeCell<Spawn<F>>,
    result: UnsafeCell<Option<Result<SharedItem<F::Item>, SharedError<F::Error>>>>,
    unparker: Arc<Unparker>,
}

struct Unparker {
    state: AtomicUsize,
    waiters: Mutex<HashMap<usize, Task>>,
}

const IDLE: usize = 0;
const POLLING: usize = 1;
const REPOLL: usize = 2;
const COMPLETE: usize = 3;
const POISONED: usize = 4;

pub fn new<F: Future>(future: F) -> Shared<F> {
    Shared {
        inner: Arc::new(Inner {
            next_clone_id: AtomicUsize::new(1),
            unparker: Arc::new(Unparker {
                state: AtomicUsize::new(IDLE),
                waiters: Mutex::new(HashMap::new()),
            }),
            future: UnsafeCell::new(executor::spawn(future)),
            result: UnsafeCell::new(None),
        }),
        waiter: 0,
    }
}

impl<F> Shared<F> where F: Future {
    // TODO: make this private
    #[deprecated(since = "0.1.12", note = "use `Future::shared` instead")]
    #[cfg(feature = "with-deprecated")]
    #[doc(hidden)]
    pub fn new(future: F) -> Self {
        new(future)
    }

    /// If any clone of this `Shared` has completed execution, returns its result immediately
    /// without blocking. Otherwise, returns None without triggering the work represented by
    /// this `Shared`.
    pub fn peek(&self) -> Option<Result<SharedItem<F::Item>, SharedError<F::Error>>> {
        match self.inner.unparker.state.load(SeqCst) {
            COMPLETE => {
                Some(unsafe { self.clone_result() })
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => None,
        }
    }

    fn set_waiter(&mut self) {
        let mut waiters = self.inner.unparker.waiters.lock().unwrap();
        waiters.insert(self.waiter, task::park());
    }

    unsafe fn clone_result(&self) -> Result<SharedItem<F::Item>, SharedError<F::Error>> {
        match *self.inner.result.get() {
            Some(Ok(ref item)) => Ok(item.clone()),
            Some(Err(ref e)) => Err(e.clone()),
            _ => unreachable!(),
        }
    }

    fn complete(&self) {
        self.inner.unparker.state.store(COMPLETE, SeqCst);
        self.inner.unparker.unpark();
    }
}

impl<F> Future for Shared<F>
    where F: Future
{
    type Item = SharedItem<F::Item>;
    type Error = SharedError<F::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.set_waiter();

        match self.inner.unparker.state.compare_and_swap(IDLE, POLLING, SeqCst) {
            IDLE => {
                // Lock acquired, fall through
            }
            POLLING | REPOLL => {
                // Another task is currently polling, at this point we just want
                // to ensure that our task handle is currently registered

                return Ok(Async::NotReady);
            }
            COMPLETE => {
                return unsafe { self.clone_result().map(Async::Ready) };
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => unreachable!(),
        }

        loop {
            struct Reset<'a>(&'a AtomicUsize);

            impl<'a> Drop for Reset<'a> {
                fn drop(&mut self) {
                    use std::thread;

                    if thread::panicking() {
                        self.0.store(POISONED, SeqCst);
                    }
                }
            }

            let _reset = Reset(&self.inner.unparker.state);

            // Get a handle to the unparker
            let unpark: Arc<Unpark> = self.inner.unparker.clone();

            // Poll the future
            match unsafe { (*self.inner.future.get()).poll_future(unpark) } {
                Ok(Async::NotReady) => {
                    // Not ready, try to release the handle
                    match self.inner.unparker.state.compare_and_swap(POLLING, IDLE, SeqCst) {
                        POLLING => {
                            // Success
                            return Ok(Async::NotReady);
                        }
                        REPOLL => {
                            // Gotta poll again!
                            let prev = self.inner.unparker.state.swap(POLLING, SeqCst);
                            assert_eq!(prev, REPOLL);
                        }
                        _ => unreachable!(),
                    }

                }
                Ok(Async::Ready(i)) => {
                    unsafe {
                        (*self.inner.result.get()) = Some(Ok(SharedItem { item: Arc::new(i) }));
                    }

                    break;
                }
                Err(e) => {
                    unsafe {
                        (*self.inner.result.get()) = Some(Err(SharedError { error: Arc::new(e) }));
                    }

                    break;
                }
            }
        }

        self.complete();
        unsafe { self.clone_result().map(Async::Ready) }
    }
}

impl<F> Clone for Shared<F> where F: Future {
    fn clone(&self) -> Self {
        let next_clone_id = self.inner.next_clone_id.fetch_add(1, SeqCst);

        Shared {
            inner: self.inner.clone(),
            waiter: next_clone_id,
        }
    }
}

impl<F> Drop for Shared<F> where F: Future {
    fn drop(&mut self) {
        let mut waiters = self.inner.unparker.waiters.lock().unwrap();
        waiters.remove(&self.waiter);
    }
}

impl Unpark for Unparker {
    fn unpark(&self) {
        self.state.compare_and_swap(POLLING, REPOLL, SeqCst);

        let waiters = mem::replace(&mut *self.waiters.lock().unwrap(), HashMap::new());

        for (_, waiter) in waiters {
            waiter.unpark();
        }
    }
}

unsafe impl<F: Future> Sync for Inner<F> {}
unsafe impl<F: Future> Send for Inner<F> {}

impl<F> fmt::Debug for Inner<F>
    where F: Future + fmt::Debug,
          F::Item: fmt::Debug,
          F::Error: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Inner")
            .finish()
    }
}

/// A wrapped item of the original future that is clonable and implements Deref
/// for ease of use.
#[derive(Debug)]
pub struct SharedItem<T> {
    item: Arc<T>,
}

impl<T> ops::Deref for SharedItem<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.item.as_ref()
    }
}

impl<T> Clone for SharedItem<T> {
    fn clone(&self) -> Self {
        SharedItem { item: self.item.clone() }
    }
}

/// A wrapped error of the original future that is clonable and implements Deref
/// for ease of use.
#[derive(Debug)]
pub struct SharedError<E> {
    error: Arc<E>,
}

impl<E> ops::Deref for SharedError<E> {
    type Target = E;

    fn deref(&self) -> &E {
        &self.error.as_ref()
    }
}

impl<T> Clone for SharedError<T> {
    fn clone(&self) -> Self {
        SharedError { error: self.error.clone() }
    }
}
<commit_msg>Remove `Clone` impl<commit_after>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! use futures::future::*;
//!
//! let future = ok::<_, bool>(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *shared1.wait().unwrap());
//! assert_eq!(6, *shared2.wait().unwrap());
//! ```

use {Future, Poll, Async};
use executor::{self, Spawn, Unpark};
use task::{self, Task};

use std::{fmt, mem, ops};
use std::cell::UnsafeCell;
use std::sync::{Arc, Mutex};
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::collections::HashMap;

/// A future that is cloneable and can be polled in multiple threads.
/// Use Future::shared() method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F: Future> {
    inner: Arc<Inner<F>>,
    waiter: usize,
}

impl<F> fmt::Debug for Shared<F>
    where F: Future + fmt::Debug,
          F::Item: fmt::Debug,
          F::Error: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Shared")
            .field("inner", &self.inner)
            .field("waiter", &self.waiter)
            .finish()
    }
}

struct Inner<F: Future> {
    next_clone_id: AtomicUsize,
    future: UnsafeCell<Spawn<F>>,
    result: UnsafeCell<Option<Result<SharedItem<F::Item>, SharedError<F::Error>>>>,
    unparker: Arc<Unparker>,
}

struct Unparker {
    state: AtomicUsize,
    waiters: Mutex<HashMap<usize, Task>>,
}

const IDLE: usize = 0;
const POLLING: usize = 1;
const REPOLL: usize = 2;
const COMPLETE: usize = 3;
const POISONED: usize = 4;

pub fn new<F: Future>(future: F) -> Shared<F> {
    Shared {
        inner: Arc::new(Inner {
            next_clone_id: AtomicUsize::new(1),
            unparker: Arc::new(Unparker {
                state: AtomicUsize::new(IDLE),
                waiters: Mutex::new(HashMap::new()),
            }),
            future: UnsafeCell::new(executor::spawn(future)),
            result: UnsafeCell::new(None),
        }),
        waiter: 0,
    }
}

impl<F> Shared<F> where F: Future {
    // TODO: make this private
    #[deprecated(since = "0.1.12", note = "use `Future::shared` instead")]
    #[cfg(feature = "with-deprecated")]
    #[doc(hidden)]
    pub fn new(future: F) -> Self {
        new(future)
    }

    /// If any clone of this `Shared` has completed execution, returns its result immediately
    /// without blocking. Otherwise, returns None without triggering the work represented by
    /// this `Shared`.
    pub fn peek(&self) -> Option<Result<SharedItem<F::Item>, SharedError<F::Error>>> {
        match self.inner.unparker.state.load(SeqCst) {
            COMPLETE => {
                Some(unsafe { self.clone_result() })
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => None,
        }
    }

    fn set_waiter(&mut self) {
        let mut waiters = self.inner.unparker.waiters.lock().unwrap();
        waiters.insert(self.waiter, task::park());
    }

    unsafe fn clone_result(&self) -> Result<SharedItem<F::Item>, SharedError<F::Error>> {
        match *self.inner.result.get() {
            Some(Ok(ref item)) => Ok(SharedItem { item: item.item.clone() }),
            Some(Err(ref e)) => Err(SharedError { error: e.error.clone() }),
            _ => unreachable!(),
        }
    }

    fn complete(&self) {
        self.inner.unparker.state.store(COMPLETE, SeqCst);
        self.inner.unparker.unpark();
    }
}

impl<F> Future for Shared<F>
    where F: Future
{
    type Item = SharedItem<F::Item>;
    type Error = SharedError<F::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.set_waiter();

        match self.inner.unparker.state.compare_and_swap(IDLE, POLLING, SeqCst) {
            IDLE => {
                // Lock acquired, fall through
            }
            POLLING | REPOLL => {
                // Another task is currently polling, at this point we just want
                // to ensure that our task handle is currently registered

                return Ok(Async::NotReady);
            }
            COMPLETE => {
                return unsafe { self.clone_result().map(Async::Ready) };
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => unreachable!(),
        }

        loop {
            struct Reset<'a>(&'a AtomicUsize);

            impl<'a> Drop for Reset<'a> {
                fn drop(&mut self) {
                    use std::thread;

                    if thread::panicking() {
                        self.0.store(POISONED, SeqCst);
                    }
                }
            }

            let _reset = Reset(&self.inner.unparker.state);

            // Get a handle to the unparker
            let unpark: Arc<Unpark> = self.inner.unparker.clone();

            // Poll the future
            match unsafe { (*self.inner.future.get()).poll_future(unpark) } {
                Ok(Async::NotReady) => {
                    // Not ready, try to release the handle
                    match self.inner.unparker.state.compare_and_swap(POLLING, IDLE, SeqCst) {
                        POLLING => {
                            // Success
                            return Ok(Async::NotReady);
                        }
                        REPOLL => {
                            // Gotta poll again!
                            let prev = self.inner.unparker.state.swap(POLLING, SeqCst);
                            assert_eq!(prev, REPOLL);
                        }
                        _ => unreachable!(),
                    }

                }
                Ok(Async::Ready(i)) => {
                    unsafe {
                        (*self.inner.result.get()) = Some(Ok(SharedItem { item: Arc::new(i) }));
                    }

                    break;
                }
                Err(e) => {
                    unsafe {
                        (*self.inner.result.get()) = Some(Err(SharedError { error: Arc::new(e) }));
                    }

                    break;
                }
            }
        }

        self.complete();
        unsafe { self.clone_result().map(Async::Ready) }
    }
}

impl<F> Clone for Shared<F> where F: Future {
    fn clone(&self) -> Self {
        let next_clone_id = self.inner.next_clone_id.fetch_add(1, SeqCst);

        Shared {
            inner: self.inner.clone(),
            waiter: next_clone_id,
        }
    }
}

impl<F> Drop for Shared<F> where F: Future {
    fn drop(&mut self) {
        let mut waiters = self.inner.unparker.waiters.lock().unwrap();
        waiters.remove(&self.waiter);
    }
}

impl Unpark for Unparker {
    fn unpark(&self) {
        self.state.compare_and_swap(POLLING, REPOLL, SeqCst);

        let waiters = mem::replace(&mut *self.waiters.lock().unwrap(), HashMap::new());

        for (_, waiter) in waiters {
            waiter.unpark();
        }
    }
}

unsafe impl<F: Future> Sync for Inner<F> {}
unsafe impl<F: Future> Send for Inner<F> {}

impl<F> fmt::Debug for Inner<F>
    where F: Future + fmt::Debug,
          F::Item: fmt::Debug,
          F::Error: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Inner")
            .finish()
    }
}

/// A wrapped item of the original future that is clonable and implements Deref
/// for ease of use.
#[derive(Debug)]
pub struct SharedItem<T> {
    item: Arc<T>,
}

impl<T> ops::Deref for SharedItem<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.item.as_ref()
    }
}

/// A wrapped error of the original future that is clonable and implements Deref
/// for ease of use.
#[derive(Debug)]
pub struct SharedError<E> {
    error: Arc<E>,
}

impl<E> ops::Deref for SharedError<E> {
    type Target = E;

    fn deref(&self) -> &E {
        &self.error.as_ref()
    }
}
<|endoftext|>