<commit_before>use std::{
    convert::TryFrom,
    fmt::{self, Display},
    str::FromStr,
};

use http::Method;

use crate::{error::UnknownVersionError, AuthScheme};

/// Metadata about an API endpoint.
#[derive(Clone, Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct Metadata {
    /// A human-readable description of the endpoint.
    pub description: &'static str,

    /// The HTTP method used by this endpoint.
    pub method: Method,

    /// A unique identifier for this endpoint.
    pub name: &'static str,

    /// The unstable path of this endpoint's URL, often `None`, used for developmental
    /// purposes.
    pub unstable_path: Option<&'static str>,

    /// The pre-v1.1 version of this endpoint's URL, `None` for post-v1.1 endpoints,
    /// supplemental to `stable_path`.
    pub r0_path: Option<&'static str>,

    /// The path of this endpoint's URL, with variable names where path parameters should be
    /// filled in during a request.
    pub stable_path: Option<&'static str>,

    /// Whether or not this endpoint is rate limited by the server.
    pub rate_limited: bool,

    /// What authentication scheme the server uses for this endpoint.
    pub authentication: AuthScheme,

    /// The matrix version that this endpoint was added in.
    ///
    /// Is None when this endpoint is unstable/unreleased.
    pub added: Option<MatrixVersion>,

    /// The matrix version that deprecated this endpoint.
    ///
    /// Deprecation often precedes one matrix version before removal.
    ///
    /// This will make [`try_into_http_request`](crate::OutgoingRequest::try_into_http_request)
    /// emit a warning, see the corresponding documentation for more information.
    pub deprecated: Option<MatrixVersion>,

    /// The matrix version that removed this endpoint.
    ///
    /// This will make [`try_into_http_request`](crate::OutgoingRequest::try_into_http_request)
    /// emit an error, see the corresponding documentation for more information.
    pub removed: Option<MatrixVersion>,
}

/// The Matrix versions Ruma currently understands to exist.
///
/// Matrix, since fall 2021, has a quarterly release schedule, using a global `vX.Y` versioning
/// scheme.
///
/// Every new minor version denotes stable support for endpoints in a *relatively*
/// backwards-compatible manner.
///
/// Matrix has a deprecation policy, read more about it here: <https://spec.matrix.org/v1.2/#deprecation-policy>.
///
/// Ruma keeps track of when endpoints are added, deprecated, and removed. It'll automatically
/// select the right endpoint stability variation to use depending on which Matrix versions you
/// pass to [`try_into_http_request`](crate::OutgoingRequest::try_into_http_request), see its
/// respective documentation for more information.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub enum MatrixVersion {
    /// Version 1.0 of the Matrix specification.
    ///
    /// Retroactively defined as <https://spec.matrix.org/v1.1/#legacy-versioning>.
    V1_0,

    /// Version 1.1 of the Matrix specification, released in Q4 2021.
    ///
    /// See <https://spec.matrix.org/v1.1/>.
    V1_1,

    /// Version 1.2 of the Matrix specification, released in Q1 2022.
    ///
    /// See <https://spec.matrix.org/v1.2/>.
    V1_2,
}

impl TryFrom<&str> for MatrixVersion {
    type Error = UnknownVersionError;

    fn try_from(value: &str) -> Result<MatrixVersion, Self::Error> {
        use MatrixVersion::*;

        Ok(match value {
            // FIXME: these are likely not entirely correct; https://github.com/ruma/ruma/issues/852
            "v1.0" |
            // Additional definitions according to https://spec.matrix.org/v1.2/#legacy-versioning
            "r0.5.0" | "r0.6.0" | "r0.6.1" => V1_0,
            "v1.1" => V1_1,
            "v1.2" => V1_2,
            _ => return Err(UnknownVersionError),
        })
    }
}

impl FromStr for MatrixVersion {
    type Err = UnknownVersionError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::try_from(s)
    }
}

impl MatrixVersion {
    /// Checks whether a version is compatible with another.
    ///
    /// A is compatible with B as long as B is equal or less, so long as A and B have the same
    /// major versions.
    ///
    /// For example, v1.2 is compatible with v1.1, as it is likely only some additions of
    /// endpoints on top of v1.1, but v1.1 would not be compatible with v1.2, as v1.1
    /// cannot represent all of v1.2, in a manner similar to set theory.
    ///
    /// Warning: Matrix has a deprecation policy, and Matrix versioning is not as
    /// straight-forward as this function makes it out to be. This function only exists
    /// to prune major version differences, and versions too new for `self`.
    ///
    /// This (considering if major versions are the same) is equivalent to a `self >= other`
    /// check.
    pub fn is_superset_of(self, other: Self) -> bool {
        let (major_l, minor_l) = self.into_parts();
        let (major_r, minor_r) = other.into_parts();
        major_l == major_r && minor_l >= minor_r
    }

    /// Decompose the Matrix version into its major and minor number.
    pub fn into_parts(self) -> (u8, u8) {
        match self {
            MatrixVersion::V1_0 => (1, 0),
            MatrixVersion::V1_1 => (1, 1),
            MatrixVersion::V1_2 => (1, 2),
        }
    }

    /// Try to turn a pair of (major, minor) version components back into a `MatrixVersion`.
    pub fn from_parts(major: u8, minor: u8) -> Result<Self, UnknownVersionError> {
        match (major, minor) {
            (1, 0) => Ok(MatrixVersion::V1_0),
            (1, 1) => Ok(MatrixVersion::V1_1),
            (1, 2) => Ok(MatrixVersion::V1_2),
            _ => Err(UnknownVersionError),
        }
    }
}

impl Display for MatrixVersion {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let (major, minor) = self.into_parts();
        f.write_str(&format!("v{}.{}", major, minor))
    }
}
<commit_msg>api: Update a link<commit_after>use std::{
    convert::TryFrom,
    fmt::{self, Display},
    str::FromStr,
};

use http::Method;

use crate::{error::UnknownVersionError, AuthScheme};

/// Metadata about an API endpoint.
#[derive(Clone, Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct Metadata {
    /// A human-readable description of the endpoint.
    pub description: &'static str,

    /// The HTTP method used by this endpoint.
    pub method: Method,

    /// A unique identifier for this endpoint.
    pub name: &'static str,

    /// The unstable path of this endpoint's URL, often `None`, used for developmental
    /// purposes.
    pub unstable_path: Option<&'static str>,

    /// The pre-v1.1 version of this endpoint's URL, `None` for post-v1.1 endpoints,
    /// supplemental to `stable_path`.
    pub r0_path: Option<&'static str>,

    /// The path of this endpoint's URL, with variable names where path parameters should be
    /// filled in during a request.
    pub stable_path: Option<&'static str>,

    /// Whether or not this endpoint is rate limited by the server.
    pub rate_limited: bool,

    /// What authentication scheme the server uses for this endpoint.
    pub authentication: AuthScheme,

    /// The matrix version that this endpoint was added in.
    ///
    /// Is None when this endpoint is unstable/unreleased.
    pub added: Option<MatrixVersion>,

    /// The matrix version that deprecated this endpoint.
    ///
    /// Deprecation often precedes one matrix version before removal.
    ///
    /// This will make [`try_into_http_request`](crate::OutgoingRequest::try_into_http_request)
    /// emit a warning, see the corresponding documentation for more information.
    pub deprecated: Option<MatrixVersion>,

    /// The matrix version that removed this endpoint.
    ///
    /// This will make [`try_into_http_request`](crate::OutgoingRequest::try_into_http_request)
    /// emit an error, see the corresponding documentation for more information.
    pub removed: Option<MatrixVersion>,
}

/// The Matrix versions Ruma currently understands to exist.
///
/// Matrix, since fall 2021, has a quarterly release schedule, using a global `vX.Y` versioning
/// scheme.
///
/// Every new minor version denotes stable support for endpoints in a *relatively*
/// backwards-compatible manner.
///
/// Matrix has a deprecation policy, read more about it here: <https://spec.matrix.org/v1.2/#deprecation-policy>.
///
/// Ruma keeps track of when endpoints are added, deprecated, and removed. It'll automatically
/// select the right endpoint stability variation to use depending on which Matrix versions you
/// pass to [`try_into_http_request`](crate::OutgoingRequest::try_into_http_request), see its
/// respective documentation for more information.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub enum MatrixVersion {
    /// Version 1.0 of the Matrix specification.
    ///
    /// Retroactively defined as <https://spec.matrix.org/v1.2/#legacy-versioning>.
    V1_0,

    /// Version 1.1 of the Matrix specification, released in Q4 2021.
    ///
    /// See <https://spec.matrix.org/v1.1/>.
    V1_1,

    /// Version 1.2 of the Matrix specification, released in Q1 2022.
    ///
    /// See <https://spec.matrix.org/v1.2/>.
    V1_2,
}

impl TryFrom<&str> for MatrixVersion {
    type Error = UnknownVersionError;

    fn try_from(value: &str) -> Result<MatrixVersion, Self::Error> {
        use MatrixVersion::*;

        Ok(match value {
            // FIXME: these are likely not entirely correct; https://github.com/ruma/ruma/issues/852
            "v1.0" |
            // Additional definitions according to https://spec.matrix.org/v1.2/#legacy-versioning
            "r0.5.0" | "r0.6.0" | "r0.6.1" => V1_0,
            "v1.1" => V1_1,
            "v1.2" => V1_2,
            _ => return Err(UnknownVersionError),
        })
    }
}

impl FromStr for MatrixVersion {
    type Err = UnknownVersionError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::try_from(s)
    }
}

impl MatrixVersion {
    /// Checks whether a version is compatible with another.
    ///
    /// A is compatible with B as long as B is equal or less, so long as A and B have the same
    /// major versions.
    ///
    /// For example, v1.2 is compatible with v1.1, as it is likely only some additions of
    /// endpoints on top of v1.1, but v1.1 would not be compatible with v1.2, as v1.1
    /// cannot represent all of v1.2, in a manner similar to set theory.
    ///
    /// Warning: Matrix has a deprecation policy, and Matrix versioning is not as
    /// straight-forward as this function makes it out to be. This function only exists
    /// to prune major version differences, and versions too new for `self`.
    ///
    /// This (considering if major versions are the same) is equivalent to a `self >= other`
    /// check.
    pub fn is_superset_of(self, other: Self) -> bool {
        let (major_l, minor_l) = self.into_parts();
        let (major_r, minor_r) = other.into_parts();
        major_l == major_r && minor_l >= minor_r
    }

    /// Decompose the Matrix version into its major and minor number.
    pub fn into_parts(self) -> (u8, u8) {
        match self {
            MatrixVersion::V1_0 => (1, 0),
            MatrixVersion::V1_1 => (1, 1),
            MatrixVersion::V1_2 => (1, 2),
        }
    }

    /// Try to turn a pair of (major, minor) version components back into a `MatrixVersion`.
    pub fn from_parts(major: u8, minor: u8) -> Result<Self, UnknownVersionError> {
        match (major, minor) {
            (1, 0) => Ok(MatrixVersion::V1_0),
            (1, 1) => Ok(MatrixVersion::V1_1),
            (1, 2) => Ok(MatrixVersion::V1_2),
            _ => Err(UnknownVersionError),
        }
    }
}

impl Display for MatrixVersion {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let (major, minor) = self.into_parts();
        f.write_str(&format!("v{}.{}", major, minor))
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The high-level interface from script to constellation. Using this abstract interface helps
//! reduce coupling between these two components.

use geom::rect::Rect;
use geom::size::TypedSize2D;
use geom::scale_factor::ScaleFactor;
use hyper::header::Headers;
use hyper::method::Method;
use layers::geometry::DevicePixel;
use util::cursor::Cursor;
use util::geometry::{PagePx, ViewportPx};
use std::sync::mpsc::{channel, Sender, Receiver};
use url::Url;

#[derive(Clone)]
pub struct ConstellationChan(pub Sender<Msg>);

impl ConstellationChan {
    pub fn new() -> (Receiver<Msg>, ConstellationChan) {
        let (chan, port) = channel();
        (port, ConstellationChan(chan))
    }
}

#[derive(PartialEq, Eq, Copy, Debug)]
pub enum IFrameSandboxState {
    IFrameSandboxed,
    IFrameUnsandboxed
}

// We pass this info to various tasks, so it lives in a separate, cloneable struct.
#[derive(Clone, Copy)]
pub struct Failure {
    pub pipeline_id: PipelineId,
    pub parent_info: Option<(PipelineId, SubpageId)>,
}

#[derive(Copy)]
pub struct WindowSizeData {
    /// The size of the initial layout viewport, before parsing an
    /// http://www.w3.org/TR/css-device-adapt/#initial-viewport
    pub initial_viewport: TypedSize2D<ViewportPx, f32>,

    /// The "viewing area" in page px. See `PagePx` documentation for details.
    pub visible_viewport: TypedSize2D<PagePx, f32>,

    /// The resolution of the window in dppx, not including any "pinch zoom" factor.
    pub device_pixel_ratio: ScaleFactor<ViewportPx, DevicePixel, f32>,
}

#[derive(PartialEq, Eq, Copy, Clone)]
pub enum KeyState {
    Pressed,
    Released,
    Repeated,
}

//N.B. Based on the glutin key enum
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Key {
    Space,
    Apostrophe,
    Comma,
    Minus,
    Period,
    Slash,
    Num0,
    Num1,
    Num2,
    Num3,
    Num4,
    Num5,
    Num6,
    Num7,
    Num8,
    Num9,
    Semicolon,
    Equal,
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H,
    I,
    J,
    K,
    L,
    M,
    N,
    O,
    P,
    Q,
    R,
    S,
    T,
    U,
    V,
    W,
    X,
    Y,
    Z,
    LeftBracket,
    Backslash,
    RightBracket,
    GraveAccent,
    World1,
    World2,

    Escape,
    Enter,
    Tab,
    Backspace,
    Insert,
    Delete,
    Right,
    Left,
    Down,
    Up,
    PageUp,
    PageDown,
    Home,
    End,
    CapsLock,
    ScrollLock,
    NumLock,
    PrintScreen,
    Pause,
    F1,
    F2,
    F3,
    F4,
    F5,
    F6,
    F7,
    F8,
    F9,
    F10,
    F11,
    F12,
    F13,
    F14,
    F15,
    F16,
    F17,
    F18,
    F19,
    F20,
    F21,
    F22,
    F23,
    F24,
    F25,
    Kp0,
    Kp1,
    Kp2,
    Kp3,
    Kp4,
    Kp5,
    Kp6,
    Kp7,
    Kp8,
    Kp9,
    KpDecimal,
    KpDivide,
    KpMultiply,
    KpSubtract,
    KpAdd,
    KpEnter,
    KpEqual,
    LeftShift,
    LeftControl,
    LeftAlt,
    LeftSuper,
    RightShift,
    RightControl,
    RightAlt,
    RightSuper,
    Menu,
}

bitflags! {
    flags KeyModifiers: u8 {
        const SHIFT = 0x01,
        const CONTROL = 0x02,
        const ALT = 0x04,
        const SUPER = 0x08,
    }
}

/// Messages from the compositor and script to the constellation.
pub enum Msg {
    Exit,
    Failure(Failure),
    InitLoadUrl(Url),
    LoadComplete,
    FrameRect(PipelineId, SubpageId, Rect<f32>),
    LoadUrl(PipelineId, LoadData),
    ScriptLoadedURLInIFrame(Url, PipelineId, SubpageId, Option<SubpageId>, IFrameSandboxState),
    Navigate(Option<(PipelineId, SubpageId)>, NavigationDirection),
    PainterReady(PipelineId),
    ResizedWindow(WindowSizeData),
    KeyEvent(Key, KeyState, KeyModifiers),
    /// Requests that the constellation inform the compositor of the title of the pipeline
    /// immediately.
    GetPipelineTitle(PipelineId),
    /// Requests that the constellation inform the compositor of the a cursor change.
    SetCursor(Cursor),
    /// Dispatch a mozbrowser event to a given iframe. Only available in experimental mode.
    MozBrowserEventMsg(PipelineId, SubpageId, MozBrowserEvent),
}

// https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API#Events
pub enum MozBrowserEvent {
    /// Sent when the scroll position within a browser <iframe> changes.
    AsyncScroll,
    /// Sent when window.close() is called within a browser <iframe>.
    Close,
    /// Sent when a browser <iframe> tries to open a context menu. This allows  handling <menuitem> element available within the browser <iframe>'s content.
    ContextMenu,
    /// Sent when an error occurred while trying to load content within a browser <iframe>.
    Error,
    /// Sent when the favicon of a browser <iframe> changes.
    IconChange,
    /// Sent when the browser <iframe> has finished loading all its assets.
    LoadEnd,
    /// Sent when the browser <iframe> starts to load a new page.
    LoadStart,
    /// Sent when a browser <iframe>'s location changes.
    LocationChange(String),
    /// Sent when window.open() is called within a browser <iframe>.
    OpenWindow,
    /// Sent when the SSL state changes within a browser <iframe>.
    SecurityChange,
    /// Sent when alert(), confirm(), or prompt() is called within a browser <iframe>.
    ShowModalPrompt,
    /// Sent when the document.title changes within a browser <iframe>.
    TitleChange(String),
    /// Sent when an HTTP authentification is requested.
    UsernameAndPasswordRequired,
    /// Sent when a link to a search engine is found.
    OpenSearch,
}

impl MozBrowserEvent {
    pub fn name(&self) -> &'static str {
        match *self {
            MozBrowserEvent::AsyncScroll => "mozbrowserasyncscroll",
            MozBrowserEvent::Close => "mozbrowserclose",
            MozBrowserEvent::ContextMenu => "mozbrowsercontextmenu",
            MozBrowserEvent::Error => "mozbrowsererror",
            MozBrowserEvent::IconChange => "mozbrowsericonchange",
            MozBrowserEvent::LoadEnd => "mozbrowserloadend",
            MozBrowserEvent::LoadStart => "mozbrowserloadstart",
            MozBrowserEvent::LocationChange(_) => "mozbrowserlocationchange",
            MozBrowserEvent::OpenWindow => "mozbrowseropenwindow",
            MozBrowserEvent::SecurityChange => "mozbrowsersecuritychange",
            MozBrowserEvent::ShowModalPrompt => "mozbrowsershowmodalprompt",
            MozBrowserEvent::TitleChange(_) => "mozbrowsertitlechange",
            MozBrowserEvent::UsernameAndPasswordRequired => "mozbrowserusernameandpasswordrequired",
            MozBrowserEvent::OpenSearch => "mozbrowseropensearch"
        }
    }
    pub fn detail(&self) -> Option<String> {
        match *self {
            MozBrowserEvent::AsyncScroll | MozBrowserEvent::Close | MozBrowserEvent::ContextMenu |
            MozBrowserEvent::Error | MozBrowserEvent::IconChange | MozBrowserEvent::LoadEnd |
            MozBrowserEvent::LoadStart | MozBrowserEvent::OpenWindow | MozBrowserEvent::SecurityChange |
            MozBrowserEvent::ShowModalPrompt | MozBrowserEvent::UsernameAndPasswordRequired | MozBrowserEvent::OpenSearch => None,
            MozBrowserEvent::LocationChange(ref new_location) => Some(new_location.clone()),
            MozBrowserEvent::TitleChange(ref new_title) => Some(new_title.clone()),
        }
    }
}

/// Similar to net::resource_task::LoadData
/// can be passed to LoadUrl to load a page with GET/POST
/// parameters or headers
#[derive(Clone)]
pub struct LoadData {
    pub url: Url,
    pub method: Method,
    pub headers: Headers,
    pub data: Option<Vec<u8>>,
}

impl LoadData {
    pub fn new(url: Url) -> LoadData {
        LoadData {
            url: url,
            method: Method::Get,
            headers: Headers::new(),
            data: None,
        }
    }
}

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub enum NavigationDirection {
    Forward,
    Back,
}

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct FrameId(pub uint);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct WorkerId(pub uint);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct PipelineId(pub uint);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct SubpageId(pub uint);

// The type of pipeline exit. During complete shutdowns, pipelines do not have to
// release resources automatically released on process termination.
#[derive(Copy)]
pub enum PipelineExitType {
    PipelineOnly,
    Complete,
}
<commit_msg>Use u32 for FrameId.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The high-level interface from script to constellation. Using this abstract interface helps
//! reduce coupling between these two components.

use geom::rect::Rect;
use geom::size::TypedSize2D;
use geom::scale_factor::ScaleFactor;
use hyper::header::Headers;
use hyper::method::Method;
use layers::geometry::DevicePixel;
use util::cursor::Cursor;
use util::geometry::{PagePx, ViewportPx};
use std::sync::mpsc::{channel, Sender, Receiver};
use url::Url;

#[derive(Clone)]
pub struct ConstellationChan(pub Sender<Msg>);

impl ConstellationChan {
    pub fn new() -> (Receiver<Msg>, ConstellationChan) {
        let (chan, port) = channel();
        (port, ConstellationChan(chan))
    }
}

#[derive(PartialEq, Eq, Copy, Debug)]
pub enum IFrameSandboxState {
    IFrameSandboxed,
    IFrameUnsandboxed
}

// We pass this info to various tasks, so it lives in a separate, cloneable struct.
#[derive(Clone, Copy)]
pub struct Failure {
    pub pipeline_id: PipelineId,
    pub parent_info: Option<(PipelineId, SubpageId)>,
}

#[derive(Copy)]
pub struct WindowSizeData {
    /// The size of the initial layout viewport, before parsing an
    /// http://www.w3.org/TR/css-device-adapt/#initial-viewport
    pub initial_viewport: TypedSize2D<ViewportPx, f32>,

    /// The "viewing area" in page px. See `PagePx` documentation for details.
    pub visible_viewport: TypedSize2D<PagePx, f32>,

    /// The resolution of the window in dppx, not including any "pinch zoom" factor.
    pub device_pixel_ratio: ScaleFactor<ViewportPx, DevicePixel, f32>,
}

#[derive(PartialEq, Eq, Copy, Clone)]
pub enum KeyState {
    Pressed,
    Released,
    Repeated,
}

//N.B. Based on the glutin key enum
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Key {
    Space,
    Apostrophe,
    Comma,
    Minus,
    Period,
    Slash,
    Num0,
    Num1,
    Num2,
    Num3,
    Num4,
    Num5,
    Num6,
    Num7,
    Num8,
    Num9,
    Semicolon,
    Equal,
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H,
    I,
    J,
    K,
    L,
    M,
    N,
    O,
    P,
    Q,
    R,
    S,
    T,
    U,
    V,
    W,
    X,
    Y,
    Z,
    LeftBracket,
    Backslash,
    RightBracket,
    GraveAccent,
    World1,
    World2,

    Escape,
    Enter,
    Tab,
    Backspace,
    Insert,
    Delete,
    Right,
    Left,
    Down,
    Up,
    PageUp,
    PageDown,
    Home,
    End,
    CapsLock,
    ScrollLock,
    NumLock,
    PrintScreen,
    Pause,
    F1,
    F2,
    F3,
    F4,
    F5,
    F6,
    F7,
    F8,
    F9,
    F10,
    F11,
    F12,
    F13,
    F14,
    F15,
    F16,
    F17,
    F18,
    F19,
    F20,
    F21,
    F22,
    F23,
    F24,
    F25,
    Kp0,
    Kp1,
    Kp2,
    Kp3,
    Kp4,
    Kp5,
    Kp6,
    Kp7,
    Kp8,
    Kp9,
    KpDecimal,
    KpDivide,
    KpMultiply,
    KpSubtract,
    KpAdd,
    KpEnter,
    KpEqual,
    LeftShift,
    LeftControl,
    LeftAlt,
    LeftSuper,
    RightShift,
    RightControl,
    RightAlt,
    RightSuper,
    Menu,
}

bitflags! {
    flags KeyModifiers: u8 {
        const SHIFT = 0x01,
        const CONTROL = 0x02,
        const ALT = 0x04,
        const SUPER = 0x08,
    }
}

/// Messages from the compositor and script to the constellation.
pub enum Msg {
    Exit,
    Failure(Failure),
    InitLoadUrl(Url),
    LoadComplete,
    FrameRect(PipelineId, SubpageId, Rect<f32>),
    LoadUrl(PipelineId, LoadData),
    ScriptLoadedURLInIFrame(Url, PipelineId, SubpageId, Option<SubpageId>, IFrameSandboxState),
    Navigate(Option<(PipelineId, SubpageId)>, NavigationDirection),
    PainterReady(PipelineId),
    ResizedWindow(WindowSizeData),
    KeyEvent(Key, KeyState, KeyModifiers),
    /// Requests that the constellation inform the compositor of the title of the pipeline
    /// immediately.
    GetPipelineTitle(PipelineId),
    /// Requests that the constellation inform the compositor of the a cursor change.
    SetCursor(Cursor),
    /// Dispatch a mozbrowser event to a given iframe. Only available in experimental mode.
    MozBrowserEventMsg(PipelineId, SubpageId, MozBrowserEvent),
}

// https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API#Events
pub enum MozBrowserEvent {
    /// Sent when the scroll position within a browser <iframe> changes.
    AsyncScroll,
    /// Sent when window.close() is called within a browser <iframe>.
    Close,
    /// Sent when a browser <iframe> tries to open a context menu. This allows  handling <menuitem> element available within the browser <iframe>'s content.
    ContextMenu,
    /// Sent when an error occurred while trying to load content within a browser <iframe>.
    Error,
    /// Sent when the favicon of a browser <iframe> changes.
    IconChange,
    /// Sent when the browser <iframe> has finished loading all its assets.
    LoadEnd,
    /// Sent when the browser <iframe> starts to load a new page.
    LoadStart,
    /// Sent when a browser <iframe>'s location changes.
    LocationChange(String),
    /// Sent when window.open() is called within a browser <iframe>.
    OpenWindow,
    /// Sent when the SSL state changes within a browser <iframe>.
    SecurityChange,
    /// Sent when alert(), confirm(), or prompt() is called within a browser <iframe>.
    ShowModalPrompt,
    /// Sent when the document.title changes within a browser <iframe>.
    TitleChange(String),
    /// Sent when an HTTP authentification is requested.
    UsernameAndPasswordRequired,
    /// Sent when a link to a search engine is found.
    OpenSearch,
}

impl MozBrowserEvent {
    pub fn name(&self) -> &'static str {
        match *self {
            MozBrowserEvent::AsyncScroll => "mozbrowserasyncscroll",
            MozBrowserEvent::Close => "mozbrowserclose",
            MozBrowserEvent::ContextMenu => "mozbrowsercontextmenu",
            MozBrowserEvent::Error => "mozbrowsererror",
            MozBrowserEvent::IconChange => "mozbrowsericonchange",
            MozBrowserEvent::LoadEnd => "mozbrowserloadend",
            MozBrowserEvent::LoadStart => "mozbrowserloadstart",
            MozBrowserEvent::LocationChange(_) => "mozbrowserlocationchange",
            MozBrowserEvent::OpenWindow => "mozbrowseropenwindow",
            MozBrowserEvent::SecurityChange => "mozbrowsersecuritychange",
            MozBrowserEvent::ShowModalPrompt => "mozbrowsershowmodalprompt",
            MozBrowserEvent::TitleChange(_) => "mozbrowsertitlechange",
            MozBrowserEvent::UsernameAndPasswordRequired => "mozbrowserusernameandpasswordrequired",
            MozBrowserEvent::OpenSearch => "mozbrowseropensearch"
        }
    }
    pub fn detail(&self) -> Option<String> {
        match *self {
            MozBrowserEvent::AsyncScroll | MozBrowserEvent::Close | MozBrowserEvent::ContextMenu |
            MozBrowserEvent::Error | MozBrowserEvent::IconChange | MozBrowserEvent::LoadEnd |
            MozBrowserEvent::LoadStart | MozBrowserEvent::OpenWindow | MozBrowserEvent::SecurityChange |
            MozBrowserEvent::ShowModalPrompt | MozBrowserEvent::UsernameAndPasswordRequired | MozBrowserEvent::OpenSearch => None,
            MozBrowserEvent::LocationChange(ref new_location) => Some(new_location.clone()),
            MozBrowserEvent::TitleChange(ref new_title) => Some(new_title.clone()),
        }
    }
}

/// Similar to net::resource_task::LoadData
/// can be passed to LoadUrl to load a page with GET/POST
/// parameters or headers
#[derive(Clone)]
pub struct LoadData {
    pub url: Url,
    pub method: Method,
    pub headers: Headers,
    pub data: Option<Vec<u8>>,
}

impl LoadData {
    pub fn new(url: Url) -> LoadData {
        LoadData {
            url: url,
            method: Method::Get,
            headers: Headers::new(),
            data: None,
        }
    }
}

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub enum NavigationDirection {
    Forward,
    Back,
}

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct FrameId(pub u32);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct WorkerId(pub uint);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct PipelineId(pub uint);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct SubpageId(pub uint);

// The type of pipeline exit. During complete shutdowns, pipelines do not have to
// release resources automatically released on process termination.
#[derive(Copy)]
pub enum PipelineExitType {
    PipelineOnly,
    Complete,
}
<|endoftext|>


<commit_before>extern crate event;
extern crate netutils;
extern crate rand;
extern crate syscall;

use rand::{Rng, OsRng};
use std::collections::{BTreeMap, VecDeque};
use std::cell::RefCell;
use std::fs::File;
use std::io::{self, Read, Write};
use std::{mem, slice, str};
use std::os::unix::io::FromRawFd;
use std::rc::Rc;

use event::EventQueue;
use netutils::{n16, Ipv4, Ipv4Addr, Ipv4Header, Udp, UdpHeader, Checksum};
use syscall::data::Packet;
use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EMSGSIZE, ENOTCONN, EWOULDBLOCK};
use syscall::flag::{EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_CREAT, O_RDWR, O_NONBLOCK};
use syscall::scheme::SchemeMut;

fn parse_socket(socket: &str) -> (Ipv4Addr, u16) {
    let mut socket_parts = socket.split(":");
    let host = Ipv4Addr::from_str(socket_parts.next().unwrap_or(""));
    let port = socket_parts.next().unwrap_or("").parse::<u16>().unwrap_or(0);
    (host, port)
}

struct Handle {
    local: (Ipv4Addr, u16),
    remote: (Ipv4Addr, u16),
    flags: usize,
    events: usize,
    data: VecDeque<Vec<u8>>,
    todo: VecDeque<Packet>,
}

struct Udpd {
    scheme_file: File,
    udp_file: File,
    ports: BTreeMap<u16, usize>,
    next_id: usize,
    handles: BTreeMap<usize, Handle>,
    rng: OsRng,
}

impl Udpd {
    fn new(scheme_file: File, udp_file: File) -> Self {
        Udpd {
            scheme_file: scheme_file,
            udp_file: udp_file,
            ports: BTreeMap::new(),
            next_id: 1,
            handles: BTreeMap::new(),
            rng: OsRng::new().expect("udpd: failed to open RNG")
        }
    }

    fn scheme_event(&mut self) -> io::Result<()> {
        loop {
            let mut packet = Packet::default();
            if self.scheme_file.read(&mut packet)? == 0 {
                break;
            }

            let a = packet.a;
            self.handle(&mut packet);
            if packet.a == (-EWOULDBLOCK) as usize {
                packet.a = a;
                if let Some(mut handle) = self.handles.get_mut(&packet.b) {
                    handle.todo.push_back(packet);
                }
            } else {
                self.scheme_file.write(&packet)?;
            }
        }

        Ok(())
    }

    fn udp_event(&mut self) -> io::Result<()> {
        loop {
            let mut bytes = [0; 65536];
            let count = self.udp_file.read(&mut bytes)?;
            if count == 0 {
                break;
            }
            if let Some(ip) = Ipv4::from_bytes(&bytes[.. count]) {
                if let Some(udp) = Udp::from_bytes(&ip.data) {
                    for (id, handle) in self.handles.iter_mut() {
                            // Local address not set or IP dst matches or is broadcast
                        if (handle.local.0 == Ipv4Addr::NULL || ip.header.dst == handle.local.0 || ip.header.dst == Ipv4Addr::BROADCAST)
                            // Local port matches UDP dst
                            && udp.header.dst.get() == handle.local.1
                            // Remote address not set or is broadcast, or IP src matches
                            && (handle.remote.0 == Ipv4Addr::NULL || handle.remote.0 == Ipv4Addr::BROADCAST || ip.header.src == handle.remote.0)
                            // Remote port not set or UDP src matches
                            && (handle.remote.1 == 0 || udp.header.src.get() == handle.remote.1)
                        {
                            handle.data.push_back(udp.data.clone());

                            while ! handle.todo.is_empty() && ! handle.data.is_empty() {
                                let mut packet = handle.todo.pop_front().unwrap();
                                let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) };
                                let data = handle.data.pop_front().unwrap();

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

                                self.scheme_file.write(&packet)?;
                            }

                            if handle.events & EVENT_READ == EVENT_READ {
                                if let Some(data) = handle.data.get(0) {
                                    self.scheme_file.write(&Packet {
                                        id: 0,
                                        pid: 0,
                                        uid: 0,
                                        gid: 0,
                                        a: syscall::number::SYS_FEVENT,
                                        b: *id,
                                        c: EVENT_READ,
                                        d: data.len()
                                    })?;
                                }
                            }
                        }
                    }
                }
            }
        }

        Ok(())
    }
}

impl SchemeMut for Udpd {
    fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
        let path = str::from_utf8(url).or(Err(Error::new(EINVAL)))?;

        let mut parts = path.split("/");
        let remote = parse_socket(parts.next().unwrap_or(""));
        let mut local = parse_socket(parts.next().unwrap_or(""));

        if local.1 == 0 {
            local.1 = self.rng.gen_range(32768, 65535);
        }

        if local.1 <= 1024 && uid != 0 {
            return Err(Error::new(EACCES));
        }

        if self.ports.contains_key(&local.1) {
            return Err(Error::new(EADDRINUSE));
        }

        self.ports.insert(local.1, 1);

        let id = self.next_id;
        self.next_id += 1;

        self.handles.insert(id, Handle {
            local: local,
            remote: remote,
            flags: flags,
            events: 0,
            data: VecDeque::new(),
            todo: VecDeque::new(),
        });

        Ok(id)
    }

    fn dup(&mut self, file: usize, buf: &[u8]) -> Result<usize> {
        let mut handle = {
            let handle = self.handles.get(&file).ok_or(Error::new(EBADF))?;
            Handle {
                local: handle.local,
                remote: handle.remote,
                flags: handle.flags,
                events: 0,
                data: handle.data.clone(),
                todo: VecDeque::new(),
            }
        };

        let path = str::from_utf8(buf).or(Err(Error::new(EINVAL)))?;

        if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 {
            handle.remote = parse_socket(path);
        }

        if let Some(mut port) = self.ports.get_mut(&handle.local.1) {
            *port = *port + 1;
        }

        let id = self.next_id;
        self.next_id += 1;

        self.handles.insert(id, handle);

        Ok(id)
    }

    fn read(&mut self, file: usize, buf: &mut [u8]) -> Result<usize> {
        let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?;

        if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 {
            Err(Error::new(ENOTCONN))
        } else if let Some(data) = handle.data.pop_front() {
            let mut i = 0;
            while i < buf.len() && i < data.len() {
                buf[i] = data[i];
                i += 1;
            }

            Ok(i)
        } else if handle.flags & O_NONBLOCK == O_NONBLOCK {
            Ok(0)
        } else {
            Err(Error::new(EWOULDBLOCK))
        }
    }

    fn write(&mut self, file: usize, buf: &[u8]) -> Result<usize> {
        let handle = self.handles.get(&file).ok_or(Error::new(EBADF))?;

        if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 {
            Err(Error::new(ENOTCONN))
        } else if buf.len() >= 65507 {
            Err(Error::new(EMSGSIZE))
        } else {
            let udp_data = buf.to_vec();

            let udp = Udp {
                header: UdpHeader {
                    src: n16::new(handle.local.1),
                    dst: n16::new(handle.remote.1),
                    len: n16::new((udp_data.len() + mem::size_of::<UdpHeader>()) as u16),
                    checksum: Checksum { data: 0 }
                },
                data: udp_data
            };

            let ip_data = udp.to_bytes();

            let ip = Ipv4 {
                header: Ipv4Header {
                    ver_hlen: 0x45,
                    services: 0,
                    len: n16::new((ip_data.len() + mem::size_of::<Ipv4Header>()) as u16),
                    id: n16::new(self.rng.gen()),
                    flags_fragment: n16::new(0),
                    ttl: 127,
                    proto: 0x11,
                    checksum: Checksum { data: 0 },
                    src: handle.local.0,
                    dst: handle.remote.0
                },
                options: Vec::new(),
                data: ip_data
            };

            self.udp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))
        }
    }

    fn fcntl(&mut self, file: usize, cmd: usize, arg: usize) -> Result<usize> {
        let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?;

        match cmd {
            F_GETFL => Ok(handle.flags),
            F_SETFL => {
                handle.flags = arg & ! O_ACCMODE;
                Ok(0)
            },
            _ => Err(Error::new(EINVAL))
        }
    }

    fn fevent(&mut self, file: usize, flags: usize) -> Result<usize> {
        let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?;

        handle.events = flags;

        Ok(file)
    }

    fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;

        let path_string = format!("udp:{}:{}/{}:{}", handle.remote.0.to_string(), handle.remote.1, handle.local.0.to_string(), handle.local.1);
        let path = path_string.as_bytes();

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

        Ok(i)
    }

    fn fsync(&mut self, file: usize) -> Result<usize> {
        let _handle = self.handles.get(&file).ok_or(Error::new(EBADF))?;

        Ok(0)
    }

    fn close(&mut self, file: usize) -> Result<usize> {
        let handle = self.handles.remove(&file).ok_or(Error::new(EBADF))?;

        let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) {
            *port = *port + 1;
            *port == 0
        } else {
            false
        };

        if remove {
            drop(self.ports.remove(&handle.local.1));
        }

        drop(handle);

        Ok(0)
    }
}

fn main() {
    // Daemonize
    if unsafe { syscall::clone(0).unwrap() } == 0 {
        let scheme_fd = syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK).expect("udpd: failed to create :udp");
        let scheme_file = unsafe { File::from_raw_fd(scheme_fd) };

        let udp_fd = syscall::open("ip:11", O_RDWR | O_NONBLOCK).expect("udpd: failed to open ip:11");
        let udp_file = unsafe { File::from_raw_fd(udp_fd) };

        let udpd = Rc::new(RefCell::new(Udpd::new(scheme_file, udp_file)));

        let mut event_queue = EventQueue::<()>::new().expect("udpd: failed to create event queue");

        let udp_udpd = udpd.clone();
        event_queue.add(udp_fd, move |_count: usize| -> io::Result<Option<()>> {
            udp_udpd.borrow_mut().udp_event()?;
            Ok(None)
        }).expect("udpd: failed to listen to events on ip:11");

        event_queue.add(scheme_fd, move |_count: usize| -> io::Result<Option<()>> {
            udpd.borrow_mut().scheme_event()?;
            Ok(None)
        }).expect("udpd: failed to listen to events on :udp");

        event_queue.trigger_all(0).expect("udpd: failed to trigger event queue");

        event_queue.run().expect("udpd: failed to run event queue");
    }
}
<commit_msg>Fix udpd compile<commit_after>extern crate event;
extern crate netutils;
extern crate rand;
extern crate syscall;

use rand::{Rng, OsRng};
use std::collections::{BTreeMap, VecDeque};
use std::cell::RefCell;
use std::fs::File;
use std::io::{self, Read, Write};
use std::{mem, slice, str};
use std::os::unix::io::FromRawFd;
use std::rc::Rc;

use event::EventQueue;
use netutils::{n16, Ipv4, Ipv4Addr, Ipv4Header, Checksum};
use netutils::udp::{Udp, UdpHeader};
use syscall::data::Packet;
use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EMSGSIZE, ENOTCONN, EWOULDBLOCK};
use syscall::flag::{EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_CREAT, O_RDWR, O_NONBLOCK};
use syscall::scheme::SchemeMut;

fn parse_socket(socket: &str) -> (Ipv4Addr, u16) {
    let mut socket_parts = socket.split(":");
    let host = Ipv4Addr::from_str(socket_parts.next().unwrap_or(""));
    let port = socket_parts.next().unwrap_or("").parse::<u16>().unwrap_or(0);
    (host, port)
}

struct Handle {
    local: (Ipv4Addr, u16),
    remote: (Ipv4Addr, u16),
    flags: usize,
    events: usize,
    data: VecDeque<Vec<u8>>,
    todo: VecDeque<Packet>,
}

struct Udpd {
    scheme_file: File,
    udp_file: File,
    ports: BTreeMap<u16, usize>,
    next_id: usize,
    handles: BTreeMap<usize, Handle>,
    rng: OsRng,
}

impl Udpd {
    fn new(scheme_file: File, udp_file: File) -> Self {
        Udpd {
            scheme_file: scheme_file,
            udp_file: udp_file,
            ports: BTreeMap::new(),
            next_id: 1,
            handles: BTreeMap::new(),
            rng: OsRng::new().expect("udpd: failed to open RNG")
        }
    }

    fn scheme_event(&mut self) -> io::Result<()> {
        loop {
            let mut packet = Packet::default();
            if self.scheme_file.read(&mut packet)? == 0 {
                break;
            }

            let a = packet.a;
            self.handle(&mut packet);
            if packet.a == (-EWOULDBLOCK) as usize {
                packet.a = a;
                if let Some(mut handle) = self.handles.get_mut(&packet.b) {
                    handle.todo.push_back(packet);
                }
            } else {
                self.scheme_file.write(&packet)?;
            }
        }

        Ok(())
    }

    fn udp_event(&mut self) -> io::Result<()> {
        loop {
            let mut bytes = [0; 65536];
            let count = self.udp_file.read(&mut bytes)?;
            if count == 0 {
                break;
            }
            if let Some(ip) = Ipv4::from_bytes(&bytes[.. count]) {
                if let Some(udp) = Udp::from_bytes(&ip.data) {
                    for (id, handle) in self.handles.iter_mut() {
                            // Local address not set or IP dst matches or is broadcast
                        if (handle.local.0 == Ipv4Addr::NULL || ip.header.dst == handle.local.0 || ip.header.dst == Ipv4Addr::BROADCAST)
                            // Local port matches UDP dst
                            && udp.header.dst.get() == handle.local.1
                            // Remote address not set or is broadcast, or IP src matches
                            && (handle.remote.0 == Ipv4Addr::NULL || handle.remote.0 == Ipv4Addr::BROADCAST || ip.header.src == handle.remote.0)
                            // Remote port not set or UDP src matches
                            && (handle.remote.1 == 0 || udp.header.src.get() == handle.remote.1)
                        {
                            handle.data.push_back(udp.data.clone());

                            while ! handle.todo.is_empty() && ! handle.data.is_empty() {
                                let mut packet = handle.todo.pop_front().unwrap();
                                let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) };
                                let data = handle.data.pop_front().unwrap();

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

                                self.scheme_file.write(&packet)?;
                            }

                            if handle.events & EVENT_READ == EVENT_READ {
                                if let Some(data) = handle.data.get(0) {
                                    self.scheme_file.write(&Packet {
                                        id: 0,
                                        pid: 0,
                                        uid: 0,
                                        gid: 0,
                                        a: syscall::number::SYS_FEVENT,
                                        b: *id,
                                        c: EVENT_READ,
                                        d: data.len()
                                    })?;
                                }
                            }
                        }
                    }
                }
            }
        }

        Ok(())
    }
}

impl SchemeMut for Udpd {
    fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
        let path = str::from_utf8(url).or(Err(Error::new(EINVAL)))?;

        let mut parts = path.split("/");
        let remote = parse_socket(parts.next().unwrap_or(""));
        let mut local = parse_socket(parts.next().unwrap_or(""));

        if local.1 == 0 {
            local.1 = self.rng.gen_range(32768, 65535);
        }

        if local.1 <= 1024 && uid != 0 {
            return Err(Error::new(EACCES));
        }

        if self.ports.contains_key(&local.1) {
            return Err(Error::new(EADDRINUSE));
        }

        self.ports.insert(local.1, 1);

        let id = self.next_id;
        self.next_id += 1;

        self.handles.insert(id, Handle {
            local: local,
            remote: remote,
            flags: flags,
            events: 0,
            data: VecDeque::new(),
            todo: VecDeque::new(),
        });

        Ok(id)
    }

    fn dup(&mut self, file: usize, buf: &[u8]) -> Result<usize> {
        let mut handle = {
            let handle = self.handles.get(&file).ok_or(Error::new(EBADF))?;
            Handle {
                local: handle.local,
                remote: handle.remote,
                flags: handle.flags,
                events: 0,
                data: handle.data.clone(),
                todo: VecDeque::new(),
            }
        };

        let path = str::from_utf8(buf).or(Err(Error::new(EINVAL)))?;

        if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 {
            handle.remote = parse_socket(path);
        }

        if let Some(mut port) = self.ports.get_mut(&handle.local.1) {
            *port = *port + 1;
        }

        let id = self.next_id;
        self.next_id += 1;

        self.handles.insert(id, handle);

        Ok(id)
    }

    fn read(&mut self, file: usize, buf: &mut [u8]) -> Result<usize> {
        let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?;

        if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 {
            Err(Error::new(ENOTCONN))
        } else if let Some(data) = handle.data.pop_front() {
            let mut i = 0;
            while i < buf.len() && i < data.len() {
                buf[i] = data[i];
                i += 1;
            }

            Ok(i)
        } else if handle.flags & O_NONBLOCK == O_NONBLOCK {
            Ok(0)
        } else {
            Err(Error::new(EWOULDBLOCK))
        }
    }

    fn write(&mut self, file: usize, buf: &[u8]) -> Result<usize> {
        let handle = self.handles.get(&file).ok_or(Error::new(EBADF))?;

        if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 {
            Err(Error::new(ENOTCONN))
        } else if buf.len() >= 65507 {
            Err(Error::new(EMSGSIZE))
        } else {
            let udp_data = buf.to_vec();

            let udp = Udp {
                header: UdpHeader {
                    src: n16::new(handle.local.1),
                    dst: n16::new(handle.remote.1),
                    len: n16::new((udp_data.len() + mem::size_of::<UdpHeader>()) as u16),
                    checksum: Checksum { data: 0 }
                },
                data: udp_data
            };

            let ip_data = udp.to_bytes();

            let ip = Ipv4 {
                header: Ipv4Header {
                    ver_hlen: 0x45,
                    services: 0,
                    len: n16::new((ip_data.len() + mem::size_of::<Ipv4Header>()) as u16),
                    id: n16::new(self.rng.gen()),
                    flags_fragment: n16::new(0),
                    ttl: 127,
                    proto: 0x11,
                    checksum: Checksum { data: 0 },
                    src: handle.local.0,
                    dst: handle.remote.0
                },
                options: Vec::new(),
                data: ip_data
            };

            self.udp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))
        }
    }

    fn fcntl(&mut self, file: usize, cmd: usize, arg: usize) -> Result<usize> {
        let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?;

        match cmd {
            F_GETFL => Ok(handle.flags),
            F_SETFL => {
                handle.flags = arg & ! O_ACCMODE;
                Ok(0)
            },
            _ => Err(Error::new(EINVAL))
        }
    }

    fn fevent(&mut self, file: usize, flags: usize) -> Result<usize> {
        let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?;

        handle.events = flags;

        Ok(file)
    }

    fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;

        let path_string = format!("udp:{}:{}/{}:{}", handle.remote.0.to_string(), handle.remote.1, handle.local.0.to_string(), handle.local.1);
        let path = path_string.as_bytes();

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

        Ok(i)
    }

    fn fsync(&mut self, file: usize) -> Result<usize> {
        let _handle = self.handles.get(&file).ok_or(Error::new(EBADF))?;

        Ok(0)
    }

    fn close(&mut self, file: usize) -> Result<usize> {
        let handle = self.handles.remove(&file).ok_or(Error::new(EBADF))?;

        let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) {
            *port = *port + 1;
            *port == 0
        } else {
            false
        };

        if remove {
            drop(self.ports.remove(&handle.local.1));
        }

        drop(handle);

        Ok(0)
    }
}

fn main() {
    // Daemonize
    if unsafe { syscall::clone(0).unwrap() } == 0 {
        let scheme_fd = syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK).expect("udpd: failed to create :udp");
        let scheme_file = unsafe { File::from_raw_fd(scheme_fd) };

        let udp_fd = syscall::open("ip:11", O_RDWR | O_NONBLOCK).expect("udpd: failed to open ip:11");
        let udp_file = unsafe { File::from_raw_fd(udp_fd) };

        let udpd = Rc::new(RefCell::new(Udpd::new(scheme_file, udp_file)));

        let mut event_queue = EventQueue::<()>::new().expect("udpd: failed to create event queue");

        let udp_udpd = udpd.clone();
        event_queue.add(udp_fd, move |_count: usize| -> io::Result<Option<()>> {
            udp_udpd.borrow_mut().udp_event()?;
            Ok(None)
        }).expect("udpd: failed to listen to events on ip:11");

        event_queue.add(scheme_fd, move |_count: usize| -> io::Result<Option<()>> {
            udpd.borrow_mut().scheme_event()?;
            Ok(None)
        }).expect("udpd: failed to listen to events on :udp");

        event_queue.trigger_all(0).expect("udpd: failed to trigger event queue");

        event_queue.run().expect("udpd: failed to run event queue");
    }
}
<|endoftext|>


<commit_before>//! A very simple HTTP server which responds with the plain text "Hello, World!" to every request.
extern mod rustymvc;
extern mod extra;
extern mod http;

use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};
use std::rt::io::Writer;
use extra::time;
use extra::arc::Arc;

use http::server::{Config, Server, ServerUtil, Request, ResponseWriter};
use http::server::request::RequestUri;
use http::headers::content_type::MediaType;

use rustymvc::router::{ControllerContext, HttpContext, Router, Response, Request};

#[deriving(Clone)]
struct MvcServer{
    router: Arc<Router>
}

impl MvcServer {
    fn new() -> MvcServer {
        let router=MvcServer::init_router();

        MvcServer{router: Arc::new(router)}
    }
    fn init_router() -> Router {
        let mut router=Router::new();
        {
            let mut test = router.controller(|_| TestController::new());
            test.handles(~"/test").with(|c,ctx| c.index(ctx));
        }
        {
            let mut test = router.controller(|_| TestController::new());
            test.handles(~"/say/[message]").with(|c,ctx| c.say(ctx));
        }
        return router;
    //router.execute(&mut context);
    }
}

impl Server for MvcServer {
    fn get_config(&self) -> Config {
        Config { bind_address: SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8001 } }
    }

    fn handle_request(&self, r: &http::server::Request, w: &mut ResponseWriter) {
        let mut c=context(r);
        let mut tmp = &mut self.router.clone();
        tmp.get().execute(&mut c);
        /*
        w.headers.date = Some(time::now_utc());
        w.headers.content_length = Some(14);
        w.headers.content_type = Some(MediaType {
            type_: ~"text",
            subtype: ~"plain",
            parameters: ~[(~"charset", ~"UTF-8")]
        });
        w.headers.server = Some(~"Example");
        */
        w.headers.content_type = Some(MediaType {
            type_: ~"text",
            subtype: ~"plain",
            parameters: ~[(~"charset", ~"UTF-8")]
        });
        w.write(c.response.body.into_bytes());
    }

}

struct TestController;

impl TestController{
    fn new() -> TestController{
    TestController
    }
    fn index(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str("test index");
    }
    fn say(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str(context.route_params[~"message"]);
    }
}

fn context(req: &http::server::Request) -> HttpContext {
    println!("uri: {:?}", req.request_uri);
    HttpContext {
        request: Request{
            path: path_to_str(&req.request_uri),//format!("{:?}", req.request_uri),
            querystring: ~""
        },
        response: Response::new()
    }
}

enum Foo
{
    Star,
    Baz(Router),
    Bar(~str)
}
fn tester(foo: Foo) -> ~str{
    match foo {
        Star => ~"",
        Bar(x) => x.to_owned(),
        Baz(r) => ~"foo"
    }
}

fn path_to_str(r: &http::server::request::RequestUri) -> ~str {
    match *r {
        http::server::request::Star => ~"",
        http::server::request::AbsoluteUri(_) => ~"",
        http::server::request::AbsolutePath(ref path) => path.to_owned(),
        http::server::request::Authority(_) => ~""
    }

}

fn main() {
    MvcServer::new().serve_forever();
}
<commit_msg>Clean up the rust-http example more<commit_after>//! A very simple HTTP server which responds with the plain text "Hello, World!" to every request.
extern mod rustymvc;
extern mod extra;
extern mod http;

use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};
use std::rt::io::Writer;
use extra::arc::Arc;

use http::server::{Config, Server, ServerUtil, ResponseWriter};
use http::server::request::RequestUri;
use http::headers::content_type::MediaType;

use rustymvc::router::{ControllerContext, HttpContext, Router, Response, Request};

#[deriving(Clone)]
struct MvcServer{
    router: Arc<Router>
}

impl MvcServer {
    fn new() -> MvcServer {
        let router=MvcServer::init_router();

        MvcServer{router: Arc::new(router)}
    }
    fn init_router() -> Router {
        let mut router=Router::new();
        {
            let mut test = router.controller(|_| TestController::new());
            test.handles(~"/test").with(|c,ctx| c.index(ctx));
        }
        {
            let mut test = router.controller(|_| TestController::new());
            test.handles(~"/say/[message]").with(|c,ctx| c.say(ctx));
        }
        return router;
    }
}

impl Server for MvcServer {
    fn get_config(&self) -> Config {
        Config { bind_address: SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8001 } }
    }

    fn handle_request(&self, r: &http::server::Request, w: &mut ResponseWriter) {
        let mut c=context(r);
        let tmp = &mut self.router.clone();
        tmp.get().execute(&mut c);

        let parts=c.response.contenttype.split_iter('/').to_owned_vec();
        w.headers.content_type = Some(MediaType {
            type_: parts[0].to_owned(),
            subtype: parts[1].to_owned(),
            parameters: ~[(~"charset", ~"UTF-8")]
        });
        w.write(c.response.body.into_bytes());
    }

}

struct TestController;

impl TestController{
    fn new() -> TestController{
    TestController
    }
    fn index(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str("test index");
    }
    fn say(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str(context.route_params[~"message"]);
    }
}

fn context(req: &http::server::Request) -> HttpContext {
    println!("uri: {:?}", req.request_uri);
    HttpContext {
        request: Request{
            path: path_to_str(&req.request_uri),
            querystring: ~"" //currently rust-http doesn't parse query strings
        },
        response: Response::new()
    }
}

fn path_to_str(r: &http::server::request::RequestUri) -> ~str {
    match *r {
        http::server::request::Star => ~"",
        http::server::request::AbsoluteUri(_) => ~"",
        http::server::request::AbsolutePath(ref path) => path.to_owned(),
        http::server::request::Authority(_) => ~""
    }

}

fn main() {
    MvcServer::new().serve_forever();
}
<|endoftext|>


<commit_before>use crate::backend::Backend;
use crate::dsl::{Filter, IntoBoxed};
use crate::expression::{AppearsOnTable, SelectableExpression};
use crate::query_builder::returning_clause::*;
use crate::query_builder::where_clause::*;
use crate::query_builder::*;
use crate::query_dsl::methods::{BoxedDsl, FilterDsl, OrFilterDsl};
use crate::query_dsl::RunQueryDsl;
use crate::query_source::Table;
use crate::result::QueryResult;

#[derive(Debug, Clone, Copy, QueryId)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
/// Represents a SQL `DELETE` statement.
///
/// The type parameters on this struct represent:
///
/// - `T`: The table we are deleting from.
/// - `U`: The `WHERE` clause of this query. The exact types used to represent
///   this are private, and you should not make any assumptions about them.
/// - `Ret`: The `RETURNING` clause of this query. The exact types used to
///   represent this are private. You can safely rely on the default type
///   representing the lack of a `RETURNING` clause.
pub struct DeleteStatement<T, U, Ret = NoReturningClause> {
    table: T,
    where_clause: U,
    returning: Ret,
}

/// A `DELETE` statement with a boxed `WHERE` clause
pub type BoxedDeleteStatement<'a, DB, T, Ret = NoReturningClause> =
    DeleteStatement<T, BoxedWhereClause<'a, DB>, Ret>;

impl<T, U> DeleteStatement<T, U, NoReturningClause> {
    pub(crate) fn new(table: T, where_clause: U) -> Self {
        DeleteStatement {
            table: table,
            where_clause: where_clause,
            returning: NoReturningClause,
        }
    }

    /// Adds the given predicate to the `WHERE` clause of the statement being
    /// constructed.
    ///
    /// If there is already a `WHERE` clause, the predicate will be appended
    /// with `AND`. There is no difference in behavior between
    /// `delete(table.filter(x))` and `delete(table).filter(x)`.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let deleted_rows = diesel::delete(users)
    ///     .filter(name.eq("Sean"))
    ///     .execute(connection);
    /// assert_eq!(Ok(1), deleted_rows);
    ///
    /// let expected_names = vec!["Tess".to_string()];
    /// let names = users.select(name).load(connection);
    ///
    /// assert_eq!(Ok(expected_names), names);
    /// # }
    /// ```
    pub fn filter<Predicate>(self, predicate: Predicate) -> Filter<Self, Predicate>
    where
        Self: FilterDsl<Predicate>,
    {
        FilterDsl::filter(self, predicate)
    }

    /// Boxes the `WHERE` clause of this delete statement.
    ///
    /// This is useful for cases where you want to conditionally modify a query,
    /// but need the type to remain the same. The backend must be specified as
    /// part of this. It is not possible to box a query and have it be useable
    /// on multiple backends.
    ///
    /// A boxed query will incur a minor performance penalty, as the query builder
    /// can no longer be inlined by the compiler. For most applications this cost
    /// will be minimal.
    ///
    /// ### Example
    ///
    /// ```rust
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use std::collections::HashMap;
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// #     let mut params = HashMap::new();
    /// #     params.insert("sean_has_been_a_jerk", true);
    /// let mut query = diesel::delete(users)
    ///     .into_boxed();
    ///
    /// if params["sean_has_been_a_jerk"] {
    ///     query = query.filter(name.eq("Sean"));
    /// }
    ///
    /// let deleted_rows = query.execute(connection)?;
    /// assert_eq!(1, deleted_rows);
    ///
    /// let expected_names = vec!["Tess"];
    /// let names = users.select(name).load::<String>(connection)?;
    ///
    /// assert_eq!(expected_names, names);
    /// #     Ok(())
    /// # }
    /// ```
    pub fn into_boxed<'a, DB>(self) -> IntoBoxed<'a, Self, DB>
    where
        DB: Backend,
        Self: BoxedDsl<'a, DB>,
    {
        BoxedDsl::internal_into_boxed(self)
    }
}

impl<T, U, Ret, Predicate> FilterDsl<Predicate> for DeleteStatement<T, U, Ret>
where
    U: WhereAnd<Predicate>,
    Predicate: AppearsOnTable<T>,
{
    type Output = DeleteStatement<T, U::Output, Ret>;

    fn filter(self, predicate: Predicate) -> Self::Output {
        DeleteStatement {
            table: self.table,
            where_clause: self.where_clause.and(predicate),
            returning: self.returning,
        }
    }
}

impl<T, U, Ret, Predicate> OrFilterDsl<Predicate> for DeleteStatement<T, U, Ret>
where
    U: WhereOr<Predicate>,
    Predicate: AppearsOnTable<T>,
{
    type Output = DeleteStatement<T, U::Output, Ret>;

    fn or_filter(self, predicate: Predicate) -> Self::Output {
        DeleteStatement {
            table: self.table,
            where_clause: self.where_clause.or(predicate),
            returning: self.returning,
        }
    }
}

impl<'a, T, U, Ret, DB> BoxedDsl<'a, DB> for DeleteStatement<T, U, Ret>
where
    U: Into<BoxedWhereClause<'a, DB>>,
{
    type Output = BoxedDeleteStatement<'a, DB, T, Ret>;

    fn internal_into_boxed(self) -> Self::Output {
        DeleteStatement {
            table: self.table,
            where_clause: self.where_clause.into(),
            returning: self.returning,
        }
    }
}

impl<T, U, Ret, DB> QueryFragment<DB> for DeleteStatement<T, U, Ret>
where
    DB: Backend,
    T: Table,
    T::FromClause: QueryFragment<DB>,
    U: QueryFragment<DB>,
    Ret: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("DELETE FROM ");
        self.table.from_clause().walk_ast(out.reborrow())?;
        self.where_clause.walk_ast(out.reborrow())?;
        self.returning.walk_ast(out.reborrow())?;
        Ok(())
    }
}

impl<T, U> AsQuery for DeleteStatement<T, U, NoReturningClause>
where
    T: Table,
    T::AllColumns: SelectableExpression<T>,
    DeleteStatement<T, U, ReturningClause<T::AllColumns>>: Query,
{
    type SqlType = <Self::Query as Query>::SqlType;
    type Query = DeleteStatement<T, U, ReturningClause<T::AllColumns>>;

    fn as_query(self) -> Self::Query {
        self.returning(T::all_columns())
    }
}

impl<T, U, Ret> Query for DeleteStatement<T, U, ReturningClause<Ret>>
where
    T: Table,
    Ret: SelectableExpression<T>,
{
    type SqlType = Ret::SqlType;
}

impl<T, U, Ret, Conn> RunQueryDsl<Conn> for DeleteStatement<T, U, Ret> {}

impl<T, U> DeleteStatement<T, U, NoReturningClause> {
    /// Specify what expression is returned after execution of the `delete`.
    ///
    /// # Examples
    ///
    /// ### Deleting a record:
    ///
    /// ```rust
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # #[cfg(feature = "postgres")]
    /// # fn main() {
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let deleted_name = diesel::delete(users.filter(name.eq("Sean")))
    ///     .returning(name)
    ///     .get_result(connection);
    /// assert_eq!(Ok("Sean".to_string()), deleted_name);
    /// # }
    /// # #[cfg(not(feature = "postgres"))]
    /// # fn main() {}
    /// ```
    pub fn returning<E>(self, returns: E) -> DeleteStatement<T, U, ReturningClause<E>>
    where
        E: SelectableExpression<T>,
        DeleteStatement<T, U, ReturningClause<E>>: Query,
    {
        DeleteStatement {
            table: self.table,
            where_clause: self.where_clause,
            returning: ReturningClause(returns),
        }
    }
}
<commit_msg>Add or_filter method to DeleteStatement<commit_after>use crate::backend::Backend;
use crate::dsl::{Filter, IntoBoxed, OrFilter};
use crate::expression::{AppearsOnTable, SelectableExpression};
use crate::query_builder::returning_clause::*;
use crate::query_builder::where_clause::*;
use crate::query_builder::*;
use crate::query_dsl::methods::{BoxedDsl, FilterDsl, OrFilterDsl};
use crate::query_dsl::RunQueryDsl;
use crate::query_source::Table;
use crate::result::QueryResult;

#[derive(Debug, Clone, Copy, QueryId)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
/// Represents a SQL `DELETE` statement.
///
/// The type parameters on this struct represent:
///
/// - `T`: The table we are deleting from.
/// - `U`: The `WHERE` clause of this query. The exact types used to represent
///   this are private, and you should not make any assumptions about them.
/// - `Ret`: The `RETURNING` clause of this query. The exact types used to
///   represent this are private. You can safely rely on the default type
///   representing the lack of a `RETURNING` clause.
pub struct DeleteStatement<T, U, Ret = NoReturningClause> {
    table: T,
    where_clause: U,
    returning: Ret,
}

/// A `DELETE` statement with a boxed `WHERE` clause
pub type BoxedDeleteStatement<'a, DB, T, Ret = NoReturningClause> =
    DeleteStatement<T, BoxedWhereClause<'a, DB>, Ret>;

impl<T, U> DeleteStatement<T, U, NoReturningClause> {
    pub(crate) fn new(table: T, where_clause: U) -> Self {
        DeleteStatement {
            table: table,
            where_clause: where_clause,
            returning: NoReturningClause,
        }
    }

    /// Adds the given predicate to the `WHERE` clause of the statement being
    /// constructed.
    ///
    /// If there is already a `WHERE` clause, the predicate will be appended
    /// with `AND`. There is no difference in behavior between
    /// `delete(table.filter(x))` and `delete(table).filter(x)`.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let deleted_rows = diesel::delete(users)
    ///     .filter(name.eq("Sean"))
    ///     .execute(connection);
    /// assert_eq!(Ok(1), deleted_rows);
    ///
    /// let expected_names = vec!["Tess".to_string()];
    /// let names = users.select(name).load(connection);
    ///
    /// assert_eq!(Ok(expected_names), names);
    /// # }
    /// ```
    pub fn filter<Predicate>(self, predicate: Predicate) -> Filter<Self, Predicate>
    where
        Self: FilterDsl<Predicate>,
    {
        FilterDsl::filter(self, predicate)
    }

    /// Adds to the `WHERE` clause of a query using `OR`
    ///
    /// If there is already a `WHERE` clause, the result will be `(old OR new)`.
    /// Calling `foo.filter(bar).or_filter(baz)`
    /// is identical to `foo.filter(bar.or(baz))`.
    /// However, the second form is much harder to do dynamically.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let deleted_rows = diesel::delete(users)
    ///     .filter(name.eq("Sean"))
    ///     .or_filter(name.eq("Tess"))
    ///     .execute(connection);
    /// assert_eq!(Ok(2), deleted_rows);
    ///
    /// let num_users = users.count().first(connection);
    ///
    /// assert_eq!(Ok(0), num_users);
    /// # }
    /// ```
    pub fn or_filter<Predicate>(self, predicate: Predicate) -> OrFilter<Self, Predicate>
    where
        Self: OrFilterDsl<Predicate>,
    {
        OrFilterDsl::or_filter(self, predicate)
    }

    /// Boxes the `WHERE` clause of this delete statement.
    ///
    /// This is useful for cases where you want to conditionally modify a query,
    /// but need the type to remain the same. The backend must be specified as
    /// part of this. It is not possible to box a query and have it be useable
    /// on multiple backends.
    ///
    /// A boxed query will incur a minor performance penalty, as the query builder
    /// can no longer be inlined by the compiler. For most applications this cost
    /// will be minimal.
    ///
    /// ### Example
    ///
    /// ```rust
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use std::collections::HashMap;
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// #     let mut params = HashMap::new();
    /// #     params.insert("sean_has_been_a_jerk", true);
    /// let mut query = diesel::delete(users)
    ///     .into_boxed();
    ///
    /// if params["sean_has_been_a_jerk"] {
    ///     query = query.filter(name.eq("Sean"));
    /// }
    ///
    /// let deleted_rows = query.execute(connection)?;
    /// assert_eq!(1, deleted_rows);
    ///
    /// let expected_names = vec!["Tess"];
    /// let names = users.select(name).load::<String>(connection)?;
    ///
    /// assert_eq!(expected_names, names);
    /// #     Ok(())
    /// # }
    /// ```
    pub fn into_boxed<'a, DB>(self) -> IntoBoxed<'a, Self, DB>
    where
        DB: Backend,
        Self: BoxedDsl<'a, DB>,
    {
        BoxedDsl::internal_into_boxed(self)
    }
}

impl<T, U, Ret, Predicate> FilterDsl<Predicate> for DeleteStatement<T, U, Ret>
where
    U: WhereAnd<Predicate>,
    Predicate: AppearsOnTable<T>,
{
    type Output = DeleteStatement<T, U::Output, Ret>;

    fn filter(self, predicate: Predicate) -> Self::Output {
        DeleteStatement {
            table: self.table,
            where_clause: self.where_clause.and(predicate),
            returning: self.returning,
        }
    }
}

impl<T, U, Ret, Predicate> OrFilterDsl<Predicate> for DeleteStatement<T, U, Ret>
where
    U: WhereOr<Predicate>,
    Predicate: AppearsOnTable<T>,
{
    type Output = DeleteStatement<T, U::Output, Ret>;

    fn or_filter(self, predicate: Predicate) -> Self::Output {
        DeleteStatement {
            table: self.table,
            where_clause: self.where_clause.or(predicate),
            returning: self.returning,
        }
    }
}

impl<'a, T, U, Ret, DB> BoxedDsl<'a, DB> for DeleteStatement<T, U, Ret>
where
    U: Into<BoxedWhereClause<'a, DB>>,
{
    type Output = BoxedDeleteStatement<'a, DB, T, Ret>;

    fn internal_into_boxed(self) -> Self::Output {
        DeleteStatement {
            table: self.table,
            where_clause: self.where_clause.into(),
            returning: self.returning,
        }
    }
}

impl<T, U, Ret, DB> QueryFragment<DB> for DeleteStatement<T, U, Ret>
where
    DB: Backend,
    T: Table,
    T::FromClause: QueryFragment<DB>,
    U: QueryFragment<DB>,
    Ret: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("DELETE FROM ");
        self.table.from_clause().walk_ast(out.reborrow())?;
        self.where_clause.walk_ast(out.reborrow())?;
        self.returning.walk_ast(out.reborrow())?;
        Ok(())
    }
}

impl<T, U> AsQuery for DeleteStatement<T, U, NoReturningClause>
where
    T: Table,
    T::AllColumns: SelectableExpression<T>,
    DeleteStatement<T, U, ReturningClause<T::AllColumns>>: Query,
{
    type SqlType = <Self::Query as Query>::SqlType;
    type Query = DeleteStatement<T, U, ReturningClause<T::AllColumns>>;

    fn as_query(self) -> Self::Query {
        self.returning(T::all_columns())
    }
}

impl<T, U, Ret> Query for DeleteStatement<T, U, ReturningClause<Ret>>
where
    T: Table,
    Ret: SelectableExpression<T>,
{
    type SqlType = Ret::SqlType;
}

impl<T, U, Ret, Conn> RunQueryDsl<Conn> for DeleteStatement<T, U, Ret> {}

impl<T, U> DeleteStatement<T, U, NoReturningClause> {
    /// Specify what expression is returned after execution of the `delete`.
    ///
    /// # Examples
    ///
    /// ### Deleting a record:
    ///
    /// ```rust
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # #[cfg(feature = "postgres")]
    /// # fn main() {
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let deleted_name = diesel::delete(users.filter(name.eq("Sean")))
    ///     .returning(name)
    ///     .get_result(connection);
    /// assert_eq!(Ok("Sean".to_string()), deleted_name);
    /// # }
    /// # #[cfg(not(feature = "postgres"))]
    /// # fn main() {}
    /// ```
    pub fn returning<E>(self, returns: E) -> DeleteStatement<T, U, ReturningClause<E>>
    where
        E: SelectableExpression<T>,
        DeleteStatement<T, U, ReturningClause<E>>: Query,
    {
        DeleteStatement {
            table: self.table,
            where_clause: self.where_clause,
            returning: ReturningClause(returns),
        }
    }
}
<|endoftext|>


<commit_before>use crate::backend::{Backend, SupportsOnConflictClause};
use crate::expression::SqlLiteral;
use crate::query_builder::*;
use crate::query_source::Column;
use crate::result::QueryResult;

#[cfg(feature = "postgres")]
/// Used to specify the constraint name for an upsert statement in the form `ON
/// CONFLICT ON CONSTRAINT`. Note that `constraint_name` must be the name of a
/// unique constraint, not the name of an index.
///
/// # Example
///
/// ```rust
/// # include!("on_conflict_docs_setup.rs");
/// #
/// # fn main() {
/// #     use self::users::dsl::*;
/// use diesel::upsert::*;
///
/// #     let conn = establish_connection();
/// #     conn.execute("TRUNCATE TABLE users").unwrap();
/// conn.execute("ALTER TABLE users ADD CONSTRAINT users_name UNIQUE (name)").unwrap();
/// let user = User { id: 1, name: "Sean", };
/// let same_name_different_id = User { id: 2, name: "Sean" };
/// let same_id_different_name = User { id: 1, name: "Pascal" };
///
/// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
///
/// let inserted_row_count = diesel::insert_into(users)
///     .values(&same_name_different_id)
///     .on_conflict(on_constraint("users_name"))
///     .do_nothing()
///     .execute(&conn);
/// assert_eq!(Ok(0), inserted_row_count);
///
/// let pk_conflict_result = diesel::insert_into(users)
///     .values(&same_id_different_name)
///     .on_conflict(on_constraint("users_name"))
///     .do_nothing()
///     .execute(&conn);
/// assert!(pk_conflict_result.is_err());
/// # }
/// ```
#[cfg(feature = "postgres")]
pub fn on_constraint(constraint_name: &str) -> OnConstraint {
    OnConstraint {
        constraint_name: constraint_name,
    }
}

#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct OnConstraint<'a> {
    constraint_name: &'a str,
}

pub trait OnConflictTarget<Table> {}

#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct NoConflictTarget;

impl<DB: Backend + SupportsOnConflictClause> QueryFragment<DB> for NoConflictTarget {
    fn walk_ast(&self, _: AstPass<DB>) -> QueryResult<()> {
        Ok(())
    }
}

impl<Table> OnConflictTarget<Table> for NoConflictTarget {}

#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct ConflictTarget<T>(pub T);

impl<DB, T> QueryFragment<DB> for ConflictTarget<T>
where
    DB: Backend + SupportsOnConflictClause,
    T: Column,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql(" (");
        out.push_identifier(T::NAME)?;
        out.push_sql(")");
        Ok(())
    }
}

impl<T> OnConflictTarget<T::Table> for ConflictTarget<T>
where
    T: Column,
{
}

impl<DB, ST> QueryFragment<DB> for ConflictTarget<SqlLiteral<ST>>
where
    DB: Backend + SupportsOnConflictClause,
    SqlLiteral<ST>: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql(" ");
        self.0.walk_ast(out.reborrow())?;
        Ok(())
    }
}

impl<Tab, ST> OnConflictTarget<Tab> for ConflictTarget<SqlLiteral<ST>> {}

impl<'a, DB> QueryFragment<DB> for ConflictTarget<OnConstraint<'a>>
where
    DB: Backend + SupportsOnConflictClause,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql(" ON CONSTRAINT ");
        out.push_identifier(self.0.constraint_name)?;
        Ok(())
    }
}

impl<'a, Table> OnConflictTarget<Table> for ConflictTarget<OnConstraint<'a>> {}

macro_rules! on_conflict_tuples {
    ($($col:ident),+) => {
        impl<DB, T, $($col),+> QueryFragment<DB> for ConflictTarget<(T, $($col),+)> where
            DB: Backend + SupportsOnConflictClause,
            T: Column,
            $($col: Column<Table=T::Table>,)+
        {
            fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
                out.push_sql(" (");
                out.push_identifier(T::NAME)?;
                $(
                    out.push_sql(", ");
                    out.push_identifier($col::NAME)?;
                )+
                out.push_sql(")");
                Ok(())
            }
        }

        impl<T, $($col),+> OnConflictTarget<T::Table> for ConflictTarget<(T, $($col),+)> where
            T: Column,
            $($col: Column<Table=T::Table>,)+
        {
        }
    }
}

on_conflict_tuples!(U);
on_conflict_tuples!(U, V);
on_conflict_tuples!(U, V, W);
on_conflict_tuples!(U, V, W, X);
on_conflict_tuples!(U, V, W, X, Y);
on_conflict_tuples!(U, V, W, X, Y, Z);
<commit_msg>use where clause<commit_after>use crate::backend::{Backend, SupportsOnConflictClause};
use crate::expression::SqlLiteral;
use crate::query_builder::*;
use crate::query_source::Column;
use crate::result::QueryResult;

#[cfg(feature = "postgres")]
/// Used to specify the constraint name for an upsert statement in the form `ON
/// CONFLICT ON CONSTRAINT`. Note that `constraint_name` must be the name of a
/// unique constraint, not the name of an index.
///
/// # Example
///
/// ```rust
/// # include!("on_conflict_docs_setup.rs");
/// #
/// # fn main() {
/// #     use self::users::dsl::*;
/// use diesel::upsert::*;
///
/// #     let conn = establish_connection();
/// #     conn.execute("TRUNCATE TABLE users").unwrap();
/// conn.execute("ALTER TABLE users ADD CONSTRAINT users_name UNIQUE (name)").unwrap();
/// let user = User { id: 1, name: "Sean", };
/// let same_name_different_id = User { id: 2, name: "Sean" };
/// let same_id_different_name = User { id: 1, name: "Pascal" };
///
/// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
///
/// let inserted_row_count = diesel::insert_into(users)
///     .values(&same_name_different_id)
///     .on_conflict(on_constraint("users_name"))
///     .do_nothing()
///     .execute(&conn);
/// assert_eq!(Ok(0), inserted_row_count);
///
/// let pk_conflict_result = diesel::insert_into(users)
///     .values(&same_id_different_name)
///     .on_conflict(on_constraint("users_name"))
///     .do_nothing()
///     .execute(&conn);
/// assert!(pk_conflict_result.is_err());
/// # }
/// ```
#[cfg(feature = "postgres")]
pub fn on_constraint(constraint_name: &str) -> OnConstraint {
    OnConstraint {
        constraint_name: constraint_name,
    }
}

#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct OnConstraint<'a> {
    constraint_name: &'a str,
}

pub trait OnConflictTarget<Table> {}

#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct NoConflictTarget;

impl<DB> QueryFragment<DB> for NoConflictTarget
where
    DB: Backend + SupportsOnConflictClause,
{
    fn walk_ast(&self, _: AstPass<DB>) -> QueryResult<()> {
        Ok(())
    }
}

impl<Table> OnConflictTarget<Table> for NoConflictTarget {}

#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct ConflictTarget<T>(pub T);

impl<DB, T> QueryFragment<DB> for ConflictTarget<T>
where
    DB: Backend + SupportsOnConflictClause,
    T: Column,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql(" (");
        out.push_identifier(T::NAME)?;
        out.push_sql(")");
        Ok(())
    }
}

impl<T> OnConflictTarget<T::Table> for ConflictTarget<T>
where
    T: Column,
{
}

impl<DB, ST> QueryFragment<DB> for ConflictTarget<SqlLiteral<ST>>
where
    DB: Backend + SupportsOnConflictClause,
    SqlLiteral<ST>: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql(" ");
        self.0.walk_ast(out.reborrow())?;
        Ok(())
    }
}

impl<Tab, ST> OnConflictTarget<Tab> for ConflictTarget<SqlLiteral<ST>> {}

impl<'a, DB> QueryFragment<DB> for ConflictTarget<OnConstraint<'a>>
where
    DB: Backend + SupportsOnConflictClause,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql(" ON CONSTRAINT ");
        out.push_identifier(self.0.constraint_name)?;
        Ok(())
    }
}

impl<'a, Table> OnConflictTarget<Table> for ConflictTarget<OnConstraint<'a>> {}

macro_rules! on_conflict_tuples {
    ($($col:ident),+) => {
        impl<DB, T, $($col),+> QueryFragment<DB> for ConflictTarget<(T, $($col),+)> where
            DB: Backend + SupportsOnConflictClause,
            T: Column,
            $($col: Column<Table=T::Table>,)+
        {
            fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
                out.push_sql(" (");
                out.push_identifier(T::NAME)?;
                $(
                    out.push_sql(", ");
                    out.push_identifier($col::NAME)?;
                )+
                out.push_sql(")");
                Ok(())
            }
        }

        impl<T, $($col),+> OnConflictTarget<T::Table> for ConflictTarget<(T, $($col),+)> where
            T: Column,
            $($col: Column<Table=T::Table>,)+
        {
        }
    }
}

on_conflict_tuples!(U);
on_conflict_tuples!(U, V);
on_conflict_tuples!(U, V, W);
on_conflict_tuples!(U, V, W, X);
on_conflict_tuples!(U, V, W, X, Y);
on_conflict_tuples!(U, V, W, X, Y, Z);
<|endoftext|>


<commit_before>bitflags! {
    /// Contents of the `%eflags`/`%rflags` register.
    ///
    /// Note that on early x86 systems, this is a 16-bit register (`%flags`),
    /// but we only support the 32-bit `%eflags` and 64-bit `%rflags`, since
    /// SOS is a protected mode/long mode OS only.
    pub flags Flags: usize {
        /// Carry flag
        const CF = 1 << 0
      , /// Parity flag
        const PF = 1 << 2
      , /// Adjust flag
        const AF = 1 << 4
      , /// Zero flag
        const ZF = 1 << 6
      , /// Sign flag
        const SF = 1 << 7
      , /// Trap flag (single step)
        ///
        /// If 1, IT'S A TRAP!
        const TF = 1 << 8
      , /// Interrupt enable flag
        const IF = 1 << 9
      , /// Direction flag
        const DF = 1 << 10
      , /// Overflow flag
        const OF = 1 << 11

      , const IOPL_RING_0 = 0 << 12
      , const IOPL_RING_1 = 1 << 12
      , const IOPL_RING_2 = 2 << 12
      , const IOPL_RING_3 = 3 << 12
      , /// I/0 Privilege Level
        ///
        /// This flag is always one on the 8086 and 186.
        const IOPL = IOPL_RING_0.bits | IOPL_RING_1.bits |
                     IOPL_RING_2.bits | IOPL_RING_3.bits

      , /// Nested task flag
        ///
        /// Always 1 on 8086 and 186s.
        const NT = 1 << 14

      , /// Should always be 1
        const RESERVED = 1 << 15

      , /// Resume flag
        ///
        /// Present on 386 and later.
        const RF = 1 << 16
      , /// Virtual 8086 Mode flag
        ///
        /// Of course, this is only present on 386 and later.
        const VM = 1 << 17
      , /// Alignment Check
        ///
        /// Present on 486SX and later.
        const AC = 1 << 18
      , /// Virtual Interrupt flag
        ///
        /// Present on Pentium and later.
        const VIF = 1 << 19
      , /// Virtual Interrupt Pending
        ///
        /// Present on Pentium and later.
        const VIP = 1 << 20
      , /// Able to use `CPUID` instruction.
        ///
        /// Present on Pentium and later.
        const ID = 1 << 21
    }
}

/// Read the current value from `$eflags`.
#[cfg(arch = "x86")]
pub fn read() -> Flags {
    let result: usize;
    unsafe {
        asm!(   "mov $0, eflags"
            :   "=r"(result)
            ::: "intel" );
    }
    Flags { bits: result }
}

/// Read the current value from `$rflags`.
#[cfg(arch = "x86_64")]
pub fn read() -> Flags {
    let result: usize;
    unsafe {
        asm!(   "mov $0, rflags"
            :   "=r"(result)
            ::: "intel" );
    }
    Flags { bits: result }
}
<commit_msg>[x86_all] fix LLVM error in code for accessing %rflags<commit_after>use core::mem;

bitflags! {
    /// Contents of the `%eflags`/`%rflags` register.
    ///
    /// Note that on early x86 systems, this is a 16-bit register (`%flags`),
    /// but we only support the 32-bit `%eflags` and 64-bit `%rflags`, since
    /// SOS is a protected mode/long mode OS only.
    pub flags Flags: usize {
        /// Carry flag
        const CF = 1 << 0
      , /// Parity flag
        const PF = 1 << 2
      , /// Adjust flag
        const AF = 1 << 4
      , /// Zero flag
        const ZF = 1 << 6
      , /// Sign flag
        const SF = 1 << 7
      , /// Trap flag (single step)
        ///
        /// If 1, IT'S A TRAP!
        const TF = 1 << 8
      , /// Interrupt enable flag
        const IF = 1 << 9
      , /// Direction flag
        const DF = 1 << 10
      , /// Overflow flag
        const OF = 1 << 11

      , const IOPL_RING_0 = 0 << 12
      , const IOPL_RING_1 = 1 << 12
      , const IOPL_RING_2 = 2 << 12
      , const IOPL_RING_3 = 3 << 12
      , /// I/0 Privilege Level
        ///
        /// This flag is always one on the 8086 and 186.
        const IOPL = IOPL_RING_0.bits | IOPL_RING_1.bits |
                     IOPL_RING_2.bits | IOPL_RING_3.bits

      , /// Nested task flag
        ///
        /// Always 1 on 8086 and 186s.
        const NT = 1 << 14

      , /// Should always be 1
        const RESERVED = 1 << 15

      , /// Resume flag
        ///
        /// Present on 386 and later.
        const RF = 1 << 16
      , /// Virtual 8086 Mode flag
        ///
        /// Of course, this is only present on 386 and later.
        const VM = 1 << 17
      , /// Alignment Check
        ///
        /// Present on 486SX and later.
        const AC = 1 << 18
      , /// Virtual Interrupt flag
        ///
        /// Present on Pentium and later.
        const VIF = 1 << 19
      , /// Virtual Interrupt Pending
        ///
        /// Present on Pentium and later.
        const VIP = 1 << 20
      , /// Able to use `CPUID` instruction.
        ///
        /// Present on Pentium and later.
        const ID = 1 << 21
    }
}

/// Read the current value from `$eflags`/`%rflags`.
pub fn read() -> Flags {
    let result: usize;
    unsafe {
        asm!(   "pushf
                 pop $0"
            :   "=r"(result)
            ::: "intel" );
    }
    Flags { bits: result }
}
<|endoftext|>