<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<D, L>(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 DoubleEndedIterator<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) -> 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(
                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>wlr_layer: Update doc-test<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::delegate_layer_shell;
//! use smithay::wayland::shell::wlr_layer::{WlrLayerShellState, WlrLayerShellHandler, LayerShellRequest};
//!
//! # struct State { layer_shell_state: WlrLayerShellState }
//! # let mut display = wayland_server::Display::<State>::new().unwrap();
//! let layer_shell_state = WlrLayerShellState::new::<State, _>(
//!     &display.handle(),
//!     None  // put a logger if you want
//! );
//!
//! // - Put your layer_shell_state into your `State`.
//! // - And implement `LayerShellHandler
//! impl WlrLayerShellHandler for State {
//!     fn shell_state(&mut self) -> &mut WlrLayerShellState {
//!         &mut self.layer_shell_state
//!     }
//!     fn request(&mut self, dh: &wayland_server::DisplayHandle, request: LayerShellRequest) {
//!         # let _ =  (dh, request);
//!         // your implementation
//!     }
//! }
//! // let smithay implement wayland_server::DelegateDispatch
//! delegate_layer_shell!(State);
//!
//! // 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<D, L>(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 DoubleEndedIterator<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) -> 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(
                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>use crate::core::{trait_aliases::Id, Directed, Directedness, Edge};
use std::{borrow::Borrow, iter::Iterator};

#[macro_use]
mod macros
{
	#[macro_export]
	macro_rules! edges_between {
		($e:expr, $v1:expr, $v2:expr) => {{
			// Filter out any edge that is not connected to both vertices
			let relevant = $e.filter(move |edge| {
				(edge.source() == $v1 && edge.sink() == $v2)
					|| (edge.source() == $v2 && edge.sink() == $v1)
			});

			// Return the result
			Box::new(relevant)
			}};
	}
	#[macro_export]
	macro_rules! edges_incident_on {
		($e:expr, $v:expr, $i:ident) => {
			Box::new($e.into_iter().filter(move |e| e.$i() == $v))
		};
		($e:expr, $v:expr) => {
			Box::new(
				$e.into_iter()
					.filter(move |edge| (edge.source() == $v) || (edge.sink() == $v)),
				)
		};
	}
}

/// The basic graph trait, providing vertex and edge inspection.
///
/// A graphs vertices are identified by the unique value of the associated type
/// [`Vertex`](#associatedtype.Vertex).
/// For example, [`Vertex`] could be `usize`, in which case every vertex is
/// identified by a unique integer value.
/// In addition to its identifier, each vertex has a weight of type
/// [`VertexWeight`]. A vertex's weight can be anything or can be omitted by
/// using `()`.
///
/// Edges are identified primarily by which two vertices they connect. They can
/// also have a weight (of type [`EdgeWeight`]) that can be anything, but may
/// also in some circumstances be used to differentiate between two edges that
/// connect the same vertices. The associated type [`Directedness`] defined
/// whether a graph is directed or undirected. If it is assigned to
/// [`Directed`](struct.Directed.html), we say the graph is directed, meaning
/// the order of vertices in the edge matter. `(v1,v2)` would be an edge
/// "pointing" from `v1` to `v2` but not the other way around, which means
/// `(v2,v1)` will always be seen as a strictly different edge.
/// When [`Directedness`] is assigned to [`Undirected`](struct.Undirected.html)
/// we say the graph is undirected and the order of vertices in an edge is not
/// important. `(v1,v2)` therefore connects `v1` and `v2` and is synonymous with
/// `(v2,v1)`.
///
/// TODO: When Rust supports 'impl trait' consider having some of the iterators
/// be clone too (those that don't include mutable references). This allows
/// cloning the iterators mid-iteration, which can be useful when comparing each
/// item to the ones after it.
///
/// ### Related
///
/// - [`GraphMut`](trait.GraphMut.html):
/// Provides methods for accessing weights through mutable references.
/// - [`NewVertex`](property/trait.NewVertex.html):
/// Provides methods for adding vertices to a graph.
/// - [`RemoveVertex`](property/trait.RemoveVertex.html):
/// Provides methods for removing vertices from a graph.
/// - [`AddEdge`](property/trait.AddEdge.html):
/// Provides methods for adding edges to a graph.
/// - [`RemoveEdge`](property/trait.RemoveEdge.html):
/// Provides methods for removing edges to a graph.
///
/// [`Vertex`]: #associatedtype.Vertex
/// [`VertexWeight`]: #associatedtype.VertexWeight
/// [`EdgeWeight`]: #associatedtype.EdgeWeight
/// [`Directedness`]: #associatedtype.Directedness
pub trait Graph
{
	/// Type of the graphs vertices.
	///
	/// This type should be lightweight, as its passed around by-value
	/// (therefore must implement [`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html)).
	/// Whether two vertices are equal is also a very common operation and
	/// should therefore also be light-weight.
	type Vertex: Id;

	/// The weight associated with each vertex.
	///
	/// `()` can be used if no weight is needed.
	type VertexWeight;

	/// The weight associated with each edge.
	///
	/// `()` can be used if no weight is needed.
	type EdgeWeight;

	/// Whether the graph is directed or not.
	///
	/// Only [`Directed`](struct.Directed.html) and
	/// [`Undirected`](struct.Undirected.html)
	/// are valid assignments. Using any other type is undefined behaviour.
	type Directedness: Directedness;

	/// Returns copies of all current vertex values in the graph.
	fn all_vertices_weighted<'a>(
		&'a self,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, &'a Self::VertexWeight)>>;
	/// Returns copies of all current edges in the graph.
	fn all_edges<'a>(
		&'a self,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, Self::Vertex, &'a Self::EdgeWeight)>>;

	// Optional methods

	fn all_vertices<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = Self::Vertex>>
	{
		Box::new(self.all_vertices_weighted().map(|(v, _)| v))
	}
	fn vertex_weight(&self, v: Self::Vertex) -> Option<&Self::VertexWeight>
	{
		self.all_vertices_weighted()
			.find(|&(candidate, _)| candidate == v)
			.map(|(_, w)| w)
	}
	fn contains_vertex(&self, v: Self::Vertex) -> bool
	{
		self.vertex_weight(v).is_some()
	}
	fn all_vertex_weights<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a Self::VertexWeight>>
	{
		Box::new(self.all_vertices_weighted().map(|(_, w)| w))
	}

	/// Returns the weights of all edges that are sourced in v1 and sinked in
	/// v2. I.e. all edges where e == (v1,v2,_).
	///
	/// If the graph is undirected, returns all edges connecting the two
	/// vertices I.e. all edges where e == (v1,v2,_) or e == (v2,v1,_)
	fn edges_between<'a: 'b, 'b>(
		&'a self,
		source: impl 'b + Borrow<Self::Vertex>,
		sink: impl 'b + Borrow<Self::Vertex>,
	) -> Box<dyn 'b + Iterator<Item = &'a Self::EdgeWeight>>
	{
		Box::new(
			self.all_edges()
				.filter(move |(so, si, _)| {
					(source.borrow() == so && sink.borrow() == si)
						|| (!Self::Directedness::directed()
							&& (source.borrow() == si && sink.borrow() == so))
				})
				.map(|(_, _, w)| w),
		)
	}

	/// Returns the sink and weight of any edge sourced in the given vertex.
	/// I.e. all edges where `e == (v,_,_)`
	///
	/// If the graph is undirected, is semantically equivalent to
	/// `edges_incident_on`.
	fn edges_sourced_in<'a: 'b, 'b>(
		&'a self,
		v: impl 'b + Borrow<Self::Vertex>,
	) -> Box<dyn 'b + Iterator<Item = (Self::Vertex, &'a Self::EdgeWeight)>>
	{
		Box::new(self.all_vertices().flat_map(move |v2| {
			self.edges_between(v.borrow().clone(), v2.borrow().clone())
				.map(move |w| (v2.clone(), w))
		}))
	}

	/// Returns the source and weight of any edge sinked in the given vertex.
	/// I.e. all edges where `e == (_,v,_)`
	///
	/// If the graph is undirected, is semantically equivalent to
	/// `edges_incident_on`.
	fn edges_sinked_in<'a: 'b, 'b>(
		&'a self,
		v: impl 'b + Borrow<Self::Vertex>,
	) -> Box<dyn 'b + Iterator<Item = (Self::Vertex, &'a Self::EdgeWeight)>>
	{
		Box::new(self.all_vertices().flat_map(move |v2| {
			self.edges_between(v2.borrow().clone(), v.borrow().clone())
				.map(move |w| (v2.clone(), w))
		}))
	}

	/// Returns the neighboring vertex and the weight of any edge incident
	/// on the given vertex.
	///
	/// If the graph is directed, edge directions are ignored.
	fn edges_incident_on<'a: 'b, 'b>(
		&'a self,
		v: impl 'b + Borrow<Self::Vertex>,
	) -> Box<dyn 'b + Iterator<Item = (Self::Vertex, &'a Self::EdgeWeight)>>
	{
		Box::new(
			self.edges_sourced_in(v.borrow().clone()).chain(
				self.edges_sinked_in(v.borrow().clone())
					.filter(move |(v2, _)| {
						Self::Directedness::directed() && v.borrow() != v2.borrow()
					}),
			),
		)
	}

	fn edge_valid<E>(&self, e: E) -> bool
	where
		E: Edge<Self::Vertex>,
	{
		self.contains_vertex(e.source()) && self.contains_vertex(e.sink())
	}
}

/// A graph with mutable vertex and edge weights.
///
/// [`Graph`](trait.Graph.html) provides methods that return references to
/// vertex and edge weight. However, it can't provide mutable references to the.
/// This trait provides mutable variants of [`Graph`](trait.Graph.html)'s
/// methods plus some additional utilities.
pub trait GraphMut: Graph
{
	fn all_vertices_weighted_mut<'a>(
		&'a mut self,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, &'a mut Self::VertexWeight)>>;

	fn all_edges_mut<'a>(
		&'a mut self,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, Self::Vertex, &'a mut Self::EdgeWeight)>>;

	// Optional methods

	fn vertex_weight_mut(&mut self, v: Self::Vertex) -> Option<&mut Self::VertexWeight>
	{
		self.all_vertices_weighted_mut()
			.find(|&(candidate, _)| candidate == v)
			.map(|(_, w)| w)
	}

	fn edges_between_mut<'a>(
		&'a mut self,
		v1: Self::Vertex,
		v2: Self::Vertex,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, Self::Vertex, &'a mut Self::EdgeWeight)>>
	{
		edges_between!(self.all_edges_mut(), v1, v2)
	}
	fn edges_sourced_in_mut<'a>(
		&'a mut self,
		v: Self::Vertex,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, Self::Vertex, &'a mut Self::EdgeWeight)>>
	where
		Self: Graph<Directedness = Directed>,
	{
		edges_incident_on!(self.all_edges_mut(), v, source)
	}
	fn edges_sinked_in_mut<'a>(
		&'a mut self,
		v: Self::Vertex,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, Self::Vertex, &'a mut Self::EdgeWeight)>>
	where
		Self: Graph<Directedness = Directed>,
	{
		edges_incident_on!(self.all_edges_mut(), v, sink)
	}
	fn edges_incident_on_mut<'a>(
		&'a mut self,
		v: Self::Vertex,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, Self::Vertex, &'a mut Self::EdgeWeight)>>
	{
		edges_incident_on!(self.all_edges_mut(), v)
	}
}
<commit_msg>Removed all mutable edge lookup methods except edges_between_mut.<commit_after>use crate::core::{trait_aliases::Id, Directedness, Edge};
use std::{borrow::Borrow, iter::Iterator};

/// The basic graph trait, providing vertex and edge inspection.
///
/// A graphs vertices are identified by the unique value of the associated type
/// [`Vertex`](#associatedtype.Vertex).
/// For example, [`Vertex`] could be `usize`, in which case every vertex is
/// identified by a unique integer value.
/// In addition to its identifier, each vertex has a weight of type
/// [`VertexWeight`]. A vertex's weight can be anything or can be omitted by
/// using `()`.
///
/// Edges are identified primarily by which two vertices they connect. They can
/// also have a weight (of type [`EdgeWeight`]) that can be anything, but may
/// also in some circumstances be used to differentiate between two edges that
/// connect the same vertices. The associated type [`Directedness`] defined
/// whether a graph is directed or undirected. If it is assigned to
/// [`Directed`](struct.Directed.html), we say the graph is directed, meaning
/// the order of vertices in the edge matter. `(v1,v2)` would be an edge
/// "pointing" from `v1` to `v2` but not the other way around, which means
/// `(v2,v1)` will always be seen as a strictly different edge.
/// When [`Directedness`] is assigned to [`Undirected`](struct.Undirected.html)
/// we say the graph is undirected and the order of vertices in an edge is not
/// important. `(v1,v2)` therefore connects `v1` and `v2` and is synonymous with
/// `(v2,v1)`.
///
/// TODO: When Rust supports 'impl trait' consider having some of the iterators
/// be clone too (those that don't include mutable references). This allows
/// cloning the iterators mid-iteration, which can be useful when comparing each
/// item to the ones after it.
///
/// ### Related
///
/// - [`GraphMut`](trait.GraphMut.html):
/// Provides methods for accessing weights through mutable references.
/// - [`NewVertex`](property/trait.NewVertex.html):
/// Provides methods for adding vertices to a graph.
/// - [`RemoveVertex`](property/trait.RemoveVertex.html):
/// Provides methods for removing vertices from a graph.
/// - [`AddEdge`](property/trait.AddEdge.html):
/// Provides methods for adding edges to a graph.
/// - [`RemoveEdge`](property/trait.RemoveEdge.html):
/// Provides methods for removing edges to a graph.
///
/// [`Vertex`]: #associatedtype.Vertex
/// [`VertexWeight`]: #associatedtype.VertexWeight
/// [`EdgeWeight`]: #associatedtype.EdgeWeight
/// [`Directedness`]: #associatedtype.Directedness
pub trait Graph
{
	/// Type of the graphs vertices.
	///
	/// This type should be lightweight, as its passed around by-value
	/// (therefore must implement [`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html)).
	/// Whether two vertices are equal is also a very common operation and
	/// should therefore also be light-weight.
	type Vertex: Id;

	/// The weight associated with each vertex.
	///
	/// `()` can be used if no weight is needed.
	type VertexWeight;

	/// The weight associated with each edge.
	///
	/// `()` can be used if no weight is needed.
	type EdgeWeight;

	/// Whether the graph is directed or not.
	///
	/// Only [`Directed`](struct.Directed.html) and
	/// [`Undirected`](struct.Undirected.html)
	/// are valid assignments. Using any other type is undefined behaviour.
	type Directedness: Directedness;

	/// Returns copies of all current vertex values in the graph.
	fn all_vertices_weighted<'a>(
		&'a self,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, &'a Self::VertexWeight)>>;
	/// Returns copies of all current edges in the graph.
	fn all_edges<'a>(
		&'a self,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, Self::Vertex, &'a Self::EdgeWeight)>>;

	// Optional methods

	fn all_vertices<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = Self::Vertex>>
	{
		Box::new(self.all_vertices_weighted().map(|(v, _)| v))
	}
	fn vertex_weight(&self, v: Self::Vertex) -> Option<&Self::VertexWeight>
	{
		self.all_vertices_weighted()
			.find(|&(candidate, _)| candidate == v)
			.map(|(_, w)| w)
	}
	fn contains_vertex(&self, v: Self::Vertex) -> bool
	{
		self.vertex_weight(v).is_some()
	}
	fn all_vertex_weights<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a Self::VertexWeight>>
	{
		Box::new(self.all_vertices_weighted().map(|(_, w)| w))
	}

	/// Returns the weights of all edges that are sourced in v1 and sinked in
	/// v2. I.e. all edges where e == (v1,v2,_).
	///
	/// If the graph is undirected, returns all edges connecting the two
	/// vertices I.e. all edges where e == (v1,v2,_) or e == (v2,v1,_)
	fn edges_between<'a: 'b, 'b>(
		&'a self,
		source: impl 'b + Borrow<Self::Vertex>,
		sink: impl 'b + Borrow<Self::Vertex>,
	) -> Box<dyn 'b + Iterator<Item = &'a Self::EdgeWeight>>
	{
		Box::new(
			self.all_edges()
				.filter(move |(so, si, _)| {
					(source.borrow() == so && sink.borrow() == si)
						|| (!Self::Directedness::directed()
							&& (source.borrow() == si && sink.borrow() == so))
				})
				.map(|(_, _, w)| w),
		)
	}

	/// Returns the sink and weight of any edge sourced in the given vertex.
	/// I.e. all edges where `e == (v,_,_)`
	///
	/// If the graph is undirected, is semantically equivalent to
	/// `edges_incident_on`.
	fn edges_sourced_in<'a: 'b, 'b>(
		&'a self,
		v: impl 'b + Borrow<Self::Vertex>,
	) -> Box<dyn 'b + Iterator<Item = (Self::Vertex, &'a Self::EdgeWeight)>>
	{
		Box::new(self.all_vertices().flat_map(move |v2| {
			self.edges_between(v.borrow().clone(), v2.borrow().clone())
				.map(move |w| (v2.clone(), w))
		}))
	}

	/// Returns the source and weight of any edge sinked in the given vertex.
	/// I.e. all edges where `e == (_,v,_)`
	///
	/// If the graph is undirected, is semantically equivalent to
	/// `edges_incident_on`.
	fn edges_sinked_in<'a: 'b, 'b>(
		&'a self,
		v: impl 'b + Borrow<Self::Vertex>,
	) -> Box<dyn 'b + Iterator<Item = (Self::Vertex, &'a Self::EdgeWeight)>>
	{
		Box::new(self.all_vertices().flat_map(move |v2| {
			self.edges_between(v2.borrow().clone(), v.borrow().clone())
				.map(move |w| (v2.clone(), w))
		}))
	}

	/// Returns the neighboring vertex and the weight of any edge incident
	/// on the given vertex.
	///
	/// If the graph is directed, edge directions are ignored.
	fn edges_incident_on<'a: 'b, 'b>(
		&'a self,
		v: impl 'b + Borrow<Self::Vertex>,
	) -> Box<dyn 'b + Iterator<Item = (Self::Vertex, &'a Self::EdgeWeight)>>
	{
		Box::new(
			self.edges_sourced_in(v.borrow().clone()).chain(
				self.edges_sinked_in(v.borrow().clone())
					.filter(move |(v2, _)| {
						Self::Directedness::directed() && v.borrow() != v2.borrow()
					}),
			),
		)
	}

	fn edge_valid<E>(&self, e: E) -> bool
	where
		E: Edge<Self::Vertex>,
	{
		self.contains_vertex(e.source()) && self.contains_vertex(e.sink())
	}
}

/// A graph with mutable vertex and edge weights.
///
/// [`Graph`](trait.Graph.html) provides methods that return references to
/// vertex and edge weight. However, it can't provide mutable references to the.
/// This trait provides mutable variants of [`Graph`](trait.Graph.html)'s
/// methods plus some additional utilities.
pub trait GraphMut: Graph
{
	fn all_vertices_weighted_mut<'a>(
		&'a mut self,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, &'a mut Self::VertexWeight)>>;

	fn all_edges_mut<'a>(
		&'a mut self,
	) -> Box<dyn 'a + Iterator<Item = (Self::Vertex, Self::Vertex, &'a mut Self::EdgeWeight)>>;

	fn edges_between_mut<'a: 'b, 'b>(
		&'a mut self,
		source: impl 'b + Borrow<Self::Vertex>,
		sink: impl 'b + Borrow<Self::Vertex>,
	) -> Box<dyn 'b + Iterator<Item = &'a mut Self::EdgeWeight>>
	{
		Box::new(self.all_edges_mut().filter_map(move |(so, si, w)| {
			if (source.borrow() == &so && sink.borrow() == &si)
				|| (!Self::Directedness::directed()
					|| (source.borrow() == &si && sink.borrow() == &so))
			{
				Some(w)
			}
			else
			{
				None
			}
		}))
	}

	// Optional methods

	fn vertex_weight_mut(&mut self, v: Self::Vertex) -> Option<&mut Self::VertexWeight>
	{
		self.all_vertices_weighted_mut()
			.find(|&(candidate, _)| candidate == v)
			.map(|(_, w)| w)
	}
}
<|endoftext|>


<commit_before><commit_msg>Prevent rustfmt from deleting lines<commit_after><|endoftext|>


<commit_before>use clipboard::ClipboardContext;
use clipboard::ClipboardProvider;

use super::{Load, Store};

pub struct Clipboard(ClipboardContext);

#[derive(Debug)]
pub enum Error {
    Clipboard(Box<::std::error::Error>),
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Clipboard(..) => "Error opening clipboard",
        }
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Error::Clipboard(ref err) => err.fmt(f),
        }
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Load for Clipboard {
    type Err = Error;

    fn new() -> Result<Self, Error> {
        ClipboardContext::new().map(Clipboard).map_err(Error::Clipboard)
    }

    fn load_primary(&self) -> Result<String, Self::Err> {
        let mut ctx: ClipboardContext = ClipboardProvider::new().unwrap();
        ctx.get_contents().map_err(Error::Clipboard)
    }

    fn load_selection(&self) -> Result<String, Self::Err> {
        let mut ctx: ClipboardContext = ClipboardProvider::new().unwrap();
        ctx.get_contents().map_err(Error::Clipboard)
    }
}

impl Store for Clipboard {
    /// Sets the primary clipboard contents
    #[inline]
    fn store_primary<S>(&mut self, contents: S) -> Result<(), Self::Err>
    where
        S: Into<String>,
    {
        self.0.set_contents(contents.into()).map_err(Error::Clipboard)
    }

    /// Sets the secondary clipboard contents
    #[inline]
    fn store_selection<S>(&mut self, contents: S) -> Result<(), Self::Err>
    where
        S: Into<String>,
    {
        self.0.set_contents(contents.into()).map_err(Error::Clipboard)
    }
}
<commit_msg>Fix selection copying on Windows<commit_after>use clipboard::ClipboardContext;
use clipboard::ClipboardProvider;

use super::{Load, Store};

pub struct Clipboard(ClipboardContext);

#[derive(Debug)]
pub enum Error {
    Clipboard(Box<::std::error::Error>),
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Clipboard(..) => "Error opening clipboard",
        }
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Error::Clipboard(ref err) => err.fmt(f),
        }
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Load for Clipboard {
    type Err = Error;

    fn new() -> Result<Self, Error> {
        ClipboardContext::new().map(Clipboard).map_err(Error::Clipboard)
    }

    fn load_primary(&self) -> Result<String, Self::Err> {
        let mut ctx: ClipboardContext = ClipboardProvider::new().unwrap();
        ctx.get_contents().map_err(Error::Clipboard)
    }
}

impl Store for Clipboard {
    /// Sets the primary clipboard contents
    #[inline]
    fn store_primary<S>(&mut self, contents: S) -> Result<(), Self::Err>
    where
        S: Into<String>,
    {
        self.0.set_contents(contents.into()).map_err(Error::Clipboard)
    }

    /// Sets the secondary clipboard contents
    #[inline]
    fn store_selection<S>(&mut self, contents: S) -> Result<(), Self::Err>
    where
        S: Into<String>,
    {
        // No such thing on Windows
        Ok(())
    }
}
<|endoftext|>


<commit_before>use ::position::Positional;
use super::annotations::{ Annotated
                        , ScopednessTypestate
                        };
use super::types::Type;
use std::rc::Rc;

pub type Ident = Positional<String>;

pub type Expr<'a, S: ScopednessTypestate>
    = Annotated<'a
               , Form<'a, S>
               , S>;

pub type Body<'a, S: ScopednessTypestate> = Vec<Expr<'a, S>>;

pub type Bindings<'a, S: ScopednessTypestate>
    = Vec<Annotated<'a
                   , Binding<'a, S>
                   , S>>;

#[derive(PartialEq, Clone, Debug)]
pub enum Form<'a, S: ScopednessTypestate> {
    Define(DefForm<'a, S>)
  , If { condition: Rc<Expr<'a, S>>
       , if_clause: Rc<Expr<'a, S>>
       , else_clause: Option<Rc<Expr<'a, S>>>
       }
  , Let(LetForm<'a, S>)
  , Call { fun: Ident
         , body: Body<'a, S>
         }
  , Lambda(Function<'a, S>)
  , Logical(Logical<'a, S>)
}

#[derive(PartialEq, Clone, Debug)]
pub struct Formal { pub name: Ident
                  , pub annot: Ident
                  }

#[derive(PartialEq, Clone, Debug)]
pub enum DefForm<'a, S: ScopednessTypestate> {
    TopLevel { name: Ident
             , annot: Ident
             , value: Rc<Expr<'a, S>>
             }
  , Function { name: Ident
             , fun: Function<'a,S>
             }
}

/// Logical `and` and `or` expressions
///
/// The general expectation is that these will generally be parsed as infix.
#[derive(PartialEq, Clone, Debug)]
pub enum Logical<'a, S: ScopednessTypestate> {
    And { a: Rc<Expr<'a, S>>
        , b: Rc<Expr<'a, S>>
        }
  , Or { a: Rc<Expr<'a, S>>
       , b: Rc<Expr<'a, S>>
       }
}

#[derive(PartialEq, Clone, Debug)]
pub enum LetForm<'a, S: ScopednessTypestate> {
    Let { bindings: Bindings<'a, S>
        , body: Body<'a, S>
        }
  , Invocation { proc_id: Ident
               , init: Binding<'a, S>
               , body: Body<'a, S>
               }
  , LetRec { bindings: Bindings<'a, S>
           , body: Body<'a, S>
           }
  , LetSplat { bindings: Bindings<'a, S>
             , body: Body<'a, S>
             }

}

#[derive(PartialEq, Clone, Debug)]
pub struct Binding<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub typ: Type
  , pub value: Rc<Expr<'a, S>>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Function<'a, S: ScopednessTypestate> {
    pub formals: Vec<Annotated<'a, Formal, S>>
  , pub annot: Ident
  , pub body: Body<'a, S>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Data<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub variants: Vec<Variant<'a, S>>
}

impl<'a, S> Data<'a, S>
where S: ScopednessTypestate {
    pub fn is_algebraic(&self) -> bool { self.variants.len() > 1 }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Variant<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub fields: Vec<Annotated<'a, Formal, S>>
}
<commit_msg>Start on module system<commit_after>use ::position::Positional;
use super::annotations::{ Annotated
                        , ScopednessTypestate
                        , ScopedState
                        , Scoped
                        };
use super::types::Type;

use std::rc::Rc;
use std::borrow::Borrow;
use std::hash::Hash;

pub type Ident = Positional<String>;

pub type Expr<'a, S: ScopednessTypestate>
    = Annotated<'a
               , Form<'a, S>
               , S>;

pub type Body<'a, S: ScopednessTypestate> = Vec<Expr<'a, S>>;

pub type Bindings<'a, S: ScopednessTypestate>
    = Vec<Annotated<'a
                   , Binding<'a, S>
                   , S>>;

#[derive(PartialEq, Clone, Debug)]
pub struct Module<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub exporting: Vec<Ident>
  , pub body: Body<'a, S>
}

impl<'a, S> Module<'a, S> where S: ScopednessTypestate {

    /// Returns true if the namespace is exporting any names
    #[inline] pub fn is_lib (&self) -> bool { !self.exporting.is_empty() }

}

impl<'a> Scoped<'a, Module<'a, ScopedState>>{

    pub fn has_name<Q: ?Sized>(&self, name: &Q) -> bool
    where String: Borrow<Q>
        , String: PartialEq<Q>
        , Q: Hash + Eq
    {
        self.is_defined_here(name) &&
        self.node.exporting
            .iter()
            .find(|ref i| &i.value == name)
            .is_some()
    }

}

#[derive(PartialEq, Clone, Debug)]
pub enum Form<'a, S: ScopednessTypestate> {
    Define(DefForm<'a, S>)
  , If { condition: Rc<Expr<'a, S>>
       , if_clause: Rc<Expr<'a, S>>
       , else_clause: Option<Rc<Expr<'a, S>>>
       }
  , Let(LetForm<'a, S>)
  , Call { fun: Ident
         , body: Body<'a, S>
         }
  , Lambda(Function<'a, S>)
  , Logical(Logical<'a, S>)
}

#[derive(PartialEq, Clone, Debug)]
pub struct Formal { pub name: Ident
                  , pub annot: Ident
                  }

#[derive(PartialEq, Clone, Debug)]
pub enum DefForm<'a, S: ScopednessTypestate> {
    TopLevel { name: Ident
             , annot: Ident
             , value: Rc<Expr<'a, S>>
             }
  , Function { name: Ident
             , fun: Function<'a,S>
             }
}

/// Logical `and` and `or` expressions
///
/// The general expectation is that these will generally be parsed as infix.
#[derive(PartialEq, Clone, Debug)]
pub enum Logical<'a, S: ScopednessTypestate> {
    And { a: Rc<Expr<'a, S>>
        , b: Rc<Expr<'a, S>>
        }
  , Or { a: Rc<Expr<'a, S>>
       , b: Rc<Expr<'a, S>>
       }
}

#[derive(PartialEq, Clone, Debug)]
pub enum LetForm<'a, S: ScopednessTypestate> {
    Let { bindings: Bindings<'a, S>
        , body: Body<'a, S>
        }
  , Invocation { proc_id: Ident
               , init: Binding<'a, S>
               , body: Body<'a, S>
               }
  , LetRec { bindings: Bindings<'a, S>
           , body: Body<'a, S>
           }
  , LetSplat { bindings: Bindings<'a, S>
             , body: Body<'a, S>
             }

}

#[derive(PartialEq, Clone, Debug)]
pub struct Binding<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub typ: Type
  , pub value: Rc<Expr<'a, S>>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Function<'a, S: ScopednessTypestate> {
    pub formals: Vec<Annotated<'a, Formal, S>>
  , pub annot: Ident
  , pub body: Body<'a, S>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Data<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub variants: Vec<Variant<'a, S>>
}

impl<'a, S> Data<'a, S>
where S: ScopednessTypestate {
    pub fn is_algebraic(&self) -> bool { self.variants.len() > 1 }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Variant<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub fields: Vec<Annotated<'a, Formal, S>>
}
<|endoftext|>


<commit_before>use std::mem;

use dma::Dma;
use io::{Mmio, Io, ReadOnly};
use netutils::setcfg;
use syscall::error::{Error, EACCES, EWOULDBLOCK, Result};
use syscall::flag::O_NONBLOCK;
use syscall::scheme::SchemeMut;

#[repr(packed)]
struct Regs {
    mac: [Mmio<u32>; 2],
    _mar: [Mmio<u32>; 2],
    _dtccr: [Mmio<u32>; 2],
    _rsv0: [Mmio<u32>; 2],
    tnpds: [Mmio<u32>; 2],
    thpds: [Mmio<u32>; 2],
    _rsv1: [Mmio<u8>; 7],
    cmd: Mmio<u8>,
    tppoll: Mmio<u8>,
    _rsv2: [Mmio<u8>; 3],
    imr: Mmio<u16>,
    isr: Mmio<u16>,
    tcr: Mmio<u32>,
    rcr: Mmio<u32>,
    _tctr: Mmio<u32>,
    _rsv3: Mmio<u32>,
    cmd_9346: Mmio<u8>,
    _config: [Mmio<u8>; 6],
    _rsv4: Mmio<u8>,
    _timer_int: Mmio<u32>,
    _rsv5: Mmio<u32>,
    _phys_ar: Mmio<u32>,
    _rsv6: [Mmio<u32>; 2],
    phys_sts: ReadOnly<Mmio<u8>>,
    _rsv7: [Mmio<u8>; 23],
    _wakeup: [Mmio<u32>; 16],
    _crc: [Mmio<u16>; 5],
    _rsv8: [Mmio<u8>; 12],
    rms: Mmio<u16>,
    _rsv9: Mmio<u32>,
    _c_plus_cr: Mmio<u16>,
    _rsv10: Mmio<u16>,
    rdsar: [Mmio<u32>; 2],
    mtps: Mmio<u8>,
    _rsv11: [Mmio<u8>; 19],
}

const OWN: u32 = 1 << 31;
const EOR: u32 = 1 << 30;
const FS: u32 = 1 << 29;
const LS: u32 = 1 << 28;

#[repr(packed)]
struct Rd {
    ctrl: Mmio<u32>,
    _vlan: Mmio<u32>,
    buffer: Mmio<u64>
}

#[repr(packed)]
struct Td {
    ctrl: Mmio<u32>,
    _vlan: Mmio<u32>,
    buffer: Mmio<u64>
}

pub struct Rtl8168 {
    regs: &'static mut Regs,
    receive_buffer: [Dma<[u8; 0x1FF8]>; 16],
    receive_ring: Dma<[Rd; 16]>,
    transmit_buffer: [Dma<[u8; 7552]>; 16],
    transmit_ring: Dma<[Td; 16]>,
    transmit_buffer_h: [Dma<[u8; 7552]>; 1],
    transmit_ring_h: Dma<[Td; 1]>
}

impl SchemeMut for Rtl8168 {
    fn open(&mut self, _path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
        if uid == 0 {
            Ok(flags)
        } else {
            Err(Error::new(EACCES))
        }
    }

    fn dup(&mut self, id: usize, _buf: &[u8]) -> Result<usize> {
        Ok(id)
    }

    fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
        for (rd_i, rd) in self.receive_ring.iter_mut().enumerate() {
            if ! rd.ctrl.readf(OWN) {
                let rd_len = rd.ctrl.read() & 0x3FFF;

                let data = &self.receive_buffer[rd_i as usize];

                let mut i = 0;
                while i < buf.len() && i < rd_len as usize {
                    buf[i] = data[i];
                    i += 1;
                }

                let eor = rd.ctrl.read() & EOR;
                rd.ctrl.write(OWN | eor | data.len() as u32);

                return Ok(i);
            }
        }

        if id & O_NONBLOCK == O_NONBLOCK {
            Ok(0)
        } else {
            Err(Error::new(EWOULDBLOCK))
        }
    }

    fn write(&mut self, _id: usize, buf: &[u8]) -> Result<usize> {
        loop {
            for (td_i, td) in self.transmit_ring.iter_mut().enumerate() {
                if ! td.ctrl.readf(OWN) {

                    let mut data = &mut self.transmit_buffer[td_i as usize];

                    let mut i = 0;
                    while i < buf.len() && i < data.len() {
                        data[i] = buf[i];
                        i += 1;
                    }

                    let eor = td.ctrl.read() & EOR;
                    td.ctrl.write(OWN | eor | FS | LS | i as u32);

                    self.regs.tppoll.writef(1 << 6, true); //Notify of normal priority packet

                    while self.regs.tppoll.readf(1 << 6) {
                        unsafe { asm!("pause" : : : "memory" : "intel", "volatile"); }
                    }

                    return Ok(i);
                }
            }

            unsafe { asm!("pause" : : : "memory" : "intel", "volatile"); }
        }
    }

    fn fevent(&mut self, _id: usize, _flags: usize) -> Result<usize> {
        Ok(0)
    }

    fn fsync(&mut self, _id: usize) -> Result<usize> {
        Ok(0)
    }

    fn close(&mut self, _id: usize) -> Result<usize> {
        Ok(0)
    }
}

impl Rtl8168 {
    pub unsafe fn new(base: usize) -> Result<Self> {
        assert_eq!(mem::size_of::<Regs>(), 256);

        let regs = &mut *(base as *mut Regs);
        assert_eq!(&regs.tnpds as *const _ as usize - base, 0x20);
        assert_eq!(&regs.cmd as *const _ as usize - base, 0x37);
        assert_eq!(&regs.tcr as *const _ as usize - base, 0x40);
        assert_eq!(&regs.rcr as *const _ as usize - base, 0x44);
        assert_eq!(&regs.cmd_9346 as *const _ as usize - base, 0x50);
        assert_eq!(&regs.phys_sts as *const _ as usize - base, 0x6C);
        assert_eq!(&regs.rms as *const _ as usize - base, 0xDA);
        assert_eq!(&regs.rdsar as *const _ as usize - base, 0xE4);
        assert_eq!(&regs.mtps as *const _ as usize - base, 0xEC);

        let mut module = Rtl8168 {
            regs: regs,
            receive_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?],
            receive_ring: Dma::zeroed()?,
            transmit_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?],
            transmit_ring: Dma::zeroed()?,
            transmit_buffer_h: [Dma::zeroed()?],
            transmit_ring_h: Dma::zeroed()?
        };

        module.init();

        Ok(module)
    }

    pub unsafe fn irq(&mut self) -> u16 {
        // Read and then clear the ISR
        let isr = self.regs.isr.read();
        self.regs.isr.write(isr);
        let imr = self.regs.imr.read();
        isr & imr
    }

    pub fn next_read(&self) -> usize {
        for rd in self.receive_ring.iter() {
            if ! rd.ctrl.readf(OWN) {
                return rd.ctrl.read() as usize & 0x3FFF;
            }
        }
        0
    }

    pub unsafe fn init(&mut self) {
        let mac_low = self.regs.mac[0].read();
        let mac_high = self.regs.mac[1].read();
        let mac = [mac_low as u8,
                    (mac_low >> 8) as u8,
                    (mac_low >> 16) as u8,
                    (mac_low >> 24) as u8,
                    mac_high as u8,
                    (mac_high >> 8) as u8];
        print!("{}", format!("   - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
        let _ = setcfg("mac", &format!("{:>02X}.{:>02X}.{:>02X}.{:>02X}.{:>02X}.{:>02X}", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));

        // Reset - this will disable tx and rx, reinitialize FIFOs, and set the system buffer pointer to the initial value
        self.regs.cmd.writef(1 << 4, true);
        while self.regs.cmd.readf(1 << 4) {}

        // Set up rx buffers
        for i in 0..self.receive_ring.len() {
            let rd = &mut self.receive_ring[i];
            let data = &mut self.receive_buffer[i];
            rd.ctrl.write(OWN | data.len() as u32);
            rd.buffer.write(data.physical() as u64);
        }
        if let Some(mut rd) = self.receive_ring.last_mut() {
            rd.ctrl.writef(EOR, true);
        }

        // Set up normal priority tx buffers
        for i in 0..self.transmit_ring.len() {
            self.transmit_ring[i].buffer.write(self.transmit_buffer[i].physical() as u64);
        }
        if let Some(mut td) = self.transmit_ring.last_mut() {
            td.ctrl.writef(EOR, true);
        }

        // Set up high priority tx buffers
        for i in 0..self.transmit_ring_h.len() {
            self.transmit_ring_h[i].buffer.write(self.transmit_buffer_h[i].physical() as u64);
        }
        if let Some(mut td) = self.transmit_ring_h.last_mut() {
            td.ctrl.writef(EOR, true);
        }

        // Unlock config
        self.regs.cmd_9346.write(1 << 7 | 1 << 6);

        // Enable rx (bit 3) and tx (bit 2)
        self.regs.cmd.writef(1 << 3 | 1 << 2, true);

        // Max RX packet size
        self.regs.rms.write(0x1FF8);

        // Max TX packet size
        self.regs.mtps.write(0x3B);

        // Set tx low priority buffer address
        self.regs.tnpds[0].write(self.transmit_ring.physical() as u32);
        self.regs.tnpds[1].write((self.transmit_ring.physical() >> 32) as u32);

        // Set tx high priority buffer address
        self.regs.thpds[0].write(self.transmit_ring_h.physical() as u32);
        self.regs.thpds[1].write((self.transmit_ring_h.physical() >> 32) as u32);

        // Set rx buffer address
        self.regs.rdsar[0].write(self.receive_ring.physical() as u32);
        self.regs.rdsar[1].write((self.receive_ring.physical() >> 32) as u32);

        //Clear ISR
        let isr = self.regs.isr.read();
        self.regs.isr.write(isr);

        // Interrupt on tx error (bit 3), tx ok (bit 2), rx error(bit 1), and rx ok (bit 0)
        self.regs.imr.write(1 << 15 | 1 << 14 | 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1);

        // Set TX config
        self.regs.tcr.write(0b11 << 24 | 0b111 << 8);

        // Set RX config - Accept broadcast (bit 3), multicast (bit 2), and unicast (bit 1)
        self.regs.rcr.write(0xE70E);

        // Lock config
        self.regs.cmd_9346.write(0);
    }
}
<commit_msg>Use mmio, disable timer interrupt<commit_after>use std::mem;

use dma::Dma;
use io::{Mmio, Io, ReadOnly};
use netutils::setcfg;
use syscall::error::{Error, EACCES, EWOULDBLOCK, Result};
use syscall::flag::O_NONBLOCK;
use syscall::scheme::SchemeMut;

#[repr(packed)]
struct Regs {
    mac: [Mmio<u32>; 2],
    _mar: [Mmio<u32>; 2],
    _dtccr: [Mmio<u32>; 2],
    _rsv0: [Mmio<u32>; 2],
    tnpds: [Mmio<u32>; 2],
    thpds: [Mmio<u32>; 2],
    _rsv1: [Mmio<u8>; 7],
    cmd: Mmio<u8>,
    tppoll: Mmio<u8>,
    _rsv2: [Mmio<u8>; 3],
    imr: Mmio<u16>,
    isr: Mmio<u16>,
    tcr: Mmio<u32>,
    rcr: Mmio<u32>,
    _tctr: Mmio<u32>,
    _rsv3: Mmio<u32>,
    cmd_9346: Mmio<u8>,
    _config: [Mmio<u8>; 6],
    _rsv4: Mmio<u8>,
    timer_int: Mmio<u32>,
    _rsv5: Mmio<u32>,
    _phys_ar: Mmio<u32>,
    _rsv6: [Mmio<u32>; 2],
    phys_sts: ReadOnly<Mmio<u8>>,
    _rsv7: [Mmio<u8>; 23],
    _wakeup: [Mmio<u32>; 16],
    _crc: [Mmio<u16>; 5],
    _rsv8: [Mmio<u8>; 12],
    rms: Mmio<u16>,
    _rsv9: Mmio<u32>,
    _c_plus_cr: Mmio<u16>,
    _rsv10: Mmio<u16>,
    rdsar: [Mmio<u32>; 2],
    mtps: Mmio<u8>,
    _rsv11: [Mmio<u8>; 19],
}

const OWN: u32 = 1 << 31;
const EOR: u32 = 1 << 30;
const FS: u32 = 1 << 29;
const LS: u32 = 1 << 28;

#[repr(packed)]
struct Rd {
    ctrl: Mmio<u32>,
    _vlan: Mmio<u32>,
    buffer: Mmio<u64>
}

#[repr(packed)]
struct Td {
    ctrl: Mmio<u32>,
    _vlan: Mmio<u32>,
    buffer: Mmio<u64>
}

pub struct Rtl8168 {
    regs: &'static mut Regs,
    receive_buffer: [Dma<[Mmio<u8>; 0x1FF8]>; 16],
    receive_ring: Dma<[Rd; 16]>,
    transmit_buffer: [Dma<[Mmio<u8>; 7552]>; 16],
    transmit_ring: Dma<[Td; 16]>,
    transmit_buffer_h: [Dma<[Mmio<u8>; 7552]>; 1],
    transmit_ring_h: Dma<[Td; 1]>
}

impl SchemeMut for Rtl8168 {
    fn open(&mut self, _path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
        if uid == 0 {
            Ok(flags)
        } else {
            Err(Error::new(EACCES))
        }
    }

    fn dup(&mut self, id: usize, _buf: &[u8]) -> Result<usize> {
        Ok(id)
    }

    fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
        for (rd_i, rd) in self.receive_ring.iter_mut().enumerate() {
            if ! rd.ctrl.readf(OWN) {
                let rd_len = rd.ctrl.read() & 0x3FFF;

                let data = &self.receive_buffer[rd_i as usize];

                let mut i = 0;
                while i < buf.len() && i < rd_len as usize {
                    buf[i] = data[i].read();
                    i += 1;
                }

                let eor = rd.ctrl.read() & EOR;
                rd.ctrl.write(OWN | eor | data.len() as u32);

                return Ok(i);
            }
        }

        if id & O_NONBLOCK == O_NONBLOCK {
            Ok(0)
        } else {
            Err(Error::new(EWOULDBLOCK))
        }
    }

    fn write(&mut self, _id: usize, buf: &[u8]) -> Result<usize> {
        loop {
            for (td_i, td) in self.transmit_ring.iter_mut().enumerate() {
                if ! td.ctrl.readf(OWN) {

                    let mut data = &mut self.transmit_buffer[td_i as usize];

                    let mut i = 0;
                    while i < buf.len() && i < data.len() {
                        data[i].write(buf[i]);
                        i += 1;
                    }

                    let eor = td.ctrl.read() & EOR;
                    td.ctrl.write(OWN | eor | FS | LS | i as u32);

                    self.regs.tppoll.writef(1 << 6, true); //Notify of normal priority packet

                    while self.regs.tppoll.readf(1 << 6) {
                        unsafe { asm!("pause" : : : "memory" : "intel", "volatile"); }
                    }

                    return Ok(i);
                }
            }

            unsafe { asm!("pause" : : : "memory" : "intel", "volatile"); }
        }
    }

    fn fevent(&mut self, _id: usize, _flags: usize) -> Result<usize> {
        Ok(0)
    }

    fn fsync(&mut self, _id: usize) -> Result<usize> {
        Ok(0)
    }

    fn close(&mut self, _id: usize) -> Result<usize> {
        Ok(0)
    }
}

impl Rtl8168 {
    pub unsafe fn new(base: usize) -> Result<Self> {
        assert_eq!(mem::size_of::<Regs>(), 256);

        let regs = &mut *(base as *mut Regs);
        assert_eq!(&regs.tnpds as *const _ as usize - base, 0x20);
        assert_eq!(&regs.cmd as *const _ as usize - base, 0x37);
        assert_eq!(&regs.tcr as *const _ as usize - base, 0x40);
        assert_eq!(&regs.rcr as *const _ as usize - base, 0x44);
        assert_eq!(&regs.cmd_9346 as *const _ as usize - base, 0x50);
        assert_eq!(&regs.phys_sts as *const _ as usize - base, 0x6C);
        assert_eq!(&regs.rms as *const _ as usize - base, 0xDA);
        assert_eq!(&regs.rdsar as *const _ as usize - base, 0xE4);
        assert_eq!(&regs.mtps as *const _ as usize - base, 0xEC);

        let mut module = Rtl8168 {
            regs: regs,
            receive_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?],
            receive_ring: Dma::zeroed()?,
            transmit_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?],
            transmit_ring: Dma::zeroed()?,
            transmit_buffer_h: [Dma::zeroed()?],
            transmit_ring_h: Dma::zeroed()?
        };

        module.init();

        Ok(module)
    }

    pub unsafe fn irq(&mut self) -> u16 {
        // Read and then clear the ISR
        let isr = self.regs.isr.read();
        self.regs.isr.write(isr);
        let imr = self.regs.imr.read();
        isr & imr
    }

    pub fn next_read(&self) -> usize {
        for rd in self.receive_ring.iter() {
            if ! rd.ctrl.readf(OWN) {
                return rd.ctrl.read() as usize & 0x3FFF;
            }
        }
        0
    }

    pub unsafe fn init(&mut self) {
        let mac_low = self.regs.mac[0].read();
        let mac_high = self.regs.mac[1].read();
        let mac = [mac_low as u8,
                    (mac_low >> 8) as u8,
                    (mac_low >> 16) as u8,
                    (mac_low >> 24) as u8,
                    mac_high as u8,
                    (mac_high >> 8) as u8];
        print!("{}", format!("   - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
        let _ = setcfg("mac", &format!("{:>02X}.{:>02X}.{:>02X}.{:>02X}.{:>02X}.{:>02X}", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));

        // Reset - this will disable tx and rx, reinitialize FIFOs, and set the system buffer pointer to the initial value
        self.regs.cmd.writef(1 << 4, true);
        while self.regs.cmd.readf(1 << 4) {}

        // Set up rx buffers
        for i in 0..self.receive_ring.len() {
            let rd = &mut self.receive_ring[i];
            let data = &mut self.receive_buffer[i];
            rd.buffer.write(data.physical() as u64);
            rd.ctrl.write(OWN | data.len() as u32);
        }
        if let Some(mut rd) = self.receive_ring.last_mut() {
            rd.ctrl.writef(EOR, true);
        }

        // Set up normal priority tx buffers
        for i in 0..self.transmit_ring.len() {
            self.transmit_ring[i].buffer.write(self.transmit_buffer[i].physical() as u64);
        }
        if let Some(mut td) = self.transmit_ring.last_mut() {
            td.ctrl.writef(EOR, true);
        }

        // Set up high priority tx buffers
        for i in 0..self.transmit_ring_h.len() {
            self.transmit_ring_h[i].buffer.write(self.transmit_buffer_h[i].physical() as u64);
        }
        if let Some(mut td) = self.transmit_ring_h.last_mut() {
            td.ctrl.writef(EOR, true);
        }

        // Unlock config
        self.regs.cmd_9346.write(1 << 7 | 1 << 6);

        // Enable rx (bit 3) and tx (bit 2)
        self.regs.cmd.writef(1 << 3 | 1 << 2, true);

        // Max RX packet size
        self.regs.rms.write(0x1FF8);

        // Max TX packet size
        self.regs.mtps.write(0x3B);

        // Set tx low priority buffer address
        self.regs.tnpds[0].write(self.transmit_ring.physical() as u32);
        self.regs.tnpds[1].write((self.transmit_ring.physical() >> 32) as u32);

        // Set tx high priority buffer address
        self.regs.thpds[0].write(self.transmit_ring_h.physical() as u32);
        self.regs.thpds[1].write((self.transmit_ring_h.physical() >> 32) as u32);

        // Set rx buffer address
        self.regs.rdsar[0].write(self.receive_ring.physical() as u32);
        self.regs.rdsar[1].write((self.receive_ring.physical() >> 32) as u32);

        // Disable timer interrupt
        self.regs.timer_int.write(0);

        //Clear ISR
        let isr = self.regs.isr.read();
        self.regs.isr.write(isr);

        // Interrupt on tx error (bit 3), tx ok (bit 2), rx error(bit 1), and rx ok (bit 0)
        self.regs.imr.write(1 << 15 | 1 << 14 | 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1);

        // Set TX config
        self.regs.tcr.write(0b11 << 24 | 0b111 << 8);

        // Set RX config - Accept broadcast (bit 3), multicast (bit 2), and unicast (bit 1)
        self.regs.rcr.write(0xE70E);

        // Lock config
        self.regs.cmd_9346.write(0);
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern mod opengles;   // FIXME: Should only be for tests.
use glut::{swap_buffers, GLint};
use self::opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, COMPILE_STATUS};
use self::opengles::gl2::{FRAGMENT_SHADER, LINK_STATUS, NO_ERROR, STATIC_DRAW};
use self::opengles::gl2::{TRIANGLE_STRIP, VERTEX_SHADER, GLenum};
use self::opengles::gl2::{GLsizei, GLuint, attach_shader, bind_buffer};
use self::opengles::gl2::{buffer_data, create_program, clear, clear_color};
use self::opengles::gl2::{compile_shader, create_shader, draw_arrays};
use self::opengles::gl2::{enable_vertex_attrib_array, gen_buffers};
use self::opengles::gl2::{get_attrib_location, get_error, get_program_iv};
use self::opengles::gl2::{get_shader_info_log, get_shader_iv};
use self::opengles::gl2::{link_program, shader_source};
use self::opengles::gl2::{use_program, vertex_attrib_pointer_f32};

use std::comm;
use std::libc::c_int;
use std::io::println;
use std::task;

fn fragment_shader_source() -> ~str {
    ~"
    #ifdef GLES2
        precision mediump float;
    #endif

        void main(void) {
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
    "
}

fn vertex_shader_source() -> ~str {
    ~"
        attribute vec3 aVertexPosition;

        /*uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;*/

        void main(void) {
            gl_Position = /*uPMatrix * uMVMatrix **/
                vec4(aVertexPosition, 1.0);
        }
    "
}

fn load_shader(source_str: ~str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, [source_str.as_bytes().to_owned()]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(fmt!("error: %d", get_error() as int));
        fail!(~"failed to compile shader with error");
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(get_shader_info_log(shader_id));
        fail!(~"failed to compile shader");
    }
    return shader_id;
}

struct ShaderProgram {
    program: GLuint,
    aVertexPosition: c_int,
    /*let uPMatrix: c_int;
    let uMVMatrix: c_int;*/
}

fn ShaderProgram(program: GLuint) -> ShaderProgram {
    let p = ShaderProgram {
        program : program,
        aVertexPosition : get_attrib_location(program, ~"aVertexPosition"),
        /*self.uPMatrix : get_uniform_location(program, "uPMatrix"),
        self.uMVMatrix : get_uniform_location(program, "uMVMatrix")*/
    };
    enable_vertex_attrib_array(p.aVertexPosition as GLuint);
    return p;
}

fn init_shaders() -> ShaderProgram {
    let vertex_shader = load_shader(vertex_shader_source(), VERTEX_SHADER);
    let fragment_shader = load_shader(fragment_shader_source(),
                                      FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail!(~"failed to initialize program");
    }

    use_program(program);

    return ShaderProgram(program);
}

fn init_buffers() -> GLuint {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);
    let vertices = ~[
        0.0f32, 1.0f32, 0.0f32,
        1.0f32, 0.0f32, 0.0f32,
        0.0f32, 0.0f32, 0.0f32
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);
    return triangle_vertex_buffer;
}

fn draw_scene(shader_program: ShaderProgram, vertex_buffer: GLuint) {
    clear_color(0.0f32, 0.0f32, 1.0f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    bind_buffer(ARRAY_BUFFER, vertex_buffer);
    vertex_attrib_pointer_f32(shader_program.aVertexPosition as GLuint,
                              3 as GLint, false, 0 as GLsizei, 0 as GLuint);
    draw_arrays(TRIANGLE_STRIP, 0 as GLint, 3 as GLint);
}

fn display_callback() {
    let program = init_shaders();
    let vertex_buffer = init_buffers();
    draw_scene(program, vertex_buffer);

    swap_buffers();
}

/*
#[test]
fn test_triangle_and_square() {
    let (po, ch): (Port<()>, Chan<()>) = stream();
    let _result_ch: Chan<()> = do spawn_listener | _po | {
        init();
        init_display_mode(DOUBLE);
        let window = create_window(~"Rust GLUT");
        display_func(display_callback);

        let (wakeup, wakeup_chan): (Port<()>, Chan<()>) = stream();

        do timer_func(1000) { wakeup_chan.send(()); }

        loop {
            check_loop();

            if wakeup.peek() {
                wakeup.recv();
                ch.send(());
                destroy_window(window);
                break;
            }
        }
    };

    po.recv();
}
*/

pub fn spawn_listener<A: Send>(f: ~fn(Port<A>)) -> Chan<A> {
    let (setup_po, setup_ch) = comm::stream();
    do task::spawn {
        let (po, ch) = comm::stream();
        setup_ch.send(ch);
        f(po);
    }
    setup_po.recv()
}
<commit_msg>fmt! -> format!<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern mod opengles;   // FIXME: Should only be for tests.
use glut::{swap_buffers, GLint};
use self::opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, COMPILE_STATUS};
use self::opengles::gl2::{FRAGMENT_SHADER, LINK_STATUS, NO_ERROR, STATIC_DRAW};
use self::opengles::gl2::{TRIANGLE_STRIP, VERTEX_SHADER, GLenum};
use self::opengles::gl2::{GLsizei, GLuint, attach_shader, bind_buffer};
use self::opengles::gl2::{buffer_data, create_program, clear, clear_color};
use self::opengles::gl2::{compile_shader, create_shader, draw_arrays};
use self::opengles::gl2::{enable_vertex_attrib_array, gen_buffers};
use self::opengles::gl2::{get_attrib_location, get_error, get_program_iv};
use self::opengles::gl2::{get_shader_info_log, get_shader_iv};
use self::opengles::gl2::{link_program, shader_source};
use self::opengles::gl2::{use_program, vertex_attrib_pointer_f32};

use std::comm;
use std::libc::c_int;
use std::io::println;
use std::task;

fn fragment_shader_source() -> ~str {
    ~"
    #ifdef GLES2
        precision mediump float;
    #endif

        void main(void) {
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
    "
}

fn vertex_shader_source() -> ~str {
    ~"
        attribute vec3 aVertexPosition;

        /*uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;*/

        void main(void) {
            gl_Position = /*uPMatrix * uMVMatrix **/
                vec4(aVertexPosition, 1.0);
        }
    "
}

fn load_shader(source_str: ~str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, [source_str.as_bytes().to_owned()]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(format!("error: {:d}", get_error() as int));
        fail!(~"failed to compile shader with error");
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(get_shader_info_log(shader_id));
        fail!(~"failed to compile shader");
    }
    return shader_id;
}

struct ShaderProgram {
    program: GLuint,
    aVertexPosition: c_int,
    /*let uPMatrix: c_int;
    let uMVMatrix: c_int;*/
}

fn ShaderProgram(program: GLuint) -> ShaderProgram {
    let p = ShaderProgram {
        program : program,
        aVertexPosition : get_attrib_location(program, ~"aVertexPosition"),
        /*self.uPMatrix : get_uniform_location(program, "uPMatrix"),
        self.uMVMatrix : get_uniform_location(program, "uMVMatrix")*/
    };
    enable_vertex_attrib_array(p.aVertexPosition as GLuint);
    return p;
}

fn init_shaders() -> ShaderProgram {
    let vertex_shader = load_shader(vertex_shader_source(), VERTEX_SHADER);
    let fragment_shader = load_shader(fragment_shader_source(),
                                      FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail!(~"failed to initialize program");
    }

    use_program(program);

    return ShaderProgram(program);
}

fn init_buffers() -> GLuint {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);
    let vertices = ~[
        0.0f32, 1.0f32, 0.0f32,
        1.0f32, 0.0f32, 0.0f32,
        0.0f32, 0.0f32, 0.0f32
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);
    return triangle_vertex_buffer;
}

fn draw_scene(shader_program: ShaderProgram, vertex_buffer: GLuint) {
    clear_color(0.0f32, 0.0f32, 1.0f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    bind_buffer(ARRAY_BUFFER, vertex_buffer);
    vertex_attrib_pointer_f32(shader_program.aVertexPosition as GLuint,
                              3 as GLint, false, 0 as GLsizei, 0 as GLuint);
    draw_arrays(TRIANGLE_STRIP, 0 as GLint, 3 as GLint);
}

fn display_callback() {
    let program = init_shaders();
    let vertex_buffer = init_buffers();
    draw_scene(program, vertex_buffer);

    swap_buffers();
}

/*
#[test]
fn test_triangle_and_square() {
    let (po, ch): (Port<()>, Chan<()>) = stream();
    let _result_ch: Chan<()> = do spawn_listener | _po | {
        init();
        init_display_mode(DOUBLE);
        let window = create_window(~"Rust GLUT");
        display_func(display_callback);

        let (wakeup, wakeup_chan): (Port<()>, Chan<()>) = stream();

        do timer_func(1000) { wakeup_chan.send(()); }

        loop {
            check_loop();

            if wakeup.peek() {
                wakeup.recv();
                ch.send(());
                destroy_window(window);
                break;
            }
        }
    };

    po.recv();
}
*/

pub fn spawn_listener<A: Send>(f: ~fn(Port<A>)) -> Chan<A> {
    let (setup_po, setup_ch) = comm::stream();
    do task::spawn {
        let (po, ch) = comm::stream();
        setup_ch.send(ch);
        f(po);
    }
    setup_po.recv()
}
<|endoftext|>


<commit_before>// Kevin Cantu
// additional vector functions

use std;

fn windowed <copy TT> (nn: uint, xx: [TT]) -> [[TT]] {
   let ww = [];

   if nn < 1u {
      fail "windowed: n should be >= 1";
   }

   vec::iteri (xx, {|ii, _x|
      let len = vec::len(xx);

      if ii+nn <= len {
         let w = vec::slice ( xx, ii, ii+nn );
         vec::push (ww, w);
      }
   });

   ret ww;
}

#[test]
fn windowed_test_3of6 () {
   assert [[1u,2u,3u],[2u,3u,4u],[3u,4u,5u],[4u,5u,6u]]
          == windowed (3u, [1u,2u,3u,4u,5u,6u]);
}

#[test]
fn windowed_test_4of6 () {
   assert [[1u,2u,3u,4u],[2u,3u,4u,5u],[3u,4u,5u,6u]]
          == windowed (4u, [1u,2u,3u,4u,5u,6u]);
}

#[test]
#[should_fail]
fn windowed_test_0of6 () {
   let _x = windowed (0u, [1u,2u,3u,4u,5u,6u]);
}

#[test]
fn windowed_test_7of6 () {
   assert [] == windowed (7u, [1u,2u,3u,4u,5u,6u]);
}

<commit_msg>take and splitAt<commit_after>// Kevin Cantu
// additional vector functions

use std;

fn windowed <copy TT> (nn: uint, xx: [TT]) -> [[TT]] {
   let ww = [];

   assert 1u <= nn;

   vec::iteri (xx, {|ii, _x|
      let len = vec::len(xx);

      if ii+nn <= len {
         let w = vec::slice ( xx, ii, ii+nn );
         vec::push (ww, w);
      }
   });

   ret ww;
}

#[test]
fn windowed_test_3of6 () {
   assert [[1u,2u,3u],[2u,3u,4u],[3u,4u,5u],[4u,5u,6u]]
          == windowed (3u, [1u,2u,3u,4u,5u,6u]);
}

#[test]
fn windowed_test_4of6 () {
   assert [[1u,2u,3u,4u],[2u,3u,4u,5u],[3u,4u,5u,6u]]
          == windowed (4u, [1u,2u,3u,4u,5u,6u]);
}

#[test]
#[should_fail]
fn windowed_test_0of6 () {
   let _x = windowed (0u, [1u,2u,3u,4u,5u,6u]);
}

#[test]
fn windowed_test_7of6 () {
   assert [] == windowed (7u, [1u,2u,3u,4u,5u,6u]);
}

fn splitAt <copy TT> (nn: uint, xx: [TT]) -> ([TT],[TT]) {
   assert 0u <= nn;
   assert nn <= vec::len(xx);
   (vec::slice(xx,0u,nn), vec::slice(xx,nn,vec::len(xx)))
}

#[test]
fn splitAt_test_a () {
   let temp: ([u8],[u8]) = splitAt(0u, []);
   assert ([],[]) == temp;
}

#[test]
fn splitAt_test_b () {
   assert ([],[1u]) == splitAt(0u, [1u]);
}

#[test]
fn splitAt_test_c () {
   assert ([1u],[]) == splitAt(1u, [1u]);
}

#[test]
#[should_fail]
fn splitAt_test_d () {
   let temp: ([u8],[u8]) = splitAt(7u, []);
   assert ([],[]) == temp;
}

fn take <copy TT> (nn: uint, xx: [TT]) -> [TT] {
   ret vec::slice (xx, 0u, nn);
}

<|endoftext|>