<commit_before>use hyper;

use std::error::Error;
use std::fmt;
use std::io;

use crate::types::RequestError;

use chrono::{DateTime, Local, Utc};
use std::time::Duration;

use futures::{future, prelude::*};
use tokio::io as tio;

/// A utility type to indicate how operations DeviceFlowHelper operations should be retried
pub enum Retry {
    /// Signal you don't want to retry
    Abort,
    /// Signals you want to retry after the given duration
    After(Duration),
    /// Instruct the caller to attempt to keep going, or choose an alternate path.
    /// If this is not supported, it will have the same effect as `Abort`
    Skip,
}

/// Contains state of pending authentication requests
#[derive(Clone, Debug, PartialEq)]
pub struct PollInformation {
    /// Code the user must enter ...
    pub user_code: String,
    /// ... at the verification URL
    pub verification_url: String,

    /// The `user_code` expires at the given time
    /// It's the time the user has left to authenticate your application
    pub expires_at: DateTime<Utc>,
    /// The interval in which we may poll for a status change
    /// The server responds with errors of we poll too fast.
    pub interval: Duration,
}

impl fmt::Display for PollInformation {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        writeln!(f, "Proceed with polling until {}", self.expires_at)
    }
}

/// Encapsulates all possible results of a `poll_token(...)` operation
#[derive(Debug)]
pub enum PollError {
    /// Connection failure - retry if you think it's worth it
    HttpError(hyper::Error),
    /// Indicates we are expired, including the expiration date
    Expired(DateTime<Utc>),
    /// Indicates that the user declined access. String is server response
    AccessDenied,
    /// Indicates that too many attempts failed.
    TimedOut,
    /// Other type of error.
    Other(String)
}

impl fmt::Display for PollError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            PollError::HttpError(ref err) => err.fmt(f),
            PollError::Expired(ref date) => writeln!(f, "Authentication expired at {}", date),
            PollError::AccessDenied => "Access denied by user".fmt(f),
            PollError::TimedOut => "Timed out waiting for token".fmt(f),
            PollError::Other(ref s) => format!("Unknown server error: {}", s).fmt(f)
        }
    }
}

impl Error for PollError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match *self {
            PollError::HttpError(ref e) => Some(e),
            _ => None,
        }
    }
}

/// A partially implemented trait to interact with the `Authenticator`
///
/// The only method that needs to be implemented manually is `present_user_code(...)`,
/// as no assumptions are made on how this presentation should happen.
pub trait AuthenticatorDelegate: Clone {
    /// Called whenever there is an client, usually if there are network problems.
    ///
    /// Return retry information.
    fn client_error(&mut self, _: &hyper::Error) -> Retry {
        Retry::Abort
    }

    /// Called whenever there is an HttpError, usually if there are network problems.
    ///
    /// Return retry information.
    fn connection_error(&mut self, _: &hyper::http::Error) -> Retry {
        Retry::Abort
    }

    /// Called whenever we failed to retrieve a token or set a token due to a storage error.
    /// You may use it to either ignore the incident or retry.
    /// This can be useful if the underlying `TokenStorage` may fail occasionally.
    /// if `is_set` is true, the failure resulted from `TokenStorage.set(...)`. Otherwise,
    /// it was `TokenStorage.get(...)`
    fn token_storage_failure(&mut self, is_set: bool, _: &Error) -> Retry {
        let _ = is_set;
        Retry::Abort
    }

    /// The server denied the attempt to obtain a request code
    fn request_failure(&mut self, _: RequestError) {}

    /// Called if we could not acquire a refresh token for a reason possibly specified
    /// by the server.
    /// This call is made for the delegate's information only.
    fn token_refresh_failed<S: AsRef<str>>(
        &mut self,
        error: S,
        error_description: &Option<String>,
    ) {
        {
            let _ = error;
        }
        {
            let _ = error_description;
        }
    }
}

pub trait FlowDelegate: Clone {
    /// Called if the request code is expired. You will have to start over in this case.
    /// This will be the last call the delegate receives.
    /// Given `DateTime` is the expiration date
    fn expired(&mut self, _: &DateTime<Utc>) {}

    /// Called if the user denied access. You would have to start over.
    /// This will be the last call the delegate receives.
    fn denied(&mut self) {}

    /// Called as long as we are waiting for the user to authorize us.
    /// Can be used to print progress information, or decide to time-out.
    ///
    /// If the returned `Retry` variant is a duration.
    /// # Notes
    /// * Only used in `DeviceFlow`. Return value will only be used if it
    /// is larger than the interval desired by the server.
    fn pending(&mut self, _: &PollInformation) -> Retry {
        Retry::After(Duration::from_secs(5))
    }

    /// Configure a custom redirect uri if needed.
    fn redirect_uri(&self) -> Option<String> {
        None
    }
    /// The server has returned a `user_code` which must be shown to the user,
    /// along with the `verification_url`.
    /// # Notes
    /// * Will be called exactly once, provided we didn't abort during `request_code` phase.
    /// * Will only be called if the Authenticator's flow_type is `FlowType::Device`.
    fn present_user_code(&mut self, pi: &PollInformation) {
        println!(
            "Please enter {} at {} and grant access to this application",
            pi.user_code, pi.verification_url
        );
        println!("Do not close this application until you either denied or granted access.");
        println!(
            "You have time until {}.",
            pi.expires_at.with_timezone(&Local)
        );
    }

    /// This method is used by the InstalledFlow.
    /// We need the user to navigate to a URL using their browser and potentially paste back a code
    /// (or maybe not). Whether they have to enter a code depends on the InstalledFlowReturnMethod
    /// used.
    fn present_user_url<S: AsRef<str> + fmt::Display>(
        &mut self,
        url: S,
        need_code: bool,
    ) -> Box<dyn Future<Item = Option<String>, Error = Box<dyn Error + Send>> + Send> {
        if need_code {
            println!(
                "Please direct your browser to {}, follow the instructions and enter the \
                 code displayed here: ",
                url
            );

            Box::new(
                tio::lines(io::BufReader::new(tio::stdin()))
                    .into_future()
                    .map_err(|(e, _)| {
                        println!("{:?}", e);
                        Box::new(e) as Box<dyn Error + Send>
                    })
                    .and_then(|(l, _)| Ok(l)),
            )
        } else {
            println!(
                "Please direct your browser to {} and follow the instructions displayed \
                 there.",
                url
            );
            Box::new(future::ok(None))
        }
    }
}

/// Uses all default implementations by AuthenticatorDelegate, and makes the trait's
/// implementation usable in the first place.
#[derive(Clone)]
pub struct DefaultAuthenticatorDelegate;
impl AuthenticatorDelegate for DefaultAuthenticatorDelegate {}

#[derive(Clone)]
pub struct DefaultFlowDelegate;
impl FlowDelegate for DefaultFlowDelegate {}
<commit_msg>chore(fmt): Make rustfmt on Travis happy.<commit_after>use hyper;

use std::error::Error;
use std::fmt;
use std::io;

use crate::types::RequestError;

use chrono::{DateTime, Local, Utc};
use std::time::Duration;

use futures::{future, prelude::*};
use tokio::io as tio;

/// A utility type to indicate how operations DeviceFlowHelper operations should be retried
pub enum Retry {
    /// Signal you don't want to retry
    Abort,
    /// Signals you want to retry after the given duration
    After(Duration),
    /// Instruct the caller to attempt to keep going, or choose an alternate path.
    /// If this is not supported, it will have the same effect as `Abort`
    Skip,
}

/// Contains state of pending authentication requests
#[derive(Clone, Debug, PartialEq)]
pub struct PollInformation {
    /// Code the user must enter ...
    pub user_code: String,
    /// ... at the verification URL
    pub verification_url: String,

    /// The `user_code` expires at the given time
    /// It's the time the user has left to authenticate your application
    pub expires_at: DateTime<Utc>,
    /// The interval in which we may poll for a status change
    /// The server responds with errors of we poll too fast.
    pub interval: Duration,
}

impl fmt::Display for PollInformation {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        writeln!(f, "Proceed with polling until {}", self.expires_at)
    }
}

/// Encapsulates all possible results of a `poll_token(...)` operation
#[derive(Debug)]
pub enum PollError {
    /// Connection failure - retry if you think it's worth it
    HttpError(hyper::Error),
    /// Indicates we are expired, including the expiration date
    Expired(DateTime<Utc>),
    /// Indicates that the user declined access. String is server response
    AccessDenied,
    /// Indicates that too many attempts failed.
    TimedOut,
    /// Other type of error.
    Other(String),
}

impl fmt::Display for PollError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            PollError::HttpError(ref err) => err.fmt(f),
            PollError::Expired(ref date) => writeln!(f, "Authentication expired at {}", date),
            PollError::AccessDenied => "Access denied by user".fmt(f),
            PollError::TimedOut => "Timed out waiting for token".fmt(f),
            PollError::Other(ref s) => format!("Unknown server error: {}", s).fmt(f),
        }
    }
}

impl Error for PollError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match *self {
            PollError::HttpError(ref e) => Some(e),
            _ => None,
        }
    }
}

/// A partially implemented trait to interact with the `Authenticator`
///
/// The only method that needs to be implemented manually is `present_user_code(...)`,
/// as no assumptions are made on how this presentation should happen.
pub trait AuthenticatorDelegate: Clone {
    /// Called whenever there is an client, usually if there are network problems.
    ///
    /// Return retry information.
    fn client_error(&mut self, _: &hyper::Error) -> Retry {
        Retry::Abort
    }

    /// Called whenever there is an HttpError, usually if there are network problems.
    ///
    /// Return retry information.
    fn connection_error(&mut self, _: &hyper::http::Error) -> Retry {
        Retry::Abort
    }

    /// Called whenever we failed to retrieve a token or set a token due to a storage error.
    /// You may use it to either ignore the incident or retry.
    /// This can be useful if the underlying `TokenStorage` may fail occasionally.
    /// if `is_set` is true, the failure resulted from `TokenStorage.set(...)`. Otherwise,
    /// it was `TokenStorage.get(...)`
    fn token_storage_failure(&mut self, is_set: bool, _: &Error) -> Retry {
        let _ = is_set;
        Retry::Abort
    }

    /// The server denied the attempt to obtain a request code
    fn request_failure(&mut self, _: RequestError) {}

    /// Called if we could not acquire a refresh token for a reason possibly specified
    /// by the server.
    /// This call is made for the delegate's information only.
    fn token_refresh_failed<S: AsRef<str>>(
        &mut self,
        error: S,
        error_description: &Option<String>,
    ) {
        {
            let _ = error;
        }
        {
            let _ = error_description;
        }
    }
}

pub trait FlowDelegate: Clone {
    /// Called if the request code is expired. You will have to start over in this case.
    /// This will be the last call the delegate receives.
    /// Given `DateTime` is the expiration date
    fn expired(&mut self, _: &DateTime<Utc>) {}

    /// Called if the user denied access. You would have to start over.
    /// This will be the last call the delegate receives.
    fn denied(&mut self) {}

    /// Called as long as we are waiting for the user to authorize us.
    /// Can be used to print progress information, or decide to time-out.
    ///
    /// If the returned `Retry` variant is a duration.
    /// # Notes
    /// * Only used in `DeviceFlow`. Return value will only be used if it
    /// is larger than the interval desired by the server.
    fn pending(&mut self, _: &PollInformation) -> Retry {
        Retry::After(Duration::from_secs(5))
    }

    /// Configure a custom redirect uri if needed.
    fn redirect_uri(&self) -> Option<String> {
        None
    }
    /// The server has returned a `user_code` which must be shown to the user,
    /// along with the `verification_url`.
    /// # Notes
    /// * Will be called exactly once, provided we didn't abort during `request_code` phase.
    /// * Will only be called if the Authenticator's flow_type is `FlowType::Device`.
    fn present_user_code(&mut self, pi: &PollInformation) {
        println!(
            "Please enter {} at {} and grant access to this application",
            pi.user_code, pi.verification_url
        );
        println!("Do not close this application until you either denied or granted access.");
        println!(
            "You have time until {}.",
            pi.expires_at.with_timezone(&Local)
        );
    }

    /// This method is used by the InstalledFlow.
    /// We need the user to navigate to a URL using their browser and potentially paste back a code
    /// (or maybe not). Whether they have to enter a code depends on the InstalledFlowReturnMethod
    /// used.
    fn present_user_url<S: AsRef<str> + fmt::Display>(
        &mut self,
        url: S,
        need_code: bool,
    ) -> Box<dyn Future<Item = Option<String>, Error = Box<dyn Error + Send>> + Send> {
        if need_code {
            println!(
                "Please direct your browser to {}, follow the instructions and enter the \
                 code displayed here: ",
                url
            );

            Box::new(
                tio::lines(io::BufReader::new(tio::stdin()))
                    .into_future()
                    .map_err(|(e, _)| {
                        println!("{:?}", e);
                        Box::new(e) as Box<dyn Error + Send>
                    })
                    .and_then(|(l, _)| Ok(l)),
            )
        } else {
            println!(
                "Please direct your browser to {} and follow the instructions displayed \
                 there.",
                url
            );
            Box::new(future::ok(None))
        }
    }
}

/// Uses all default implementations by AuthenticatorDelegate, and makes the trait's
/// implementation usable in the first place.
#[derive(Clone)]
pub struct DefaultAuthenticatorDelegate;
impl AuthenticatorDelegate for DefaultAuthenticatorDelegate {}

#[derive(Clone)]
pub struct DefaultFlowDelegate;
impl FlowDelegate for DefaultFlowDelegate {}
<|endoftext|>


<commit_before>//! Utilities for handling shell surfaces with the `wlr_layer_shell` protocol
//!
//! This interface should be suitable for the implementation of many desktop shell components,
//! and a broad number of other applications that interact with the desktop.
//!
//! ### Initialization
//!
//! To initialize this handler, simple use the [`wlr_layer_shell_init`] function provided in this module.
//! You need to provide a closure that will be invoked whenever some action is required from you,
//! are represented by the [`LayerShellRequest`] enum.
//!
//! ```no_run
//! # extern crate wayland_server;
//! #
//! use smithay::wayland::shell::wlr_layer::{wlr_layer_shell_init, LayerShellRequest};
//!
//! # let mut display = wayland_server::Display::new();
//! let (shell_state, _) = wlr_layer_shell_init(
//!     &mut display,
//!     // your implementation
//!     |event: LayerShellRequest, dispatch_data| { /* handle the shell requests here */ },
//!     None  // put a logger if you want
//! );
//!
//! // You're now ready to go!
//! ```

use std::sync::{Arc, Mutex};

use wayland_protocols_wlr::layer_shell::v1::server::{
    zwlr_layer_shell_v1::{self, ZwlrLayerShellV1},
    zwlr_layer_surface_v1,
};
use wayland_server::{
    backend::GlobalId,
    protocol::{wl_output::WlOutput, wl_surface},
    DisplayHandle, GlobalDispatch, Resource,
};

use crate::{
    utils::{alive_tracker::IsAlive, Logical, Size},
    wayland::{
        compositor::{self, Cacheable},
        Serial, SERIAL_COUNTER,
    },
};

mod handlers;
mod types;

pub use handlers::WlrLayerSurfaceUserData;
pub use types::{Anchor, ExclusiveZone, KeyboardInteractivity, Layer, Margins};

/// The role of a wlr_layer_shell_surface
pub const LAYER_SURFACE_ROLE: &str = "zwlr_layer_surface_v1";

/// Attributes for layer surface
#[derive(Debug)]
pub struct LayerSurfaceAttributes {
    surface: zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
    /// Defines if the surface has received at least one
    /// layer_surface.ack_configure from the client
    pub configured: bool,
    /// The serial of the last acked configure
    pub configure_serial: Option<Serial>,
    /// Holds the state if the surface has sent the initial
    /// configure event to the client. It is expected that
    /// during the first commit a initial
    /// configure event is sent to the client
    pub initial_configure_sent: bool,
    /// Holds the configures the server has sent out
    /// to the client waiting to be acknowledged by
    /// the client. All pending configures that are older
    /// than the acknowledged one will be discarded during
    /// processing layer_surface.ack_configure.
    pending_configures: Vec<LayerSurfaceConfigure>,
    /// Holds the pending state as set by the server.
    pub server_pending: Option<LayerSurfaceState>,
    /// Holds the last server_pending state that has been acknowledged
    /// by the client. This state should be cloned to the current
    /// during a commit.
    pub last_acked: Option<LayerSurfaceState>,
    /// Holds the current state of the layer after a successful
    /// commit.
    pub current: LayerSurfaceState,
}

impl LayerSurfaceAttributes {
    fn new(surface: zwlr_layer_surface_v1::ZwlrLayerSurfaceV1) -> Self {
        Self {
            surface,
            configured: false,
            configure_serial: None,
            initial_configure_sent: false,
            pending_configures: Vec::new(),
            server_pending: None,
            last_acked: None,
            current: Default::default(),
        }
    }

    fn ack_configure(&mut self, serial: Serial) -> Option<LayerSurfaceConfigure> {
        let configure = self
            .pending_configures
            .iter()
            .find(|configure| configure.serial == serial)
            .cloned()?;

        self.last_acked = Some(configure.state.clone());

        self.configured = true;
        self.configure_serial = Some(serial);
        self.pending_configures.retain(|c| c.serial > serial);
        Some(configure)
    }
}

/// State of a layer surface
#[derive(Debug, Default, Clone, PartialEq)]
pub struct LayerSurfaceState {
    /// The suggested size of the surface
    pub size: Option<Size<i32, Logical>>,
}

/// Represents the client pending state
#[derive(Debug, Default, Clone, Copy)]
pub struct LayerSurfaceCachedState {
    /// The size requested by the client
    pub size: Size<i32, Logical>,
    /// Anchor bitflags, describing how the layers surface should be positioned and sized
    pub anchor: Anchor,
    /// Descripton of exclusive zone
    pub exclusive_zone: ExclusiveZone,
    /// Describes distance from the anchor point of the output
    pub margin: Margins,
    /// Describes how keyboard events are delivered to this surface
    pub keyboard_interactivity: KeyboardInteractivity,
    /// The layer that the surface is rendered on
    pub layer: Layer,
}

impl Cacheable for LayerSurfaceCachedState {
    fn commit(&mut self, _dh: &DisplayHandle) -> Self {
        *self
    }
    fn merge_into(self, into: &mut Self, _dh: &DisplayHandle) {
        *into = self;
    }
}

/// Shell global state
///
/// This state allows you to retrieve a list of surfaces
/// currently known to the shell global.
#[derive(Debug, Clone)]
pub struct WlrLayerShellState {
    known_layers: Arc<Mutex<Vec<LayerSurface>>>,
    shell_global: GlobalId,
    _log: slog::Logger,
}

impl WlrLayerShellState {
    /// Create a new `wlr_layer_shell` globals
    pub fn new<L, D>(display: &DisplayHandle, logger: L) -> WlrLayerShellState
    where
        L: Into<Option<::slog::Logger>>,
        D: GlobalDispatch<ZwlrLayerShellV1, ()>,
        D: 'static,
    {
        let log = crate::slog_or_fallback(logger);

        let shell_global = display.create_global::<D, ZwlrLayerShellV1, _>(4, ());

        WlrLayerShellState {
            known_layers: Default::default(),
            shell_global,
            _log: log.new(slog::o!("smithay_module" => "layer_shell_handler")),
        }
    }

    /// Get shell global id
    pub fn shell_global(&self) -> GlobalId {
        self.shell_global.clone()
    }

    /// Access all the shell surfaces known by this handler
    pub fn layer_surfaces(&self) -> &[LayerSurface] {
        // &self.known_layers[..]
        todo!()
    }
}

/// Handler for wlr layer shell
pub trait WlrLayerShellHandler {
    /// [WlrLayerShellState] getter
    fn shell_state(&mut self) -> &mut WlrLayerShellState;

    /// Layer shell request
    fn request(&mut self, dh: &DisplayHandle, request: LayerShellRequest);
}

/// A handle to a layer surface
#[derive(Debug, Clone)]
pub struct LayerSurface {
    wl_surface: wl_surface::WlSurface,
    shell_surface: zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
}

impl std::cmp::PartialEq for LayerSurface {
    fn eq(&self, other: &Self) -> bool {
        self.wl_surface == other.wl_surface
    }
}

impl LayerSurface {
    /// Checks if the surface is still alive
    pub fn alive(&self) -> bool {
        self.wl_surface.alive() && self.shell_surface.alive()
    }

    /// Gets the current pending state for a configure
    ///
    /// Returns `Some` if either no initial configure has been sent or
    /// the `server_pending` is `Some` and different from the last pending
    /// configure or `last_acked` if there is no pending
    ///
    /// Returns `None` if either no `server_pending` or the pending
    /// has already been sent to the client or the pending is equal
    /// to the `last_acked`
    fn get_pending_state(&self, attributes: &mut LayerSurfaceAttributes) -> Option<LayerSurfaceState> {
        if !attributes.initial_configure_sent {
            return Some(attributes.server_pending.take().unwrap_or_default());
        }

        let server_pending = match attributes.server_pending.take() {
            Some(state) => state,
            None => {
                return None;
            }
        };

        let last_state = attributes
            .pending_configures
            .last()
            .map(|c| &c.state)
            .or(attributes.last_acked.as_ref());

        if let Some(state) = last_state {
            if state == &server_pending {
                return None;
            }
        }

        Some(server_pending)
    }

    /// Send a configure event to this layer surface to suggest it a new configuration
    ///
    /// The serial of this configure will be tracked waiting for the client to ACK it.
    ///
    /// You can manipulate the state that will be sent to the client with the [`with_pending_state`](#method.with_pending_state)
    /// method.
    pub fn send_configure(&self) {
        let configure = compositor::with_states(&self.wl_surface, |states| {
            let mut attributes = states
                .data_map
                .get::<Mutex<LayerSurfaceAttributes>>()
                .unwrap()
                .lock()
                .unwrap();
            if let Some(pending) = self.get_pending_state(&mut *attributes) {
                let configure = LayerSurfaceConfigure {
                    serial: SERIAL_COUNTER.next_serial(),
                    state: pending,
                };

                attributes.pending_configures.push(configure.clone());
                attributes.initial_configure_sent = true;

                Some(configure)
            } else {
                None
            }
        });

        // send surface configure
        if let Some(configure) = configure {
            let (width, height) = configure.state.size.unwrap_or_default().into();
            let serial = configure.serial;
            self.shell_surface
                .configure(serial.into(), width as u32, height as u32);
        }
    }

    /// Make sure this surface was configured
    ///
    /// Returns `true` if it was, if not, returns `false` and raise
    /// a protocol error to the associated layer surface. Also returns `false`
    /// if the surface is already destroyed.
    pub fn ensure_configured(&self, dh: &DisplayHandle) -> bool {
        let configured = compositor::with_states(&self.wl_surface, |states| {
            states
                .data_map
                .get::<Mutex<LayerSurfaceAttributes>>()
                .unwrap()
                .lock()
                .unwrap()
                .configured
        });
        if !configured {
            self.shell_surface.post_error(
                dh,
                zwlr_layer_shell_v1::Error::AlreadyConstructed,
                "layer_surface has never been configured",
            );
        }
        configured
    }

    /// Send a "close" event to the client
    pub fn send_close(&self) {
        self.shell_surface.closed()
    }

    /// Access the underlying `wl_surface` of this layer surface
    ///
    /// Returns `None` if the layer surface actually no longer exists.
    pub fn wl_surface(&self) -> &wl_surface::WlSurface {
        &self.wl_surface
    }

    /// Allows the pending state of this layer to
    /// be manipulated.
    ///
    /// This should be used to inform the client about size and state changes,
    /// for example after a resize request from the client.
    ///
    /// The state will be sent to the client when calling [`send_configure`](#method.send_configure).
    pub fn with_pending_state<F, T>(&self, f: F) -> T
    where
        F: FnOnce(&mut LayerSurfaceState) -> T,
    {
        compositor::with_states(&self.wl_surface, |states| {
            let mut attributes = states
                .data_map
                .get::<Mutex<LayerSurfaceAttributes>>()
                .unwrap()
                .lock()
                .unwrap();
            if attributes.server_pending.is_none() {
                attributes.server_pending = Some(attributes.current.clone());
            }

            let server_pending = attributes.server_pending.as_mut().unwrap();
            f(server_pending)
        })
    }

    /// Gets a copy of the current state of this layer
    ///
    /// Returns `None` if the underlying surface has been
    /// destroyed
    pub fn current_state(&self) -> LayerSurfaceState {
        compositor::with_states(&self.wl_surface, |states| {
            let attributes = states
                .data_map
                .get::<Mutex<LayerSurfaceAttributes>>()
                .unwrap()
                .lock()
                .unwrap();

            attributes.current.clone()
        })
    }
}

/// A configure message for layer surfaces
#[derive(Debug, Clone)]
pub struct LayerSurfaceConfigure {
    /// The state associated with this configure
    pub state: LayerSurfaceState,

    /// A serial number to track ACK from the client
    ///
    /// This should be an ever increasing number, as the ACK-ing
    /// from a client for a serial will validate all pending lower
    /// serials.
    pub serial: Serial,
}

/// Events generated by layer shell surfaces
///
/// Depending on what you want to do, you might ignore some of them
#[derive(Debug)]
pub enum LayerShellRequest {
    /// A new layer surface was created
    ///
    /// You likely need to send a [`LayerSurfaceConfigure`] to the surface, to hint the
    /// client as to how its layer surface should be sized.
    NewLayerSurface {
        /// the surface
        surface: LayerSurface,
        /// The output that the layer will be displayed on
        ///
        /// None means that the compositor should decide which output to use,
        /// Generally this will be the one that the user most recently interacted with
        output: Option<WlOutput>,
        /// This values indicate on which layer a surface should be rendered on
        layer: Layer,
        /// namespace that defines the purpose of the layer surface
        namespace: String,
    },

    /// A surface has acknowledged a configure serial.
    AckConfigure {
        /// The surface.
        surface: wl_surface::WlSurface,
        /// The configure serial.
        configure: LayerSurfaceConfigure,
    },
}

/// Macro to delegate implementation of wlr layer shell to [`WlrLayerShellState`].
///
/// You must also implement [`WlrLayerShellHandler`] to use this.
#[macro_export]
macro_rules! delegate_layer_shell {
    ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
        type __ZwlrLayerShellV1 =
            $crate::reexports::wayland_protocols_wlr::layer_shell::v1::server::zwlr_layer_shell_v1::ZwlrLayerShellV1;
        type __ZwlrLayerShellSurfaceV1 =
            $crate::reexports::wayland_protocols_wlr::layer_shell::v1::server::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;

        $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            __ZwlrLayerShellV1: ()
        ] => $crate::wayland::shell::wlr_layer::WlrLayerShellState);
        $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            __ZwlrLayerShellSurfaceV1: $crate::wayland::shell::wlr_layer::WlrLayerSurfaceUserData
        ] => $crate::wayland::shell::wlr_layer::WlrLayerShellState);

        $crate::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            __ZwlrLayerShellV1: ()
        ] => $crate::wayland::shell::wlr_layer::WlrLayerShellState);
    };
}
<commit_msg>layer_shell: expose known layer surfaces<commit_after>//! Utilities for handling shell surfaces with the `wlr_layer_shell` protocol
//!
//! This interface should be suitable for the implementation of many desktop shell components,
//! and a broad number of other applications that interact with the desktop.
//!
//! ### Initialization
//!
//! To initialize this handler, simple use the [`wlr_layer_shell_init`] function provided in this module.
//! You need to provide a closure that will be invoked whenever some action is required from you,
//! are represented by the [`LayerShellRequest`] enum.
//!
//! ```no_run
//! # extern crate wayland_server;
//! #
//! use smithay::wayland::shell::wlr_layer::{wlr_layer_shell_init, LayerShellRequest};
//!
//! # let mut display = wayland_server::Display::new();
//! let (shell_state, _) = wlr_layer_shell_init(
//!     &mut display,
//!     // your implementation
//!     |event: LayerShellRequest, dispatch_data| { /* handle the shell requests here */ },
//!     None  // put a logger if you want
//! );
//!
//! // You're now ready to go!
//! ```

use std::sync::{Arc, Mutex};

use wayland_protocols_wlr::layer_shell::v1::server::{
    zwlr_layer_shell_v1::{self, ZwlrLayerShellV1},
    zwlr_layer_surface_v1,
};
use wayland_server::{
    backend::GlobalId,
    protocol::{wl_output::WlOutput, wl_surface},
    DisplayHandle, GlobalDispatch, Resource,
};

use crate::{
    utils::{alive_tracker::IsAlive, Logical, Size},
    wayland::{
        compositor::{self, Cacheable},
        Serial, SERIAL_COUNTER,
    },
};

mod handlers;
mod types;

pub use handlers::WlrLayerSurfaceUserData;
pub use types::{Anchor, ExclusiveZone, KeyboardInteractivity, Layer, Margins};

/// The role of a wlr_layer_shell_surface
pub const LAYER_SURFACE_ROLE: &str = "zwlr_layer_surface_v1";

/// Attributes for layer surface
#[derive(Debug)]
pub struct LayerSurfaceAttributes {
    surface: zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
    /// Defines if the surface has received at least one
    /// layer_surface.ack_configure from the client
    pub configured: bool,
    /// The serial of the last acked configure
    pub configure_serial: Option<Serial>,
    /// Holds the state if the surface has sent the initial
    /// configure event to the client. It is expected that
    /// during the first commit a initial
    /// configure event is sent to the client
    pub initial_configure_sent: bool,
    /// Holds the configures the server has sent out
    /// to the client waiting to be acknowledged by
    /// the client. All pending configures that are older
    /// than the acknowledged one will be discarded during
    /// processing layer_surface.ack_configure.
    pending_configures: Vec<LayerSurfaceConfigure>,
    /// Holds the pending state as set by the server.
    pub server_pending: Option<LayerSurfaceState>,
    /// Holds the last server_pending state that has been acknowledged
    /// by the client. This state should be cloned to the current
    /// during a commit.
    pub last_acked: Option<LayerSurfaceState>,
    /// Holds the current state of the layer after a successful
    /// commit.
    pub current: LayerSurfaceState,
}

impl LayerSurfaceAttributes {
    fn new(surface: zwlr_layer_surface_v1::ZwlrLayerSurfaceV1) -> Self {
        Self {
            surface,
            configured: false,
            configure_serial: None,
            initial_configure_sent: false,
            pending_configures: Vec::new(),
            server_pending: None,
            last_acked: None,
            current: Default::default(),
        }
    }

    fn ack_configure(&mut self, serial: Serial) -> Option<LayerSurfaceConfigure> {
        let configure = self
            .pending_configures
            .iter()
            .find(|configure| configure.serial == serial)
            .cloned()?;

        self.last_acked = Some(configure.state.clone());

        self.configured = true;
        self.configure_serial = Some(serial);
        self.pending_configures.retain(|c| c.serial > serial);
        Some(configure)
    }
}

/// State of a layer surface
#[derive(Debug, Default, Clone, PartialEq)]
pub struct LayerSurfaceState {
    /// The suggested size of the surface
    pub size: Option<Size<i32, Logical>>,
}

/// Represents the client pending state
#[derive(Debug, Default, Clone, Copy)]
pub struct LayerSurfaceCachedState {
    /// The size requested by the client
    pub size: Size<i32, Logical>,
    /// Anchor bitflags, describing how the layers surface should be positioned and sized
    pub anchor: Anchor,
    /// Descripton of exclusive zone
    pub exclusive_zone: ExclusiveZone,
    /// Describes distance from the anchor point of the output
    pub margin: Margins,
    /// Describes how keyboard events are delivered to this surface
    pub keyboard_interactivity: KeyboardInteractivity,
    /// The layer that the surface is rendered on
    pub layer: Layer,
}

impl Cacheable for LayerSurfaceCachedState {
    fn commit(&mut self, _dh: &DisplayHandle) -> Self {
        *self
    }
    fn merge_into(self, into: &mut Self, _dh: &DisplayHandle) {
        *into = self;
    }
}

/// Shell global state
///
/// This state allows you to retrieve a list of surfaces
/// currently known to the shell global.
#[derive(Debug, Clone)]
pub struct WlrLayerShellState {
    known_layers: Arc<Mutex<Vec<LayerSurface>>>,
    shell_global: GlobalId,
    _log: slog::Logger,
}

impl WlrLayerShellState {
    /// Create a new `wlr_layer_shell` globals
    pub fn new<L, D>(display: &DisplayHandle, logger: L) -> WlrLayerShellState
    where
        L: Into<Option<::slog::Logger>>,
        D: GlobalDispatch<ZwlrLayerShellV1, ()>,
        D: 'static,
    {
        let log = crate::slog_or_fallback(logger);

        let shell_global = display.create_global::<D, ZwlrLayerShellV1, _>(4, ());

        WlrLayerShellState {
            known_layers: Default::default(),
            shell_global,
            _log: log.new(slog::o!("smithay_module" => "layer_shell_handler")),
        }
    }

    /// Get shell global id
    pub fn shell_global(&self) -> GlobalId {
        self.shell_global.clone()
    }

    /// Access all the shell surfaces known by this handler
    pub fn layer_surfaces(&self) -> impl Iterator<Item = LayerSurface> {
        self.known_layers.lock().unwrap().clone().into_iter()
    }
}

/// Handler for wlr layer shell
pub trait WlrLayerShellHandler {
    /// [WlrLayerShellState] getter
    fn shell_state(&mut self) -> &mut WlrLayerShellState;

    /// Layer shell request
    fn request(&mut self, dh: &DisplayHandle, request: LayerShellRequest);
}

/// A handle to a layer surface
#[derive(Debug, Clone)]
pub struct LayerSurface {
    wl_surface: wl_surface::WlSurface,
    shell_surface: zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
}

impl std::cmp::PartialEq for LayerSurface {
    fn eq(&self, other: &Self) -> bool {
        self.wl_surface == other.wl_surface
    }
}

impl LayerSurface {
    /// Checks if the surface is still alive
    pub fn alive(&self) -> bool {
        self.wl_surface.alive() && self.shell_surface.alive()
    }

    /// Gets the current pending state for a configure
    ///
    /// Returns `Some` if either no initial configure has been sent or
    /// the `server_pending` is `Some` and different from the last pending
    /// configure or `last_acked` if there is no pending
    ///
    /// Returns `None` if either no `server_pending` or the pending
    /// has already been sent to the client or the pending is equal
    /// to the `last_acked`
    fn get_pending_state(&self, attributes: &mut LayerSurfaceAttributes) -> Option<LayerSurfaceState> {
        if !attributes.initial_configure_sent {
            return Some(attributes.server_pending.take().unwrap_or_default());
        }

        let server_pending = match attributes.server_pending.take() {
            Some(state) => state,
            None => {
                return None;
            }
        };

        let last_state = attributes
            .pending_configures
            .last()
            .map(|c| &c.state)
            .or(attributes.last_acked.as_ref());

        if let Some(state) = last_state {
            if state == &server_pending {
                return None;
            }
        }

        Some(server_pending)
    }

    /// Send a configure event to this layer surface to suggest it a new configuration
    ///
    /// The serial of this configure will be tracked waiting for the client to ACK it.
    ///
    /// You can manipulate the state that will be sent to the client with the [`with_pending_state`](#method.with_pending_state)
    /// method.
    pub fn send_configure(&self) {
        let configure = compositor::with_states(&self.wl_surface, |states| {
            let mut attributes = states
                .data_map
                .get::<Mutex<LayerSurfaceAttributes>>()
                .unwrap()
                .lock()
                .unwrap();
            if let Some(pending) = self.get_pending_state(&mut *attributes) {
                let configure = LayerSurfaceConfigure {
                    serial: SERIAL_COUNTER.next_serial(),
                    state: pending,
                };

                attributes.pending_configures.push(configure.clone());
                attributes.initial_configure_sent = true;

                Some(configure)
            } else {
                None
            }
        });

        // send surface configure
        if let Some(configure) = configure {
            let (width, height) = configure.state.size.unwrap_or_default().into();
            let serial = configure.serial;
            self.shell_surface
                .configure(serial.into(), width as u32, height as u32);
        }
    }

    /// Make sure this surface was configured
    ///
    /// Returns `true` if it was, if not, returns `false` and raise
    /// a protocol error to the associated layer surface. Also returns `false`
    /// if the surface is already destroyed.
    pub fn ensure_configured(&self, dh: &DisplayHandle) -> bool {
        let configured = compositor::with_states(&self.wl_surface, |states| {
            states
                .data_map
                .get::<Mutex<LayerSurfaceAttributes>>()
                .unwrap()
                .lock()
                .unwrap()
                .configured
        });
        if !configured {
            self.shell_surface.post_error(
                dh,
                zwlr_layer_shell_v1::Error::AlreadyConstructed,
                "layer_surface has never been configured",
            );
        }
        configured
    }

    /// Send a "close" event to the client
    pub fn send_close(&self) {
        self.shell_surface.closed()
    }

    /// Access the underlying `wl_surface` of this layer surface
    ///
    /// Returns `None` if the layer surface actually no longer exists.
    pub fn wl_surface(&self) -> &wl_surface::WlSurface {
        &self.wl_surface
    }

    /// Allows the pending state of this layer to
    /// be manipulated.
    ///
    /// This should be used to inform the client about size and state changes,
    /// for example after a resize request from the client.
    ///
    /// The state will be sent to the client when calling [`send_configure`](#method.send_configure).
    pub fn with_pending_state<F, T>(&self, f: F) -> T
    where
        F: FnOnce(&mut LayerSurfaceState) -> T,
    {
        compositor::with_states(&self.wl_surface, |states| {
            let mut attributes = states
                .data_map
                .get::<Mutex<LayerSurfaceAttributes>>()
                .unwrap()
                .lock()
                .unwrap();
            if attributes.server_pending.is_none() {
                attributes.server_pending = Some(attributes.current.clone());
            }

            let server_pending = attributes.server_pending.as_mut().unwrap();
            f(server_pending)
        })
    }

    /// Gets a copy of the current state of this layer
    ///
    /// Returns `None` if the underlying surface has been
    /// destroyed
    pub fn current_state(&self) -> LayerSurfaceState {
        compositor::with_states(&self.wl_surface, |states| {
            let attributes = states
                .data_map
                .get::<Mutex<LayerSurfaceAttributes>>()
                .unwrap()
                .lock()
                .unwrap();

            attributes.current.clone()
        })
    }
}

/// A configure message for layer surfaces
#[derive(Debug, Clone)]
pub struct LayerSurfaceConfigure {
    /// The state associated with this configure
    pub state: LayerSurfaceState,

    /// A serial number to track ACK from the client
    ///
    /// This should be an ever increasing number, as the ACK-ing
    /// from a client for a serial will validate all pending lower
    /// serials.
    pub serial: Serial,
}

/// Events generated by layer shell surfaces
///
/// Depending on what you want to do, you might ignore some of them
#[derive(Debug)]
pub enum LayerShellRequest {
    /// A new layer surface was created
    ///
    /// You likely need to send a [`LayerSurfaceConfigure`] to the surface, to hint the
    /// client as to how its layer surface should be sized.
    NewLayerSurface {
        /// the surface
        surface: LayerSurface,
        /// The output that the layer will be displayed on
        ///
        /// None means that the compositor should decide which output to use,
        /// Generally this will be the one that the user most recently interacted with
        output: Option<WlOutput>,
        /// This values indicate on which layer a surface should be rendered on
        layer: Layer,
        /// namespace that defines the purpose of the layer surface
        namespace: String,
    },

    /// A surface has acknowledged a configure serial.
    AckConfigure {
        /// The surface.
        surface: wl_surface::WlSurface,
        /// The configure serial.
        configure: LayerSurfaceConfigure,
    },
}

/// Macro to delegate implementation of wlr layer shell to [`WlrLayerShellState`].
///
/// You must also implement [`WlrLayerShellHandler`] to use this.
#[macro_export]
macro_rules! delegate_layer_shell {
    ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
        type __ZwlrLayerShellV1 =
            $crate::reexports::wayland_protocols_wlr::layer_shell::v1::server::zwlr_layer_shell_v1::ZwlrLayerShellV1;
        type __ZwlrLayerShellSurfaceV1 =
            $crate::reexports::wayland_protocols_wlr::layer_shell::v1::server::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;

        $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            __ZwlrLayerShellV1: ()
        ] => $crate::wayland::shell::wlr_layer::WlrLayerShellState);
        $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            __ZwlrLayerShellSurfaceV1: $crate::wayland::shell::wlr_layer::WlrLayerSurfaceUserData
        ] => $crate::wayland::shell::wlr_layer::WlrLayerShellState);

        $crate::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            __ZwlrLayerShellV1: ()
        ] => $crate::wayland::shell::wlr_layer::WlrLayerShellState);
    };
}
<|endoftext|>


<commit_before>//! Module for [DumbBuffer](https://01.org/linuxgraphics/gfx-docs/drm/gpu/drm-kms.html#dumb-buffer-objects) buffers

use std::fmt;
use std::os::unix::io::AsRawFd;
use std::sync::Arc;

use drm::buffer::Buffer as DrmBuffer;
use drm::control::{dumbbuffer::DumbBuffer as Handle, Device as ControlDevice};

use super::{Allocator, Buffer, Format, Fourcc, Modifier};
use crate::backend::drm::device::{DrmDevice, DrmDeviceInternal, FdWrapper};
use crate::utils::{Buffer as BufferCoords, Size};

/// Wrapper around raw DumbBuffer handles.
pub struct DumbBuffer<A: AsRawFd + 'static> {
    fd: Arc<FdWrapper<A>>,
    handle: Handle,
    format: Format,
}

impl<A: AsRawFd + 'static> fmt::Debug for DumbBuffer<A> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("DumbBuffer")
            .field("handle", &self.handle)
            .field("format", &self.format)
            .finish()
    }
}

impl<A: AsRawFd + 'static> Allocator<DumbBuffer<A>> for DrmDevice<A> {
    type Error = drm::SystemError;

    fn create_buffer(
        &mut self,
        width: u32,
        height: u32,
        fourcc: Fourcc,
        modifiers: &[Modifier],
    ) -> Result<DumbBuffer<A>, Self::Error> {
        // dumb buffers are always linear
        if modifiers
            .iter()
            .all(|&x| x != Modifier::Invalid && x != Modifier::Linear)
        {
            return Err(drm::SystemError::InvalidArgument);
        }

        let handle = self.create_dumb_buffer((width, height), fourcc, 32 /* TODO */)?;

        Ok(DumbBuffer {
            fd: match &*self.internal {
                DrmDeviceInternal::Atomic(dev) => dev.fd.clone(),
                DrmDeviceInternal::Legacy(dev) => dev.fd.clone(),
            },
            handle,
            format: Format {
                code: fourcc,
                modifier: Modifier::Linear,
            },
        })
    }
}

impl<A: AsRawFd + 'static> Buffer for DumbBuffer<A> {
    fn size(&self) -> Size<i32, BufferCoords> {
        let (w, h) = self.handle.size();
        (w as i32, h as i32).into()
    }

    fn format(&self) -> Format {
        self.format
    }
}

impl<A: AsRawFd + 'static> DumbBuffer<A> {
    /// Raw handle to the underlying buffer.
    ///
    /// Note: This handle will become invalid, once the `DumbBuffer` wrapper is dropped
    /// or the device used to create is closed. Do not copy this handle and assume it keeps being valid.
    pub fn handle(&self) -> &Handle {
        &self.handle
    }
}

impl<A: AsRawFd + 'static> Drop for DumbBuffer<A> {
    fn drop(&mut self) {
        let _ = self.fd.destroy_dumb_buffer(self.handle);
    }
}
<commit_msg>dumballocator: Don't hardcode bpp<commit_after>//! Module for [DumbBuffer](https://01.org/linuxgraphics/gfx-docs/drm/gpu/drm-kms.html#dumb-buffer-objects) buffers

use std::fmt;
use std::os::unix::io::AsRawFd;
use std::sync::Arc;

use drm::buffer::Buffer as DrmBuffer;
use drm::control::{dumbbuffer::DumbBuffer as Handle, Device as ControlDevice};

use super::{format::get_bpp, Allocator, Buffer, Format, Fourcc, Modifier};
use crate::backend::drm::device::{DrmDevice, DrmDeviceInternal, FdWrapper};
use crate::utils::{Buffer as BufferCoords, Size};

/// Wrapper around raw DumbBuffer handles.
pub struct DumbBuffer<A: AsRawFd + 'static> {
    fd: Arc<FdWrapper<A>>,
    handle: Handle,
    format: Format,
}

impl<A: AsRawFd + 'static> fmt::Debug for DumbBuffer<A> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("DumbBuffer")
            .field("handle", &self.handle)
            .field("format", &self.format)
            .finish()
    }
}

impl<A: AsRawFd + 'static> Allocator<DumbBuffer<A>> for DrmDevice<A> {
    type Error = drm::SystemError;

    fn create_buffer(
        &mut self,
        width: u32,
        height: u32,
        fourcc: Fourcc,
        modifiers: &[Modifier],
    ) -> Result<DumbBuffer<A>, Self::Error> {
        // dumb buffers are always linear
        if modifiers
            .iter()
            .all(|&x| x != Modifier::Invalid && x != Modifier::Linear)
        {
            return Err(drm::SystemError::InvalidArgument);
        }

        let handle = self.create_dumb_buffer(
            (width, height),
            fourcc,
            get_bpp(fourcc).ok_or(drm::SystemError::InvalidArgument)? as u32,
        )?;

        Ok(DumbBuffer {
            fd: match &*self.internal {
                DrmDeviceInternal::Atomic(dev) => dev.fd.clone(),
                DrmDeviceInternal::Legacy(dev) => dev.fd.clone(),
            },
            handle,
            format: Format {
                code: fourcc,
                modifier: Modifier::Linear,
            },
        })
    }
}

impl<A: AsRawFd + 'static> Buffer for DumbBuffer<A> {
    fn size(&self) -> Size<i32, BufferCoords> {
        let (w, h) = self.handle.size();
        (w as i32, h as i32).into()
    }

    fn format(&self) -> Format {
        self.format
    }
}

impl<A: AsRawFd + 'static> DumbBuffer<A> {
    /// Raw handle to the underlying buffer.
    ///
    /// Note: This handle will become invalid, once the `DumbBuffer` wrapper is dropped
    /// or the device used to create is closed. Do not copy this handle and assume it keeps being valid.
    pub fn handle(&self) -> &Handle {
        &self.handle
    }
}

impl<A: AsRawFd + 'static> Drop for DumbBuffer<A> {
    fn drop(&mut self) {
        let _ = self.fd.destroy_dumb_buffer(self.handle);
    }
}
<|endoftext|>


<commit_before>#![crate_name = "spellck_standalone"]
#![deny(missing_docs)]
#![feature(os, io, rustc_private)]

//! Prints the misspelled words in the public documentation &
//! identifiers of a crate.

extern crate getopts;
extern crate arena;
extern crate syntax;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_trans;

extern crate spellck;

use std::os;
use std::old_io as io;
use std::cell::Cell;
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet, BinaryHeap};
use arena::TypedArena;
use syntax::{ast, ast_map};
use syntax::codemap::{Span, BytePos};
use rustc::middle::{privacy, ty};
use rustc::session::search_paths::SearchPaths;
use rustc::session::{self, config};
use rustc_driver::driver;

use spellck::visitor::SpellingVisitor;

static DEFAULT_DICT: &'static str = "/usr/share/dict/words";
static LIBDIR: &'static str = "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib";

fn main() {
    let args = os::args();
    let opts = &[getopts::optmulti("d", "dict",
                                  "dictionary file (a list of words, one per line)", "PATH"),
                getopts::optflag("n", "no-def-dict", "don't use the default dictionary"),
                getopts::optflag("h", "help", "show this help message")];

    let matches = getopts::getopts(args.tail(), opts).unwrap();
    if matches.opt_present("help") {
        println!("{}", getopts::usage(args[0].as_slice(), opts));
        return;
    }

    let mut words = HashSet::new();

    if !matches.opt_present("no-def-dict") {
        if !read_lines_into(&Path::new(DEFAULT_DICT), &mut words) {
            return
        }
    }
    for dict in matches.opt_strs("d").into_iter().chain(matches.opt_strs("dict").into_iter()) {
        if !read_lines_into(&Path::new(dict), &mut words) {
            return
        }
    }

    let mut search_paths = SearchPaths::new();
    search_paths.add_path(LIBDIR);
    let externs = HashMap::new();

    // one visitor; the internal list of misspelled words gets reset
    // for each file, since the spans could conflict.
    let any_mistakes = Cell::new(false);

    for name in matches.free.iter() {
        get_ast(Path::new(name), search_paths.clone(), externs.clone(),
                |sess, krate, export, _public| {
            let cm = sess.codemap();

            let mut visitor = SpellingVisitor::new(&words, export);
            visitor.check_crate(krate);

            struct Sort<'a> {
                sp: Span,
                words: &'a Vec<String>
            }
            impl<'a> PartialEq for Sort<'a> {
                fn eq(&self, other: &Sort<'a>) -> bool {
                    self.sp == other.sp
                }
            }
            impl<'a> PartialOrd for Sort<'a> {
                fn partial_cmp(&self, other: &Sort<'a>) -> Option<Ordering> {
                    Some(self.cmp(other))
                }
            }
            impl<'a> Eq for Sort<'a> {}
            impl<'a> Ord for Sort<'a> {
                fn cmp(&self, other: &Sort<'a>) -> Ordering {
                    let Span { lo: BytePos(slo), hi: BytePos(shi), .. } = self.sp;
                    let Span { lo: BytePos(olo), hi: BytePos(ohi), .. } = other.sp;
                    (slo, shi).cmp(&(olo, ohi))
                }
            }

            // extract the lines in order of the spans, so that e.g. files
            // are grouped together, and lines occur in increasing order.
            let pq: BinaryHeap<Sort> =
                visitor.misspellings.iter().map(|(pos, v)| Sort { sp: pos.span, words: v }).collect();

            // run through the spans, printing the words that are
            // apparently misspelled
            for Sort {sp, words} in pq.into_sorted_vec().into_iter() {
                any_mistakes.set(true);

                let lines = cm.span_to_lines(sp);
                let sp_text = cm.span_to_string(sp);

                // [] required for connect :(
                let word_vec: Vec<&str> = words.iter().map(|s| &s[]).collect();

                println!("{}: misspelled {words}: {}",
                         sp_text,
                         word_vec.connect(", "),
                         words = if words.len() == 1 {"word"} else {"words"});

                // first line; no lines = no printing
                match &lines.lines[] {
                    [line_num, ..] => {
                        if let Some(line) = lines.file.get_line(line_num) {
                            println!("{}: {}", sp_text, line);
                        }
                    }
                    _ => {}
                }
            }
        })
    }

    if any_mistakes.get() {
        os::set_exit_status(1)
    }
}

/// Load each line of the file `p` into the given `Extend` object.
fn read_lines_into<E: Extend<String>>
                  (p: &Path, e: &mut E) -> bool {
    match io::File::open(p) {
        Ok(mut r) => {
            let s = String::from_utf8(r.read_to_end().unwrap())
                .ok().expect(&format!("{} is not UTF-8", p.display())[]);
            e.extend(s.lines().map(|ss| ss.to_string()));
            true
        }
        Err(e) => {
            let mut stderr = io::stderr();
            (write!(&mut stderr as &mut Writer,
                    "Error reading {}: {}", p.display(), e)).unwrap();
            os::set_exit_status(10);
            false
        }
    }
}

type Externs = HashMap<String, Vec<String>>;

/// Extract the expanded ast of a crate, along with the codemap which
/// connects source code locations to the actual code.
/// Extract the expanded ast of a krate, along with the codemap which
/// connects source code locations to the actual code.
fn get_ast<F>(path: Path,
              search_paths: SearchPaths, externs: Externs,
              f: F)
        where F: Fn(&session::Session, &ast::Crate,
                    &privacy::ExportedItems, &privacy::PublicItems) {
    use syntax::diagnostic;
    use rustc_trans::back::link;

    // cargo culted from rustdoc_ng :(
    let input = config::Input::File(path);

    let sessopts = config::Options {
        maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
        externs: externs,
        search_paths: search_paths,
        .. config::basic_options().clone()
    };

    let codemap = syntax::codemap::CodeMap::new();
    let diagnostic_handler =
        diagnostic::default_handler(diagnostic::Auto, None, true);
    let span_diagnostic_handler =
        diagnostic::mk_span_handler(diagnostic_handler, codemap);

    let sess = session::build_session_(sessopts, None, span_diagnostic_handler);

    let cfg = config::build_configuration(&sess);

    let mut controller = driver::CompileController::basic();
    controller.after_analysis = driver::PhaseController {
        stop: true,
        callback: Box::new(|state| {
            let ca = state.analysis.unwrap();
            let ty::CrateAnalysis { ref exported_items, ref public_items, ref ty_cx, .. } = *ca;
            f(&ty_cx.sess, ty_cx.map.krate(), exported_items, public_items)
        })
    };

    driver::compile_input(sess, cfg, &input, &None, &None, None, controller);
}
<commit_msg>Update standalone to (30e1f9a1c 2015-03-14) (built 2015-03-15).<commit_after>#![crate_name = "spellck_standalone"]
#![deny(missing_docs)]
#![feature(rustc_private)]
#![feature(collections, exit_status, std_misc)]

//! Prints the misspelled words in the public documentation &
//! identifiers of a crate.

extern crate getopts;
extern crate arena;
extern crate syntax;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_trans;

#[allow(plugin_as_library)]
extern crate spellck;

use std::env;
use std::path::{AsPath, PathBuf};
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::cell::Cell;
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet, BinaryHeap};
use syntax::ast;
use syntax::codemap::{Span, BytePos};
use syntax::diagnostics;
use rustc::middle::{privacy, ty};
use rustc::session::{self, config};
use rustc_driver::{driver, pretty, Compilation};

use spellck::visitor::SpellingVisitor;

static DEFAULT_DICT: &'static str = "/usr/share/dict/words";
static LIBDIR: &'static str = "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib";

fn main() {
    let args = env::args().collect::<Vec<_>>();
    let opts = &[getopts::optmulti("d", "dict",
                                  "dictionary file (a list of words, one per line)", "PATH"),
                getopts::optflag("n", "no-def-dict", "don't use the default dictionary"),
                getopts::optflag("h", "help", "show this help message")];

    let matches = getopts::getopts(args.tail(), opts).unwrap();
    if matches.opt_present("help") {
        println!("{}", getopts::usage(&args[0], opts));
        return;
    }

    let mut words = HashSet::new();

    if !matches.opt_present("no-def-dict") {
        if !read_lines_into(DEFAULT_DICT, &mut words) {
            return
        }
    }
    for dict in matches.opt_strs("d").into_iter().chain(matches.opt_strs("dict").into_iter()) {
        if !read_lines_into(&dict, &mut words) {
            return
        }
    }

    // one visitor; the internal list of misspelled words gets reset
    // for each file, since the spans could conflict.
    let any_mistakes = Cell::new(false);

    for name in matches.free {
        get_ast(name,
                |sess, krate, export, _public| {
            let cm = sess.codemap();

            let mut visitor = SpellingVisitor::new(&words, export);
            visitor.check_crate(krate);

            struct Sort<'a> {
                sp: Span,
                words: &'a Vec<String>
            }
            impl<'a> PartialEq for Sort<'a> {
                fn eq(&self, other: &Sort<'a>) -> bool {
                    self.sp == other.sp
                }
            }
            impl<'a> PartialOrd for Sort<'a> {
                fn partial_cmp(&self, other: &Sort<'a>) -> Option<Ordering> {
                    Some(self.cmp(other))
                }
            }
            impl<'a> Eq for Sort<'a> {}
            impl<'a> Ord for Sort<'a> {
                fn cmp(&self, other: &Sort<'a>) -> Ordering {
                    let Span { lo: BytePos(slo), hi: BytePos(shi), .. } = self.sp;
                    let Span { lo: BytePos(olo), hi: BytePos(ohi), .. } = other.sp;
                    (slo, shi).cmp(&(olo, ohi))
                }
            }

            // extract the lines in order of the spans, so that e.g. files
            // are grouped together, and lines occur in increasing order.
            let pq: BinaryHeap<Sort> =
                visitor.misspellings.iter().map(|(pos, v)| Sort { sp: pos.span, words: v }).collect();

            // run through the spans, printing the words that are
            // apparently misspelled
            for Sort {sp, words} in pq.into_sorted_vec().into_iter() {
                any_mistakes.set(true);

                let lines = cm.span_to_lines(sp);
                let sp_text = cm.span_to_string(sp);

                // [] required for connect :(
                let word_vec: Vec<&str> = words.iter().map(|s| &**s).collect();

                println!("{}: misspelled {words}: {}",
                         sp_text,
                         word_vec.connect(", "),
                         words = if words.len() == 1 {"word"} else {"words"});

                // first line; no lines = no printing
                match &*lines.lines {
                    [line_num, ..] => {
                        if let Some(line) = lines.file.get_line(line_num) {
                            println!("{}: {}", sp_text, line);
                        }
                    }
                    _ => {}
                }
            }
        })
    }

    if any_mistakes.get() {
        env::set_exit_status(1)
    }
}

/// Load each line of the file `p` into the given `Extend` object.
fn read_lines_into<P: AsPath + ::std::fmt::Debug + ?Sized, E: Extend<String>>
                  (p: &P, e: &mut E) -> bool {
    match File::open(p) {
        Ok(mut r) => {
            let mut s = String::new();
            r.read_to_string(&mut s).unwrap();
            e.extend(s.lines().map(|ss| ss.to_string()));
            true
        }
        Err(e) => {
            let mut stderr = io::stderr();
            (write!(&mut stderr,
                    "Error reading {:?}: {}", p, e)).unwrap();
            env::set_exit_status(10);
            false
        }
    }
}

type Externs = HashMap<String, Vec<String>>;

struct Calls<F> {
    f: Option<F>
}

impl<'a, F> rustc_driver::CompilerCalls<'a> for Calls<F>
    where F: 'a + Fn(&session::Session, &ast::Crate,
                     &privacy::ExportedItems, &privacy::PublicItems)
{
    fn early_callback(&mut self,
                      _matches: &getopts::Matches,
                      _descriptions: &diagnostics::registry::Registry)
                      -> Compilation {
        Compilation::Continue
    }

    fn no_input(&mut self,
                _matches: &getopts::Matches,
                _sopts: &config::Options,
                _odir: &Option<PathBuf>,
                _ofile: &Option<PathBuf>,
                _descriptions: &diagnostics::registry::Registry)
                -> Option<(config::Input, Option<PathBuf>)> {
        unreachable!()
    }

    fn parse_pretty(&mut self,
                    _sess: &session::Session,
                    _matches: &getopts::Matches)
                    -> Option<(pretty::PpMode, Option<pretty::UserIdentifiedItem>)> {
        None
    }

    fn late_callback(&mut self,
                     matches: &getopts::Matches,
                     sess: &session::Session,
                     input: &config::Input,
                     odir: &Option<PathBuf>,
                     ofile: &Option<PathBuf>)
                     -> Compilation {
        rustc_driver::RustcDefaultCalls.late_callback(matches, sess, input, odir, ofile)
    }

    fn build_controller(&mut self, _sess: &session::Session) -> driver::CompileController<'a> {
        let f = self.f.take().unwrap();
        let mut controller = driver::CompileController::basic();
        controller.after_analysis = driver::PhaseController {
            stop: rustc_driver::Compilation::Stop,
            callback: Box::new(move |state| {
                let ca = state.analysis.unwrap();
                let ty::CrateAnalysis { ref exported_items, ref public_items, ref ty_cx, .. } = *ca;
                f(&ty_cx.sess, ty_cx.map.krate(), exported_items, public_items)
            })
        };
        controller
    }
}

/// Extract the expanded ast of a krate, along with the codemap which
/// connects source code locations to the actual code.
#[allow(deprecated)]
fn get_ast<F>(path: String,
              f: F)
        where F: Fn(&session::Session, &ast::Crate,
                    &privacy::ExportedItems, &privacy::PublicItems)
{
    let mut calls = Calls { f: Some(f) };
    rustc_driver::run_compiler(&[format!("-L{}", LIBDIR), path], &mut calls);
}
<|endoftext|>


<commit_before>use bot::BotEnv;
use listeners::{Timeouts, PollTagger, AutoReplyListener, ReactionAuthorize};
use commands::*;

use lalafell::listeners::CommandListener;

use serenity::prelude::RwLock;
use serenity::client::{EventHandler, Context};
use serenity::model::id::GuildId;
use serenity::model::event::MessageUpdateEvent;
use serenity::model::channel::{Message, GuildChannel, Reaction};
use serenity::model::guild::Member;
use serenity::model::gateway::Ready;

use std::sync::Arc;

pub struct Handler {
  env: Arc<BotEnv>,
  listeners: Vec<Box<EventHandler + Send + Sync>>
}

impl Handler {
  pub fn new(env: Arc<BotEnv>) -> Self {
    let listeners: Vec<Box<EventHandler + Send + Sync>> = vec![
      box command_listener(&env),
      box ReactionAuthorize,
      box Timeouts,
      box PollTagger,
      box AutoReplyListener::default()
    ];
    Handler {
      env,
      listeners
    }
  }
}

impl EventHandler for Handler {
  fn message(&self, ctx: Context, msg: Message) {
    for listener in &self.listeners {
      listener.message(ctx.clone(), msg.clone());
    }
  }

  fn message_update(&self, ctx: Context, update: MessageUpdateEvent) {
    for listener in &self.listeners {
      listener.message_update(ctx.clone(), update.clone());
    }
  }

  fn guild_member_addition(&self, ctx: Context, guild: GuildId, member: Member) {
    for listener in &self.listeners {
      listener.guild_member_addition(ctx.clone(), guild, member.clone());
    }
  }

  fn reaction_add(&self, ctx: Context, reaction: Reaction) {
    for listener in &self.listeners {
      listener.reaction_add(ctx.clone(), reaction.clone());
    }
  }

  fn reaction_remove(&self, ctx: Context, reaction: Reaction) {
    for listener in &self.listeners {
      listener.reaction_remove(ctx.clone(), reaction.clone());
    }
  }

  fn channel_create(&self, ctx: Context, channel: Arc<RwLock<GuildChannel>>) {
    for listener in &self.listeners {
      listener.channel_create(ctx.clone(), Arc::clone(&channel));
    }
  }

  fn ready(&self, ctx: Context, _: Ready) {
    if let Some(g) = ::tasks::random_presence::random_game(self.env.as_ref()) {
      ctx.shard.set_game(Some(g));
    }
  }
}

macro_rules! command_listener {
  (env => $env:expr, $($($alias:expr),+ => $name:ident),+) => {{
    let mut command_listener = CommandListener::default();
    $(
      command_listener.add_command(&[$($alias),*], box $name::new(Arc::clone(&$env)));
    )*
    command_listener
  }}
}

fn command_listener<'a>(env: &Arc<BotEnv>) -> CommandListener<'a> {
  command_listener! {
    env => env,
    "race" => RaceCommand,
    "tag" => TagCommand,
    "autotag" => AutoTagCommand,
    "viewtag" => ViewTagCommand,
    "updatetags" => UpdateTagsCommand,
    "updatetag" => UpdateTagCommand,
    "verify" => VerifyCommand,
    "referencecount" => ReferenceCountCommand,
    "poll" => PollCommand,
    "pollresults" => PollResultsCommand,
    "timeout" => TimeoutCommand,
    "untimeout" => UntimeoutCommand,
    // "archive" => ArchiveCommand,
    "imagedump", "dump" => ImageDumpCommand,
    "configure", "config" => ConfigureCommand,
    "randomreaction", "reaction" => RandomReactionCommand,
    "search" => SearchCommand,
    "presence" => PresenceCommand,
    "ping" => PingCommand,
    "reload", "reloadconfig" => ReloadConfigCommand
  }
}
<commit_msg>feat: add !blob command<commit_after>use bot::BotEnv;
use listeners::{Timeouts, PollTagger, AutoReplyListener, ReactionAuthorize};
use commands::*;

use lalafell::listeners::CommandListener;

use serenity::prelude::RwLock;
use serenity::client::{EventHandler, Context};
use serenity::model::id::GuildId;
use serenity::model::event::MessageUpdateEvent;
use serenity::model::channel::{Message, GuildChannel, Reaction};
use serenity::model::guild::Member;
use serenity::model::gateway::Ready;

use std::sync::Arc;

pub struct Handler {
  env: Arc<BotEnv>,
  listeners: Vec<Box<EventHandler + Send + Sync>>
}

impl Handler {
  pub fn new(env: Arc<BotEnv>) -> Self {
    let listeners: Vec<Box<EventHandler + Send + Sync>> = vec![
      box command_listener(&env),
      box ReactionAuthorize,
      box Timeouts,
      box PollTagger,
      box AutoReplyListener::default()
    ];
    Handler {
      env,
      listeners
    }
  }
}

impl EventHandler for Handler {
  fn message(&self, ctx: Context, msg: Message) {
    for listener in &self.listeners {
      listener.message(ctx.clone(), msg.clone());
    }
  }

  fn message_update(&self, ctx: Context, update: MessageUpdateEvent) {
    for listener in &self.listeners {
      listener.message_update(ctx.clone(), update.clone());
    }
  }

  fn guild_member_addition(&self, ctx: Context, guild: GuildId, member: Member) {
    for listener in &self.listeners {
      listener.guild_member_addition(ctx.clone(), guild, member.clone());
    }
  }

  fn reaction_add(&self, ctx: Context, reaction: Reaction) {
    for listener in &self.listeners {
      listener.reaction_add(ctx.clone(), reaction.clone());
    }
  }

  fn reaction_remove(&self, ctx: Context, reaction: Reaction) {
    for listener in &self.listeners {
      listener.reaction_remove(ctx.clone(), reaction.clone());
    }
  }

  fn channel_create(&self, ctx: Context, channel: Arc<RwLock<GuildChannel>>) {
    for listener in &self.listeners {
      listener.channel_create(ctx.clone(), Arc::clone(&channel));
    }
  }

  fn ready(&self, ctx: Context, _: Ready) {
    if let Some(g) = ::tasks::random_presence::random_game(self.env.as_ref()) {
      ctx.shard.set_game(Some(g));
    }
  }
}

macro_rules! command_listener {
  (env => $env:expr, $($($alias:expr),+ => $name:ident),+) => {{
    let mut command_listener = CommandListener::default();
    $(
      command_listener.add_command(&[$($alias),*], box $name::new(Arc::clone(&$env)));
    )*
    command_listener
  }}
}

fn command_listener<'a>(env: &Arc<BotEnv>) -> CommandListener<'a> {
  command_listener! {
    env => env,
    "race" => RaceCommand,
    "tag" => TagCommand,
    "autotag" => AutoTagCommand,
    "viewtag" => ViewTagCommand,
    "updatetags" => UpdateTagsCommand,
    "updatetag" => UpdateTagCommand,
    "verify" => VerifyCommand,
    "referencecount" => ReferenceCountCommand,
    "poll" => PollCommand,
    "pollresults" => PollResultsCommand,
    "timeout" => TimeoutCommand,
    "untimeout" => UntimeoutCommand,
    // "archive" => ArchiveCommand,
    "imagedump", "dump" => ImageDumpCommand,
    "configure", "config" => ConfigureCommand,
    "randomreaction", "reaction" => RandomReactionCommand,
    "search" => SearchCommand,
    "presence" => PresenceCommand,
    "ping" => PingCommand,
    "reload", "reloadconfig" => ReloadConfigCommand,
    "blob" => BlobCommand
  }
}
<|endoftext|>


<commit_before>use core::fmt::Display;

use super::{dead_key::KlcDeadKeys, layout::KlcLayout, ligature::KlcLigature};

pub struct KlcFile {
    pub keyboard_name: String,
    pub copyright: String,
    pub company: String,
    pub layout: KlcLayout,
    pub ligature: KlcLigature,
    pub dead_keys: KlcDeadKeys,
}

impl Display for KlcFile {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("COPYRIGHT\t\"{}\"\n\n", self.copyright))?;
        f.write_fmt(format_args!("COMPANY\t\"{}\"\n\n", self.company))?;

        f.write_str("VERSION\t1.0\n\n")?;

        f.write_str(&self.layout.to_string())?;

        f.write_str(&self.ligature.to_string())?;

        f.write_str(&self.dead_keys.to_string())?;

        Ok(())
    }
}
<commit_msg>Add footer<commit_after>use core::fmt::Display;

use super::{dead_key::KlcDeadKeys, layout::KlcLayout, ligature::KlcLigature};

pub struct KlcFile {
    pub keyboard_name: String,
    pub copyright: String,
    pub company: String,
    pub layout: KlcLayout,
    pub ligature: KlcLigature,
    pub dead_keys: KlcDeadKeys,
}

impl Display for KlcFile {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("COPYRIGHT\t\"{}\"\n\n", self.copyright))?;
        f.write_fmt(format_args!("COMPANY\t\"{}\"\n\n", self.company))?;

        f.write_str("VERSION\t1.0\n\n")?;

        f.write_str(&self.layout.to_string())?;

        f.write_str(&self.ligature.to_string())?;

        f.write_str(&self.dead_keys.to_string())?;

        f.write_str(FOOTER_CONTENT)?;

        f.write_str("\nDESCRIPTIONS\n\n")?;

        Ok(())
    }
}

const FOOTER_CONTENT: &str = r#"
KEYNAME

01	Esc
0e	Backspace
0f	Tab
1c	Enter
1d	Ctrl
2a	Shift
36	"Right Shift"
37	"Num *"
38	Alt
39	Space
3a	"Caps Lock"
3b	F1
3c	F2
3d	F3
3e	F4
3f	F5
40	F6
41	F7
42	F8
43	F9
44	F10
45	Pause
46	"Scroll Lock"
47	"Num 7"
48	"Num 8"
49	"Num 9"
4a	"Num -"
4b	"Num 4"
4c	"Num 5"
4d	"Num 6"
4e	"Num +"
4f	"Num 1"
50	"Num 2"
51	"Num 3"
52	"Num 0"
53	"Num Del"
54	"Sys Req"
57	F11
58	F12
7c	F13
7d	F14
7e	F15
7f	F16
80	F17
81	F18
82	F19
83	F20
84	F21
85	F22
86	F23
87	F24

KEYNAME_EXT

1c	"Num Enter"
1d	"Right Ctrl"
35	"Num /"
37	"Prnt Scrn"
38	"Right Alt"
45	"Num Lock"
46	Break
47	Home
48	Up
49	"Page Up"
4b	Left
4d	Right
4f	End
50	Down
51	"Page Down"
52	Insert
53	Delete
54	<00>
56	Help
5b	"Left Windows"
5c	"Right Windows"
5d	Application
"#;
<|endoftext|>


<commit_before>#![cfg(unix)]

extern crate env_logger;
extern crate futures;
extern crate libc;
extern crate mio;
extern crate tokio;
extern crate tokio_io;

use std::fs::File;
use std::io::{self, Write};
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::thread;
use std::time::Duration;

use mio::event::Evented;
use mio::unix::{UnixReady, EventedFd};
use mio::{PollOpt, Ready, Token};
use tokio::reactor::{Handle, PollEvented};
use tokio_io::io::read_to_end;
use futures::Future;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
    })
}

struct MyFile(File);

impl MyFile {
    fn new(file: File) -> MyFile {
        unsafe {
            let r = libc::fcntl(file.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
            assert!(r != -1, "fcntl error: {}", io::Error::last_os_error());
        }
        MyFile(file)
    }
}

impl io::Read for MyFile {
    fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
        self.0.read(bytes)
    }
}

impl Evented for MyFile {
    fn register(&self, poll: &mio::Poll, token: Token, interest: Ready, opts: PollOpt)
                -> io::Result<()> {
        let hup: Ready = UnixReady::hup().into();
        EventedFd(&self.0.as_raw_fd()).register(poll, token, interest | hup, opts)
    }
    fn reregister(&self, poll: &mio::Poll, token: Token, interest: Ready, opts: PollOpt)
                  -> io::Result<()> {
        let hup: Ready = UnixReady::hup().into();
        EventedFd(&self.0.as_raw_fd()).reregister(poll, token, interest | hup, opts)
    }
    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        EventedFd(&self.0.as_raw_fd()).deregister(poll)
    }
}

#[test]
fn hup() {
    drop(env_logger::init());

    let handle = Handle::default();
    unsafe {
        let mut pipes = [0; 2];
        assert!(libc::pipe(pipes.as_mut_ptr()) != -1,
                "pipe error: {}", io::Error::last_os_error());
        let read = File::from_raw_fd(pipes[0]);
        let mut write = File::from_raw_fd(pipes[1]);
        let t = thread::spawn(move || {
            write.write_all(b"Hello!\n").unwrap();
            write.write_all(b"Good bye!\n").unwrap();
            thread::sleep(Duration::from_millis(100));
        });

        let source = PollEvented::new(MyFile::new(read), &handle).unwrap();

        let reader = read_to_end(source, Vec::new());
        let (_, content) = t!(reader.wait());
        assert_eq!(&b"Hello!\nGood bye!\n"[..], &content[..]);
        t.join().unwrap();
    }
}
<commit_msg>Fix deprecation warnings in tests (#167)<commit_after>#![cfg(unix)]

extern crate env_logger;
extern crate futures;
extern crate libc;
extern crate mio;
extern crate tokio;
extern crate tokio_io;

use std::fs::File;
use std::io::{self, Write};
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::thread;
use std::time::Duration;

use mio::event::Evented;
use mio::unix::{UnixReady, EventedFd};
use mio::{PollOpt, Ready, Token};
use tokio::reactor::{Handle, PollEvented2};
use tokio_io::io::read_to_end;
use futures::Future;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
    })
}

struct MyFile(File);

impl MyFile {
    fn new(file: File) -> MyFile {
        unsafe {
            let r = libc::fcntl(file.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
            assert!(r != -1, "fcntl error: {}", io::Error::last_os_error());
        }
        MyFile(file)
    }
}

impl io::Read for MyFile {
    fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
        self.0.read(bytes)
    }
}

impl Evented for MyFile {
    fn register(&self, poll: &mio::Poll, token: Token, interest: Ready, opts: PollOpt)
                -> io::Result<()> {
        let hup: Ready = UnixReady::hup().into();
        EventedFd(&self.0.as_raw_fd()).register(poll, token, interest | hup, opts)
    }
    fn reregister(&self, poll: &mio::Poll, token: Token, interest: Ready, opts: PollOpt)
                  -> io::Result<()> {
        let hup: Ready = UnixReady::hup().into();
        EventedFd(&self.0.as_raw_fd()).reregister(poll, token, interest | hup, opts)
    }
    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        EventedFd(&self.0.as_raw_fd()).deregister(poll)
    }
}

#[test]
fn hup() {
    drop(env_logger::init());

    let handle = Handle::default();
    unsafe {
        let mut pipes = [0; 2];
        assert!(libc::pipe(pipes.as_mut_ptr()) != -1,
                "pipe error: {}", io::Error::last_os_error());
        let read = File::from_raw_fd(pipes[0]);
        let mut write = File::from_raw_fd(pipes[1]);
        let t = thread::spawn(move || {
            write.write_all(b"Hello!\n").unwrap();
            write.write_all(b"Good bye!\n").unwrap();
            thread::sleep(Duration::from_millis(100));
        });

        let source = PollEvented2::new_with_handle(MyFile::new(read), &handle).unwrap();

        let reader = read_to_end(source, Vec::new());
        let (_, content) = t!(reader.wait());
        assert_eq!(&b"Hello!\nGood bye!\n"[..], &content[..]);
        t.join().unwrap();
    }
}
<|endoftext|>


<commit_before>use std::result;
use common::combinator::*;

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

macro_rules! token_defs {
    ($enum_name:ident => {
        $($name:ident,)*
    }) => {
        #[derive(PartialEq, Debug)]
        pub enum $enum_name {
            $(
                $name(i32, i32, String),
            )*
        }

        impl $enum_name {
            pub fn pos(&self) -> (i32, i32) {
                match *self {
                    $(
                        $enum_name::$name(row, col, _) => (row, col),
                    )*
                }
            }

            pub fn literal(&self) -> &String {
                match *self {
                    $(
                        $enum_name::$name(_, _, ref lit) => lit,
                    )*
                }
            }
        }
    }
}

#[macro_export]
macro_rules! token {
    ($token:ident, $row:expr, $col:expr, $literal:expr) => {
        Token::$token($row, $col, $literal.to_string())
    }
}

token_defs!(Token => {
    Illegal,

    // identifier and literals
    Ident,
    IntLiteral,
    BoolLiteral,
    StringLiteral,

    // statements
    Assign,
    If,
    Else,

    // operators
    Plus,
    Minus,
    Divide,
    Multiply,
    Eq,
    NotEq,
    GreaterThan,
    LessThan,
    Not,

    // reserved words
    Function,
    Let,
    Return,

    // punctuations
    Comma,
    Colon,
    SemiColon,
    LParen,
    RParen,
    LBrace,
    RBrace,
    LBracket,
    RBracket,
});

#[derive(Debug)]
pub struct LexError {
    message: String,
    pos: (i32, i32),
}

pub struct Lexer {
    input: Vec<char>,
    cursor: usize,
    row: i32,
    col: i32,
    met_newline: bool,
    saved_cursor: usize,
    saved_row: i32,
    saved_col: i32,
}

impl Lexer {
    pub fn new<I>(input: I) -> Lexer
        where I: Iterator<Item = char>
    {
        Lexer {
            input: input.collect(),
            cursor: 0,
            row: 1,
            col: 0,
            met_newline: false,
            saved_cursor: 0,
            saved_row: 1,
            saved_col: 0,
        }
    }
}

impl Parser<char, LexError> for Lexer {
    fn consume(&mut self) -> Option<char> {
        match self.input.get(self.cursor) {
            Some(x) => {
                self.cursor += 1;

                if self.met_newline {
                    self.row += 1;
                    self.col = 1;
                    self.met_newline = false;
                } else {
                    self.col += 1;
                }

                if *x == '\n' {
                    self.met_newline = true;
                }
                Some(x.clone())
            }
            None => None,
        }
    }

    fn preview(&self) -> Option<&char> {
        self.input.get(self.cursor)
    }

    fn current_pos(&self) -> (i32, i32) {
        (self.row, self.col)
    }

    fn error<S: Into<String>>(&self, message: S) -> LexError {
        LexError {
            message: message.into(),
            pos: self.current_pos(),
        }
    }

    fn save(&mut self) {
        self.saved_cursor = self.cursor;
        self.saved_row = self.row;
        self.saved_col = self.col;
    }

    fn load(&mut self) {
        self.cursor = self.saved_cursor;
        self.row = self.saved_row;
        self.col = self.saved_col;
    }
}

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

    #[test]
    fn pos() {
        let mut l = Lexer::new(String::from("123\n 4\n5\n").chars());
        l.consume();
        assert_eq!(l.current_pos(), (1, 1));
        l.consume();
        assert_eq!(l.current_pos(), (1, 2));
        l.consume();
        assert_eq!(l.current_pos(), (1, 3));
        l.consume();
        assert_eq!(l.current_pos(), (1, 4));
        l.consume();
        assert_eq!(l.current_pos(), (2, 1));
        l.consume();
        assert_eq!(l.current_pos(), (2, 2));
        l.consume();
        assert_eq!(l.current_pos(), (2, 3));
        l.consume();
        assert_eq!(l.current_pos(), (3, 1));
        l.consume();
        assert_eq!(l.current_pos(), (3, 2));
        l.consume();
        assert_eq!(l.current_pos(), (3, 2));
        l.consume();
        assert_eq!(l.current_pos(), (3, 2));
    }
}
<commit_msg>Change how current_pos() works<commit_after>use std::result;
use common::combinator::*;

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

macro_rules! token_defs {
    ($enum_name:ident => {
        $($name:ident,)*
    }) => {
        #[derive(PartialEq, Debug)]
        pub enum $enum_name {
            $(
                $name(i32, i32, String),
            )*
        }

        impl $enum_name {
            pub fn pos(&self) -> (i32, i32) {
                match *self {
                    $(
                        $enum_name::$name(row, col, _) => (row, col),
                    )*
                }
            }

            pub fn literal(&self) -> &String {
                match *self {
                    $(
                        $enum_name::$name(_, _, ref lit) => lit,
                    )*
                }
            }
        }
    }
}

#[macro_export]
macro_rules! token {
    ($token:ident, $row:expr, $col:expr, $literal:expr) => {
        Token::$token($row, $col, $literal.to_string())
    }
}

token_defs!(Token => {
    Illegal,

    // identifier and literals
    Ident,
    IntLiteral,
    BoolLiteral,
    StringLiteral,

    // statements
    Assign,
    If,
    Else,

    // operators
    Plus,
    Minus,
    Divide,
    Multiply,
    Eq,
    NotEq,
    GreaterThan,
    LessThan,
    Not,

    // reserved words
    Function,
    Let,
    Return,

    // punctuations
    Comma,
    Colon,
    SemiColon,
    LParen,
    RParen,
    LBrace,
    RBrace,
    LBracket,
    RBracket,
});

#[derive(Debug)]
pub struct LexError {
    message: String,
    pos: (i32, i32),
}

pub struct Lexer {
    input: Vec<char>,
    cursor: usize,
    row: i32,
    col: i32,
    saved_cursor: usize,
    saved_row: i32,
    saved_col: i32,
}

impl Lexer {
    pub fn new<I>(input: I) -> Lexer
        where I: Iterator<Item = char>
    {
        Lexer {
            input: input.collect(),
            cursor: 0,
            row: 1,
            col: 1,
            saved_cursor: 0,
            saved_row: 1,
            saved_col: 1,
        }
    }
}

impl Parser<char, LexError> for Lexer {
    fn consume(&mut self) -> Option<char> {
        match self.input.get(self.cursor) {
            Some(x) => {
                self.cursor += 1;

                if *x == '\n' {
                    self.row += 1;
                    self.col = 1;
                } else {
                    self.col += 1;
                }

                Some(x.clone())
            }
            None => None,
        }
    }

    fn preview(&self) -> Option<&char> {
        self.input.get(self.cursor)
    }

    fn current_pos(&self) -> (i32, i32) {
        (self.row, self.col)
    }

    fn error<S: Into<String>>(&self, message: S) -> LexError {
        LexError {
            message: message.into(),
            pos: self.current_pos(),
        }
    }

    fn save(&mut self) {
        self.saved_cursor = self.cursor;
        self.saved_row = self.row;
        self.saved_col = self.col;
    }

    fn load(&mut self) {
        self.cursor = self.saved_cursor;
        self.row = self.saved_row;
        self.col = self.saved_col;
    }
}

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

    #[test]
    fn pos() {
        let mut l = Lexer::new(String::from("123\n 4\n5\n").chars());
        assert_eq!(l.current_pos(), (1, 1));
        l.consume();
        assert_eq!(l.current_pos(), (1, 2));
        l.consume();
        assert_eq!(l.current_pos(), (1, 3));
        l.consume();
        assert_eq!(l.current_pos(), (1, 4));
        l.consume();
        assert_eq!(l.current_pos(), (2, 1));
        l.consume();
        assert_eq!(l.current_pos(), (2, 2));
        l.consume();
        assert_eq!(l.current_pos(), (2, 3));
        l.consume();
        assert_eq!(l.current_pos(), (3, 1));
        l.consume();
        assert_eq!(l.current_pos(), (3, 2));
        l.consume();
        assert_eq!(l.current_pos(), (4, 1));
        l.consume();
        assert_eq!(l.current_pos(), (4, 1));
        l.consume();
    }
}
<|endoftext|>


<commit_before>//! Thin wrappers around `std::path`, distinguishing between absolute and
//! relative paths.
use std::{
    convert::{TryFrom, TryInto},
    io, ops,
    path::{Component, Path, PathBuf},
};

#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct AbsPathBuf(PathBuf);

impl From<AbsPathBuf> for PathBuf {
    fn from(AbsPathBuf(path_buf): AbsPathBuf) -> PathBuf {
        path_buf
    }
}

impl ops::Deref for AbsPathBuf {
    type Target = AbsPath;
    fn deref(&self) -> &AbsPath {
        self.as_path()
    }
}

impl AsRef<Path> for AbsPathBuf {
    fn as_ref(&self) -> &Path {
        self.0.as_path()
    }
}

impl TryFrom<PathBuf> for AbsPathBuf {
    type Error = PathBuf;
    fn try_from(path_buf: PathBuf) -> Result<AbsPathBuf, PathBuf> {
        if !path_buf.is_absolute() {
            return Err(path_buf);
        }
        Ok(AbsPathBuf(path_buf))
    }
}

impl TryFrom<&str> for AbsPathBuf {
    type Error = PathBuf;
    fn try_from(path: &str) -> Result<AbsPathBuf, PathBuf> {
        AbsPathBuf::try_from(PathBuf::from(path))
    }
}

impl AbsPathBuf {
    pub fn canonicalized(path: &Path) -> io::Result<AbsPathBuf> {
        path.canonicalize().map(|it| AbsPathBuf::try_from(it).unwrap())
    }
    pub fn as_path(&self) -> &AbsPath {
        AbsPath::new_unchecked(self.0.as_path())
    }
    pub fn pop(&mut self) -> bool {
        self.0.pop()
    }
}

#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[repr(transparent)]
pub struct AbsPath(Path);

impl ops::Deref for AbsPath {
    type Target = Path;
    fn deref(&self) -> &Path {
        &self.0
    }
}

impl AsRef<Path> for AbsPath {
    fn as_ref(&self) -> &Path {
        &self.0
    }
}

impl<'a> TryFrom<&'a Path> for &'a AbsPath {
    type Error = &'a Path;
    fn try_from(path: &'a Path) -> Result<&'a AbsPath, &'a Path> {
        if !path.is_absolute() {
            return Err(path);
        }
        Ok(AbsPath::new_unchecked(path))
    }
}

impl AbsPath {
    fn new_unchecked(path: &Path) -> &AbsPath {
        unsafe { &*(path as *const Path as *const AbsPath) }
    }

    pub fn join(&self, path: impl AsRef<Path>) -> AbsPathBuf {
        self.as_ref().join(path).try_into().unwrap()
    }
    pub fn normalize(&self) -> AbsPathBuf {
        AbsPathBuf(normalize_path(&self.0))
    }
}

// https://github.com/rust-lang/cargo/blob/79c769c3d7b4c2cf6a93781575b7f592ef974255/src/cargo/util/paths.rs#L60-L85
fn normalize_path(path: &Path) -> PathBuf {
    let mut components = path.components().peekable();
    let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
        components.next();
        PathBuf::from(c.as_os_str())
    } else {
        PathBuf::new()
    };

    for component in components {
        match component {
            Component::Prefix(..) => unreachable!(),
            Component::RootDir => {
                ret.push(component.as_os_str());
            }
            Component::CurDir => {}
            Component::ParentDir => {
                ret.pop();
            }
            Component::Normal(c) => {
                ret.push(c);
            }
        }
    }
    ret
}
<commit_msg>Add paths::RelPath[Buf]<commit_after>//! Thin wrappers around `std::path`, distinguishing between absolute and
//! relative paths.
use std::{
    convert::{TryFrom, TryInto},
    io, ops,
    path::{Component, Path, PathBuf},
};

#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct AbsPathBuf(PathBuf);

impl From<AbsPathBuf> for PathBuf {
    fn from(AbsPathBuf(path_buf): AbsPathBuf) -> PathBuf {
        path_buf
    }
}

impl ops::Deref for AbsPathBuf {
    type Target = AbsPath;
    fn deref(&self) -> &AbsPath {
        self.as_path()
    }
}

impl AsRef<Path> for AbsPathBuf {
    fn as_ref(&self) -> &Path {
        self.0.as_path()
    }
}

impl TryFrom<PathBuf> for AbsPathBuf {
    type Error = PathBuf;
    fn try_from(path_buf: PathBuf) -> Result<AbsPathBuf, PathBuf> {
        if !path_buf.is_absolute() {
            return Err(path_buf);
        }
        Ok(AbsPathBuf(path_buf))
    }
}

impl TryFrom<&str> for AbsPathBuf {
    type Error = PathBuf;
    fn try_from(path: &str) -> Result<AbsPathBuf, PathBuf> {
        AbsPathBuf::try_from(PathBuf::from(path))
    }
}

impl AbsPathBuf {
    pub fn canonicalized(path: &Path) -> io::Result<AbsPathBuf> {
        path.canonicalize().map(|it| AbsPathBuf::try_from(it).unwrap())
    }
    pub fn as_path(&self) -> &AbsPath {
        AbsPath::new_unchecked(self.0.as_path())
    }
    pub fn pop(&mut self) -> bool {
        self.0.pop()
    }
}

#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[repr(transparent)]
pub struct AbsPath(Path);

impl ops::Deref for AbsPath {
    type Target = Path;
    fn deref(&self) -> &Path {
        &self.0
    }
}

impl AsRef<Path> for AbsPath {
    fn as_ref(&self) -> &Path {
        &self.0
    }
}

impl<'a> TryFrom<&'a Path> for &'a AbsPath {
    type Error = &'a Path;
    fn try_from(path: &'a Path) -> Result<&'a AbsPath, &'a Path> {
        if !path.is_absolute() {
            return Err(path);
        }
        Ok(AbsPath::new_unchecked(path))
    }
}

impl AbsPath {
    fn new_unchecked(path: &Path) -> &AbsPath {
        unsafe { &*(path as *const Path as *const AbsPath) }
    }

    pub fn join(&self, path: impl AsRef<Path>) -> AbsPathBuf {
        self.as_ref().join(path).try_into().unwrap()
    }
    pub fn normalize(&self) -> AbsPathBuf {
        AbsPathBuf(normalize_path(&self.0))
    }
    pub fn to_path_buf(&self) -> AbsPathBuf {
        AbsPathBuf::try_from(self.0.to_path_buf()).unwrap()
    }
    pub fn strip_prefix(&self, base: &AbsPath) -> Option<&RelPath> {
        self.0.strip_prefix(base).ok().map(RelPath::new_unchecked)
    }
}

#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct RelPathBuf(PathBuf);

impl From<RelPathBuf> for PathBuf {
    fn from(RelPathBuf(path_buf): RelPathBuf) -> PathBuf {
        path_buf
    }
}

impl ops::Deref for RelPathBuf {
    type Target = RelPath;
    fn deref(&self) -> &RelPath {
        self.as_path()
    }
}

impl AsRef<Path> for RelPathBuf {
    fn as_ref(&self) -> &Path {
        self.0.as_path()
    }
}

impl TryFrom<PathBuf> for RelPathBuf {
    type Error = PathBuf;
    fn try_from(path_buf: PathBuf) -> Result<RelPathBuf, PathBuf> {
        if !path_buf.is_relative() {
            return Err(path_buf);
        }
        Ok(RelPathBuf(path_buf))
    }
}

impl TryFrom<&str> for RelPathBuf {
    type Error = PathBuf;
    fn try_from(path: &str) -> Result<RelPathBuf, PathBuf> {
        RelPathBuf::try_from(PathBuf::from(path))
    }
}

impl RelPathBuf {
    pub fn as_path(&self) -> &RelPath {
        RelPath::new_unchecked(self.0.as_path())
    }
}

#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[repr(transparent)]
pub struct RelPath(Path);

impl ops::Deref for RelPath {
    type Target = Path;
    fn deref(&self) -> &Path {
        &self.0
    }
}

impl AsRef<Path> for RelPath {
    fn as_ref(&self) -> &Path {
        &self.0
    }
}

impl RelPath {
    pub fn new_unchecked(path: &Path) -> &RelPath {
        unsafe { &*(path as *const Path as *const RelPath) }
    }
}

// https://github.com/rust-lang/cargo/blob/79c769c3d7b4c2cf6a93781575b7f592ef974255/src/cargo/util/paths.rs#L60-L85
fn normalize_path(path: &Path) -> PathBuf {
    let mut components = path.components().peekable();
    let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
        components.next();
        PathBuf::from(c.as_os_str())
    } else {
        PathBuf::new()
    };

    for component in components {
        match component {
            Component::Prefix(..) => unreachable!(),
            Component::RootDir => {
                ret.push(component.as_os_str());
            }
            Component::CurDir => {}
            Component::ParentDir => {
                ret.pop();
            }
            Component::Normal(c) => {
                ret.push(c);
            }
        }
    }
    ret
}
<|endoftext|>