<commit_before>// Copyright (c) 2016 glium_sdl2 developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! An SDL2 backend for [Glium](https://github.com/tomaka/glium) - a high-level
//! OpenGL wrapper for the Rust language.
//!
//! # Example
//! ```no_run
//! # #[macro_use] extern crate glium;
//! # extern crate glium_sdl2;
//! # extern crate sdl2;
//! # fn main() {
//! use glium_sdl2::DisplayBuild;
//!
//! let sdl_context = sdl2::init().unwrap();
//! let video_subsystem = sdl_context.video().unwrap();
//!
//! let display = video_subsystem.window("My window", 800, 600)
//!     .resizable()
//!     .build_glium()
//!     .unwrap();
//!
//! let mut running = true;
//! let mut event_pump = sdl_context.event_pump().unwrap();
//!
//! while running {
//!     let mut target = display.draw();
//!     // do drawing here...
//!     target.finish().unwrap();
//!
//!     // Event loop: includes all windows
//!
//!     for event in event_pump.poll_iter() {
//!         use sdl2::event::Event;
//!
//!         match event {
//!             Event::Quit { .. } => {
//!                 running = false;
//!             },
//!             _ => ()
//!         }
//!     }
//! }
//! # }
//! ```

use std;
use glium;
use sdl2;

use std::mem;
use std::cell::UnsafeCell;
use std::ops::Deref;
use std::rc::Rc;
use std::os::raw::c_void;

use glium::SwapBuffersError;
use glium::debug;
use glium::backend::{Backend, Context, Facade};
use sdl2::VideoSubsystem;
use sdl2::video::{Window, WindowRef, WindowBuildError};

pub type Display = SDL2Facade;

#[derive(Debug)]
pub enum GliumSdl2Error {
    WindowBuildError(WindowBuildError),
    ContextCreationError(String)
}

impl From<String> for GliumSdl2Error {
    fn from(s : String) -> GliumSdl2Error {
        return GliumSdl2Error::ContextCreationError(s);
    }
}

impl From<WindowBuildError> for GliumSdl2Error {
    fn from(err : WindowBuildError) -> GliumSdl2Error {
        return GliumSdl2Error::WindowBuildError(err);
    }
}

impl std::error::Error for GliumSdl2Error {
    fn description(&self) -> &str {
        return match *self {
            GliumSdl2Error::WindowBuildError(ref err) => err.description(),
            GliumSdl2Error::ContextCreationError(ref s) => s
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            GliumSdl2Error::WindowBuildError(ref err) => err.cause(),
            GliumSdl2Error::ContextCreationError(_) => None
        }
    }
}

impl std::fmt::Display for GliumSdl2Error {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        formatter.write_str(self.to_string().as_str())
    }
}

/// Facade implementation for an SDL2 window.
#[derive(Clone)]
pub struct SDL2Facade {
    // contains everything related to the current context and its state
    context: Rc<Context>,

    backend: Rc<SDL2WindowBackend>,
}

impl Facade for SDL2Facade {
    fn get_context(&self) -> &Rc<Context> { &self.context }
}

impl Deref for SDL2Facade {
    type Target = Context;

    fn deref(&self) -> &Context { &self.context }
}

impl SDL2Facade {
    pub fn window(&self) -> &WindowRef {
        self.backend.window()
    }

    pub fn window_mut(&mut self) -> &mut WindowRef {
        self.backend.window_mut()
    }

    /// Start drawing on the backbuffer.
    ///
    /// This function returns a `Frame`, which can be used to draw on it.
    /// When the `Frame` is destroyed, the buffers are swapped.
    ///
    /// Note that destroying a `Frame` is immediate, even if vsync is enabled.
    pub fn draw(&self) -> glium::Frame {
        glium::Frame::new(self.context.clone(), self.backend.get_framebuffer_dimensions())
    }
}

/// An object that can build a facade object.
///
/// This trait is different from `glium::DisplayBuild` because Rust doesn't allow trait
/// implementations on types from external crates, unless the trait is in the same crate as the impl.
/// To clarify, both `glium::DisplayBuild` and `sdl2::video::WindowBuilder` are in different crates
/// than `glium_sdl2`.
pub trait DisplayBuild {
    /// The object that this `DisplayBuild` builds.
    type Facade: glium::backend::Facade;

    /// The type of error that initialization can return.
    type Err;

    /// Build a context and a facade to draw on it.
    ///
    /// Performs a compatibility check to make sure that all core elements of glium
    /// are supported by the implementation.
    fn build_glium(self) -> Result<Self::Facade, Self::Err> where Self: Sized {
        self.build_glium_debug(Default::default())
    }

    /// Build a context and a facade to draw on it.
    ///
    /// Performs a compatibility check to make sure that all core elements of glium
    /// are supported by the implementation.
    fn build_glium_debug(self, debug::DebugCallbackBehavior) -> Result<Self::Facade, Self::Err>;

    /// Build a context and a facade to draw on it
    ///
    /// This function does the same as `build_glium`, except that the resulting context
    /// will assume that the current OpenGL context will never change.
    unsafe fn build_glium_unchecked(self) -> Result<Self::Facade, Self::Err> where Self: Sized {
        self.build_glium_unchecked_debug(Default::default())
    }

    /// Build a context and a facade to draw on it
    ///
    /// This function does the same as `build_glium`, except that the resulting context
    /// will assume that the current OpenGL context will never change.
    unsafe fn build_glium_unchecked_debug(self, debug::DebugCallbackBehavior)
                                          -> Result<Self::Facade, Self::Err>;

    // TODO
    // Changes the settings of an existing facade.
    // fn rebuild_glium(self, &Self::Facade) -> Result<(), Self::Err>;
}

impl<'a> DisplayBuild for &'a mut sdl2::video::WindowBuilder {
    type Facade = SDL2Facade;
    type Err = glium::GliumCreationError<GliumSdl2Error>;

    fn build_glium_debug(self, debug: debug::DebugCallbackBehavior) -> Result<SDL2Facade, glium::GliumCreationError<GliumSdl2Error>> {
        let backend = Rc::new(try!(SDL2WindowBackend::new(self)));
        let context = try!(unsafe { Context::new(backend.clone(), true, debug) });

        let display = SDL2Facade {
            context: context,
            backend: backend
        };

        Ok(display)
    }

    unsafe fn build_glium_unchecked_debug(self, debug: debug::DebugCallbackBehavior) -> Result<SDL2Facade, glium::GliumCreationError<GliumSdl2Error>> {
        let backend = Rc::new(try!(SDL2WindowBackend::new(self)));
        let context = try!(Context::new(backend.clone(), false, debug));

        let display = SDL2Facade {
            context: context,
            backend: backend
        };

        Ok(display)
    }
}

pub struct SDL2WindowBackend {
    window: UnsafeCell<sdl2::video::Window>,
    context: sdl2::video::GLContext
}

impl SDL2WindowBackend {
    fn subsystem(&self) -> &VideoSubsystem {
        let ptr = self.window.get();
        let window: &Window = unsafe { mem::transmute(ptr) };
        window.subsystem()
    }

    fn window(&self) -> &WindowRef {
        let ptr = self.window.get();
        let window: &Window = unsafe { mem::transmute(ptr) };
        window
    }

    fn window_mut(&self) -> &mut WindowRef {
        let ptr = self.window.get();
        let window: &mut Window = unsafe { mem::transmute(ptr) };
        window
    }

    pub fn new(window_builder: &mut sdl2::video::WindowBuilder) -> Result<SDL2WindowBackend, GliumSdl2Error> {
        let window = try!(window_builder.opengl().build());
        let context = try!(window.gl_create_context());

        Ok(SDL2WindowBackend {
            window: UnsafeCell::new(window),
            context: context
        })
    }
}

unsafe impl Backend for SDL2WindowBackend {
    fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
        self.window().gl_swap_window();

        // AFAIK, SDL or `SDL_GL_SwapWindow` doesn't have any way to detect context loss.
        // TODO: Find out if context loss is an issue in SDL2 (especially for the Android port).

        Ok(())
    }

    unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
        // Assumes the appropriate context for the window has been set before this call.

        self.subsystem().gl_get_proc_address(symbol) as *const c_void
    }

    fn get_framebuffer_dimensions(&self) -> (u32, u32) {
        let (width, height) = self.window().drawable_size();
        (width as u32, height as u32)
    }

    fn is_current(&self) -> bool {
        self.context.is_current()
    }

    unsafe fn make_current(&self) {
        self.window().gl_make_current(&self.context).unwrap()
    }
}<commit_msg>Fix build error<commit_after>// Copyright (c) 2016 glium_sdl2 developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! An SDL2 backend for [Glium](https://github.com/tomaka/glium) - a high-level
//! OpenGL wrapper for the Rust language.

use std;
use glium;
use sdl2;

use std::mem;
use std::cell::UnsafeCell;
use std::ops::Deref;
use std::rc::Rc;
use std::os::raw::c_void;

use glium::SwapBuffersError;
use glium::debug;
use glium::backend::{Backend, Context, Facade};
use sdl2::VideoSubsystem;
use sdl2::video::{Window, WindowRef, WindowBuildError};

pub type Display = SDL2Facade;

#[derive(Debug)]
pub enum GliumSdl2Error {
    WindowBuildError(WindowBuildError),
    ContextCreationError(String)
}

impl From<String> for GliumSdl2Error {
    fn from(s : String) -> GliumSdl2Error {
        return GliumSdl2Error::ContextCreationError(s);
    }
}

impl From<WindowBuildError> for GliumSdl2Error {
    fn from(err : WindowBuildError) -> GliumSdl2Error {
        return GliumSdl2Error::WindowBuildError(err);
    }
}

impl std::error::Error for GliumSdl2Error {
    fn description(&self) -> &str {
        return match *self {
            GliumSdl2Error::WindowBuildError(ref err) => err.description(),
            GliumSdl2Error::ContextCreationError(ref s) => s
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            GliumSdl2Error::WindowBuildError(ref err) => err.cause(),
            GliumSdl2Error::ContextCreationError(_) => None
        }
    }
}

impl std::fmt::Display for GliumSdl2Error {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        formatter.write_str(self.to_string().as_str())
    }
}

/// Facade implementation for an SDL2 window.
#[derive(Clone)]
pub struct SDL2Facade {
    // contains everything related to the current context and its state
    context: Rc<Context>,

    backend: Rc<SDL2WindowBackend>,
}

impl Facade for SDL2Facade {
    fn get_context(&self) -> &Rc<Context> { &self.context }
}

impl Deref for SDL2Facade {
    type Target = Context;

    fn deref(&self) -> &Context { &self.context }
}

impl SDL2Facade {
    pub fn window(&self) -> &WindowRef {
        self.backend.window()
    }

    pub fn window_mut(&mut self) -> &mut WindowRef {
        self.backend.window_mut()
    }

    /// Start drawing on the backbuffer.
    ///
    /// This function returns a `Frame`, which can be used to draw on it.
    /// When the `Frame` is destroyed, the buffers are swapped.
    ///
    /// Note that destroying a `Frame` is immediate, even if vsync is enabled.
    pub fn draw(&self) -> glium::Frame {
        glium::Frame::new(self.context.clone(), self.backend.get_framebuffer_dimensions())
    }
}

/// An object that can build a facade object.
///
/// This trait is different from `glium::DisplayBuild` because Rust doesn't allow trait
/// implementations on types from external crates, unless the trait is in the same crate as the impl.
/// To clarify, both `glium::DisplayBuild` and `sdl2::video::WindowBuilder` are in different crates
/// than `glium_sdl2`.
pub trait DisplayBuild {
    /// The object that this `DisplayBuild` builds.
    type Facade: glium::backend::Facade;

    /// The type of error that initialization can return.
    type Err;

    /// Build a context and a facade to draw on it.
    ///
    /// Performs a compatibility check to make sure that all core elements of glium
    /// are supported by the implementation.
    fn build_glium(self) -> Result<Self::Facade, Self::Err> where Self: Sized {
        self.build_glium_debug(Default::default())
    }

    /// Build a context and a facade to draw on it.
    ///
    /// Performs a compatibility check to make sure that all core elements of glium
    /// are supported by the implementation.
    fn build_glium_debug(self, debug::DebugCallbackBehavior) -> Result<Self::Facade, Self::Err>;

    /// Build a context and a facade to draw on it
    ///
    /// This function does the same as `build_glium`, except that the resulting context
    /// will assume that the current OpenGL context will never change.
    unsafe fn build_glium_unchecked(self) -> Result<Self::Facade, Self::Err> where Self: Sized {
        self.build_glium_unchecked_debug(Default::default())
    }

    /// Build a context and a facade to draw on it
    ///
    /// This function does the same as `build_glium`, except that the resulting context
    /// will assume that the current OpenGL context will never change.
    unsafe fn build_glium_unchecked_debug(self, debug::DebugCallbackBehavior)
                                          -> Result<Self::Facade, Self::Err>;

    // TODO
    // Changes the settings of an existing facade.
    // fn rebuild_glium(self, &Self::Facade) -> Result<(), Self::Err>;
}

impl<'a> DisplayBuild for &'a mut sdl2::video::WindowBuilder {
    type Facade = SDL2Facade;
    type Err = glium::GliumCreationError<GliumSdl2Error>;

    fn build_glium_debug(self, debug: debug::DebugCallbackBehavior) -> Result<SDL2Facade, glium::GliumCreationError<GliumSdl2Error>> {
        let backend = Rc::new(try!(SDL2WindowBackend::new(self)));
        let context = try!(unsafe { Context::new(backend.clone(), true, debug) });

        let display = SDL2Facade {
            context: context,
            backend: backend
        };

        Ok(display)
    }

    unsafe fn build_glium_unchecked_debug(self, debug: debug::DebugCallbackBehavior) -> Result<SDL2Facade, glium::GliumCreationError<GliumSdl2Error>> {
        let backend = Rc::new(try!(SDL2WindowBackend::new(self)));
        let context = try!(Context::new(backend.clone(), false, debug));

        let display = SDL2Facade {
            context: context,
            backend: backend
        };

        Ok(display)
    }
}

pub struct SDL2WindowBackend {
    window: UnsafeCell<sdl2::video::Window>,
    context: sdl2::video::GLContext
}

impl SDL2WindowBackend {
    fn subsystem(&self) -> &VideoSubsystem {
        let ptr = self.window.get();
        let window: &Window = unsafe { mem::transmute(ptr) };
        window.subsystem()
    }

    fn window(&self) -> &WindowRef {
        let ptr = self.window.get();
        let window: &Window = unsafe { mem::transmute(ptr) };
        window
    }

    fn window_mut(&self) -> &mut WindowRef {
        let ptr = self.window.get();
        let window: &mut Window = unsafe { mem::transmute(ptr) };
        window
    }

    pub fn new(window_builder: &mut sdl2::video::WindowBuilder) -> Result<SDL2WindowBackend, GliumSdl2Error> {
        let window = try!(window_builder.opengl().build());
        let context = try!(window.gl_create_context());

        Ok(SDL2WindowBackend {
            window: UnsafeCell::new(window),
            context: context
        })
    }
}

unsafe impl Backend for SDL2WindowBackend {
    fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
        self.window().gl_swap_window();

        // AFAIK, SDL or `SDL_GL_SwapWindow` doesn't have any way to detect context loss.
        // TODO: Find out if context loss is an issue in SDL2 (especially for the Android port).

        Ok(())
    }

    unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
        // Assumes the appropriate context for the window has been set before this call.

        self.subsystem().gl_get_proc_address(symbol) as *const c_void
    }

    fn get_framebuffer_dimensions(&self) -> (u32, u32) {
        let (width, height) = self.window().drawable_size();
        (width as u32, height as u32)
    }

    fn is_current(&self) -> bool {
        self.context.is_current()
    }

    unsafe fn make_current(&self) {
        self.window().gl_make_current(&self.context).unwrap()
    }
}<|endoftext|>


<commit_before>use select::SelectCommand;
use super::drilldown::Drilldown;
use command::{Command, Query};
use command::Command::Select;
use selectable::fragmentable::Fragmentable;
use command_query::CommandQuery;
use queryable::Queryable;
use commandable::Commandable;
use command_line::CommandLine;

pub struct DrilldownBuilder {
    select: SelectCommand,
    drilldown: Drilldown,
}

/// Drilldown builder.
///
/// ## Simple usage
///
/// ```
/// extern crate ruroonga_command as ruroonga;
/// let select = ruroonga::select::SelectCommand::new("Entries".to_string())
///                  .filter("content @ \"fast\"".to_string());
/// let drilldown = ruroonga::selectable::drilldown::Drilldown::new()
///                  .drilldown("tag".to_string());
/// let mut builder =
///     ruroonga::selectable::drilldown_builder::DrilldownBuilder::new(select, drilldown);
/// let _ = builder.build();
/// ```
/// In more practical example, please refer to drilldown_builder_xxx
/// in [examples/drilldown_builder.rs](https://github.com/cosmo0920/ruroonga_command/blob/master/examples/drilldown_builder.rs).
impl DrilldownBuilder {
    pub fn new(select: SelectCommand, drilldown: Drilldown) -> DrilldownBuilder {
        DrilldownBuilder {
            select: select,
            drilldown: drilldown,
        }
    }

    pub fn build(self) -> (Command, Query) {
        let mut query: Query = vec![];
        let (ordered_select, select) = self.select.to_fragment();
        for ordered in ordered_select.iter() {
            query.push(ordered.to_owned());
        }
        for (key, value) in select.iter() {
            query.push((key.to_owned(), value.to_owned()));
        }
        let (_, drilldown) = self.drilldown.to_fragment();
        for (key, value) in drilldown.iter() {
            query.push((key.to_owned(), value.to_owned()));
        }
        (Select, query)
    }
}

impl Queryable for DrilldownBuilder {
    fn to_query(self) -> String {
        let (command, query) = self.build();
        let mut command = CommandQuery::new(command, query);
        command.encode()
    }
}

impl Commandable for DrilldownBuilder {
    fn to_command(self) -> String {
        let (command, query) = self.build();
        let mut command = CommandLine::new(command, query);
        command.encode()
    }
}
<commit_msg>drilldown_builder: fold a lone line<commit_after>use select::SelectCommand;
use super::drilldown::Drilldown;
use command::{Command, Query};
use command::Command::Select;
use selectable::fragmentable::Fragmentable;
use command_query::CommandQuery;
use queryable::Queryable;
use commandable::Commandable;
use command_line::CommandLine;

pub struct DrilldownBuilder {
    select: SelectCommand,
    drilldown: Drilldown,
}

/// Drilldown builder.
///
/// ## Simple usage
///
/// ```
/// extern crate ruroonga_command as ruroonga;
/// let select = ruroonga::select::SelectCommand::new("Entries".to_string())
///                  .filter("content @ \"fast\"".to_string());
/// let drilldown = ruroonga::selectable::drilldown::Drilldown::new()
///                  .drilldown("tag".to_string());
/// let mut builder =
///     ruroonga::selectable::drilldown_builder::DrilldownBuilder::new(select, drilldown);
/// let _ = builder.build();
/// ```
/// In more practical example, please refer to drilldown_builder_xxx
/// in [examples/drilldown_builder.rs]
/// (https://github.com/cosmo0920/ruroonga_command/blob/master/examples/drilldown_builder.rs).
impl DrilldownBuilder {
    pub fn new(select: SelectCommand, drilldown: Drilldown) -> DrilldownBuilder {
        DrilldownBuilder {
            select: select,
            drilldown: drilldown,
        }
    }

    pub fn build(self) -> (Command, Query) {
        let mut query: Query = vec![];
        let (ordered_select, select) = self.select.to_fragment();
        for ordered in ordered_select.iter() {
            query.push(ordered.to_owned());
        }
        for (key, value) in select.iter() {
            query.push((key.to_owned(), value.to_owned()));
        }
        let (_, drilldown) = self.drilldown.to_fragment();
        for (key, value) in drilldown.iter() {
            query.push((key.to_owned(), value.to_owned()));
        }
        (Select, query)
    }
}

impl Queryable for DrilldownBuilder {
    fn to_query(self) -> String {
        let (command, query) = self.build();
        let mut command = CommandQuery::new(command, query);
        command.encode()
    }
}

impl Commandable for DrilldownBuilder {
    fn to_command(self) -> String {
        let (command, query) = self.build();
        let mut command = CommandLine::new(command, query);
        command.encode()
    }
}
<|endoftext|>


<commit_before>use input::Input;
use ncurses;
use ncurses::ll::{attr_t, chtype, mmask_t};
use ncurses::NCURSES_ATTR_SHIFT;

fn NCURSES_BITS(mask: u32, shift: u32) -> u32 {
    mask << (shift + NCURSES_ATTR_SHIFT) as usize
}

pub fn COLOR_PAIR(n: chtype) -> attr_t {
    NCURSES_BITS(n as u32, 0u32) as attr_t
}

pub const COLOR_BLACK: i16 = 0;
pub const COLOR_RED: i16 = 1;
pub const COLOR_GREEN: i16 = 2;
pub const COLOR_YELLOW: i16 = 3;
pub const COLOR_BLUE: i16 = 4;
pub const COLOR_MAGENTA: i16 = 5;
pub const COLOR_CYAN: i16 = 6;
pub const COLOR_WHITE: i16 = 7;

pub const A_ATTRIBUTES: attr_t = (!0u32 << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_BLINK: attr_t = (1u32 << (11u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_BOLD: attr_t = (1u32 << (13u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_CHARTEXT: attr_t = (1u32 << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_COLOR: attr_t = ((((1u32) << 8) - 1u32) << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_DIM: attr_t = (1u32 << (12u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_ITALIC: attr_t = (1u32 << (23 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_NORMAL: attr_t = 0u32 as attr_t;
pub const A_UNDERLINE: attr_t = (1u32 << (9 + NCURSES_ATTR_SHIFT)) as attr_t;

// pub fn A_STANDOUT() -> attr_t
// { NCURSES_BITS(1u32, 8u32) as attr_t }
//
// pub fn A_UNDERLINE() -> attr_t
// { NCURSES_BITS(1u32, 9u32) as attr_t }
//
// pub fn A_REVERSE() -> attr_t
// { NCURSES_BITS(1u32, 10u32) as attr_t }

pub const KEY_RESIZE: i32 = 0632;

pub const KEY_OFFSET: i32 = 0o0400;
pub const KEY_F15: i32 = (KEY_OFFSET + 0x17);
pub const KEY_EVENT: i32 = (KEY_OFFSET + 0o633);

pub const SPECIAL_KEY_CODES: [Input; 108] = [Input::KeyCodeYes,

                                             Input::KeyBreak,
                                             Input::KeyDown,
                                             Input::KeyUp,
                                             Input::KeyLeft,
                                             Input::KeyRight,
                                             Input::KeyHome,
                                             Input::KeyBackspace,

                                             Input::KeyF0,
                                             Input::KeyF1,
                                             Input::KeyF2,
                                             Input::KeyF3,
                                             Input::KeyF4,
                                             Input::KeyF5,
                                             Input::KeyF6,
                                             Input::KeyF7,
                                             Input::KeyF8,
                                             Input::KeyF9,
                                             Input::KeyF10,
                                             Input::KeyF11,
                                             Input::KeyF12,
                                             Input::KeyF13,
                                             Input::KeyF14,
                                             Input::KeyF15,
                                             // ncurses reserves space for 64 function keys, but we've
                                             // only implemented 15. This has to be taken into account
                                             // when converting the integer into an index of this array
                                             Input::KeyDL,
                                             Input::KeyIL,
                                             Input::KeyDC,
                                             Input::KeyIC,
                                             Input::KeyEIC,
                                             Input::KeyClear,
                                             Input::KeyEOS,
                                             Input::KeyEOL,
                                             Input::KeySF,
                                             Input::KeySR,
                                             Input::KeyNPage,
                                             Input::KeyPPage,
                                             Input::KeySTab,
                                             Input::KeyCTab,
                                             Input::KeyCATab,
                                             Input::KeyEnter,
                                             Input::KeySReset,
                                             Input::KeyReset,
                                             Input::KeyPrint,
                                             Input::KeyLL,
                                             Input::KeyA1,
                                             Input::KeyA3,
                                             Input::KeyB2,
                                             Input::KeyC1,
                                             Input::KeyC3,
                                             Input::KeyBTab,
                                             Input::KeyBeg,
                                             Input::KeyCancel,
                                             Input::KeyClose,
                                             Input::KeyCommand,
                                             Input::KeyCopy,
                                             Input::KeyCreate,
                                             Input::KeyEnd,
                                             Input::KeyExit,
                                             Input::KeyFind,
                                             Input::KeyHelp,
                                             Input::KeyMark,
                                             Input::KeyMessage,
                                             Input::KeyMove,
                                             Input::KeyNext,
                                             Input::KeyOpen,
                                             Input::KeyOptions,
                                             Input::KeyPrevious,
                                             Input::KeyRedo,
                                             Input::KeyReference,
                                             Input::KeyRefresh,
                                             Input::KeyReplace,
                                             Input::KeyRestart,
                                             Input::KeyResume,
                                             Input::KeySave,
                                             Input::KeySBeg,
                                             Input::KeySCancel,
                                             Input::KeySCommand,
                                             Input::KeySCopy,
                                             Input::KeySCreate,
                                             Input::KeySDC,
                                             Input::KeySDL,
                                             Input::KeySelect,
                                             Input::KeySEnd,
                                             Input::KeySEOL,
                                             Input::KeySExit,
                                             Input::KeySFind,
                                             Input::KeySHelp,
                                             Input::KeySHome,
                                             Input::KeySIC,

                                             Input::KeySLeft,
                                             Input::KeySMessage,
                                             Input::KeySMove,
                                             Input::KeySNext,
                                             Input::KeySOptions,
                                             Input::KeySPrevious,
                                             Input::KeySPrint,
                                             Input::KeySRedo,
                                             Input::KeySReplace,
                                             Input::KeySRight,
                                             Input::KeySResume,
                                             Input::KeySSave,
                                             Input::KeySSuspend,
                                             Input::KeySUndo,
                                             Input::KeySuspend,
                                             Input::KeyUndo,
                                             Input::KeyMouse,
                                             Input::KeyResize,
                                             Input::KeyEvent];

pub const ALL_MOUSE_EVENTS: mmask_t = ncurses::ALL_MOUSE_EVENTS as mmask_t;
<commit_msg>Added A_LEFTLINE, A_OVERLINE and A_RIGHTLINE, even though they aren't supported.<commit_after>use input::Input;
use ncurses;
use ncurses::ll::{attr_t, chtype, mmask_t};
use ncurses::NCURSES_ATTR_SHIFT;

fn NCURSES_BITS(mask: u32, shift: u32) -> u32 {
    mask << (shift + NCURSES_ATTR_SHIFT) as usize
}

pub fn COLOR_PAIR(n: chtype) -> attr_t {
    NCURSES_BITS(n as u32, 0u32) as attr_t
}

pub const COLOR_BLACK: i16 = 0;
pub const COLOR_RED: i16 = 1;
pub const COLOR_GREEN: i16 = 2;
pub const COLOR_YELLOW: i16 = 3;
pub const COLOR_BLUE: i16 = 4;
pub const COLOR_MAGENTA: i16 = 5;
pub const COLOR_CYAN: i16 = 6;
pub const COLOR_WHITE: i16 = 7;

pub const A_ATTRIBUTES: attr_t = (!0u32 << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_BLINK: attr_t = (1u32 << (11u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_BOLD: attr_t = (1u32 << (13u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_CHARTEXT: attr_t = (1u32 << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_COLOR: attr_t = ((((1u32) << 8) - 1u32) << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_DIM: attr_t = (1u32 << (12u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_ITALIC: attr_t = (1u32 << (23 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_LEFTLINE: attr_t = 0; // Not supported on ncurses
pub const A_NORMAL: attr_t = 0u32 as attr_t;
pub const A_OVERLINE: attr_t = 0; // Not supported on ncurses
pub const A_RIGHTLINE: attr_t = 0; // Not supported on ncurses
pub const A_UNDERLINE: attr_t = (1u32 << (9 + NCURSES_ATTR_SHIFT)) as attr_t;

// pub fn A_STANDOUT() -> attr_t
// { NCURSES_BITS(1u32, 8u32) as attr_t }
//
// pub fn A_REVERSE() -> attr_t
// { NCURSES_BITS(1u32, 10u32) as attr_t }

pub const KEY_RESIZE: i32 = 0632;

pub const KEY_OFFSET: i32 = 0o0400;
pub const KEY_F15: i32 = (KEY_OFFSET + 0x17);
pub const KEY_EVENT: i32 = (KEY_OFFSET + 0o633);

pub const SPECIAL_KEY_CODES: [Input; 108] = [Input::KeyCodeYes,

                                             Input::KeyBreak,
                                             Input::KeyDown,
                                             Input::KeyUp,
                                             Input::KeyLeft,
                                             Input::KeyRight,
                                             Input::KeyHome,
                                             Input::KeyBackspace,

                                             Input::KeyF0,
                                             Input::KeyF1,
                                             Input::KeyF2,
                                             Input::KeyF3,
                                             Input::KeyF4,
                                             Input::KeyF5,
                                             Input::KeyF6,
                                             Input::KeyF7,
                                             Input::KeyF8,
                                             Input::KeyF9,
                                             Input::KeyF10,
                                             Input::KeyF11,
                                             Input::KeyF12,
                                             Input::KeyF13,
                                             Input::KeyF14,
                                             Input::KeyF15,
                                             // ncurses reserves space for 64 function keys, but we've
                                             // only implemented 15. This has to be taken into account
                                             // when converting the integer into an index of this array
                                             Input::KeyDL,
                                             Input::KeyIL,
                                             Input::KeyDC,
                                             Input::KeyIC,
                                             Input::KeyEIC,
                                             Input::KeyClear,
                                             Input::KeyEOS,
                                             Input::KeyEOL,
                                             Input::KeySF,
                                             Input::KeySR,
                                             Input::KeyNPage,
                                             Input::KeyPPage,
                                             Input::KeySTab,
                                             Input::KeyCTab,
                                             Input::KeyCATab,
                                             Input::KeyEnter,
                                             Input::KeySReset,
                                             Input::KeyReset,
                                             Input::KeyPrint,
                                             Input::KeyLL,
                                             Input::KeyA1,
                                             Input::KeyA3,
                                             Input::KeyB2,
                                             Input::KeyC1,
                                             Input::KeyC3,
                                             Input::KeyBTab,
                                             Input::KeyBeg,
                                             Input::KeyCancel,
                                             Input::KeyClose,
                                             Input::KeyCommand,
                                             Input::KeyCopy,
                                             Input::KeyCreate,
                                             Input::KeyEnd,
                                             Input::KeyExit,
                                             Input::KeyFind,
                                             Input::KeyHelp,
                                             Input::KeyMark,
                                             Input::KeyMessage,
                                             Input::KeyMove,
                                             Input::KeyNext,
                                             Input::KeyOpen,
                                             Input::KeyOptions,
                                             Input::KeyPrevious,
                                             Input::KeyRedo,
                                             Input::KeyReference,
                                             Input::KeyRefresh,
                                             Input::KeyReplace,
                                             Input::KeyRestart,
                                             Input::KeyResume,
                                             Input::KeySave,
                                             Input::KeySBeg,
                                             Input::KeySCancel,
                                             Input::KeySCommand,
                                             Input::KeySCopy,
                                             Input::KeySCreate,
                                             Input::KeySDC,
                                             Input::KeySDL,
                                             Input::KeySelect,
                                             Input::KeySEnd,
                                             Input::KeySEOL,
                                             Input::KeySExit,
                                             Input::KeySFind,
                                             Input::KeySHelp,
                                             Input::KeySHome,
                                             Input::KeySIC,

                                             Input::KeySLeft,
                                             Input::KeySMessage,
                                             Input::KeySMove,
                                             Input::KeySNext,
                                             Input::KeySOptions,
                                             Input::KeySPrevious,
                                             Input::KeySPrint,
                                             Input::KeySRedo,
                                             Input::KeySReplace,
                                             Input::KeySRight,
                                             Input::KeySResume,
                                             Input::KeySSave,
                                             Input::KeySSuspend,
                                             Input::KeySUndo,
                                             Input::KeySuspend,
                                             Input::KeyUndo,
                                             Input::KeyMouse,
                                             Input::KeyResize,
                                             Input::KeyEvent];

pub const ALL_MOUSE_EVENTS: mmask_t = ncurses::ALL_MOUSE_EVENTS as mmask_t;
<|endoftext|>


<commit_before>#![allow(should_implement_trait)]

use std::cmp::max;
use std::io::Read;
use common::VInt;
use common::BinarySerializable;
use super::TermDictionaryImpl;
use termdict::{TermStreamerBuilder, TermStreamer};

pub(crate) fn stream_before<'a, V>(term_dictionary: &'a TermDictionaryImpl<V>,
                                   target_key: &[u8])
                                   -> TermStreamerImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    let (prev_key, offset) = term_dictionary.strictly_previous_key(target_key.as_ref());
    let offset: usize = offset as usize;
    TermStreamerImpl {
        cursor: &term_dictionary.stream_data()[offset..],
        current_key: Vec::from(prev_key),
        current_value: V::default(),
    }
}

/// See [`TermStreamerBuilder`](./trait.TermStreamerBuilder.html)
pub struct TermStreamerBuilderImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    term_dictionary: &'a TermDictionaryImpl<V>,
    origin: usize,
    offset_from: usize,
    offset_to: usize,
    current_key: Vec<u8>,
}

impl<'a, V> TermStreamerBuilder<V> for TermStreamerBuilderImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    type Streamer = TermStreamerImpl<'a, V>;

    /// Limit the range to terms greater or equal to the bound
    fn ge<T: AsRef<[u8]>>(mut self, bound: T) -> Self {
        let target_key = bound.as_ref();
        let streamer = stream_before(self.term_dictionary, target_key.as_ref());
        let smaller_than = |k: &[u8]| k.lt(target_key);
        let (offset_before, current_key) = get_offset(smaller_than, streamer);
        self.current_key = current_key;
        self.offset_from = offset_before - self.origin;
        self
    }

    /// Limit the range to terms strictly greater than the bound
    fn gt<T: AsRef<[u8]>>(mut self, bound: T) -> Self {
        let target_key = bound.as_ref();
        let streamer = stream_before(self.term_dictionary, target_key.as_ref());
        let smaller_than = |k: &[u8]| k.le(target_key);
        let (offset_before, current_key) = get_offset(smaller_than, streamer);
        self.current_key = current_key;
        self.offset_from = offset_before - self.origin;
        self
    }

    /// Limit the range to terms lesser or equal to the bound
    fn lt<T: AsRef<[u8]>>(mut self, bound: T) -> Self {
        let target_key = bound.as_ref();
        let streamer = stream_before(self.term_dictionary, target_key.as_ref());
        let smaller_than = |k: &[u8]| k.lt(target_key);
        let (offset_before, _) = get_offset(smaller_than, streamer);
        self.offset_to = offset_before - self.origin;
        self
    }

    /// Limit the range to terms lesser or equal to the bound
    fn le<T: AsRef<[u8]>>(mut self, bound: T) -> Self {
        let target_key = bound.as_ref();
        let streamer = stream_before(self.term_dictionary, target_key.as_ref());
        let smaller_than = |k: &[u8]| k.le(target_key);
        let (offset_before, _) = get_offset(smaller_than, streamer);
        self.offset_to = offset_before - self.origin;
        self
    }

    /// Build the streamer.
    fn into_stream(self) -> Self::Streamer {
        let data: &[u8] = self.term_dictionary.stream_data();
        let start = self.offset_from;
        let stop = max(self.offset_to, start);
        TermStreamerImpl {
            cursor: &data[start..stop],
            current_key: self.current_key,
            current_value: V::default(),
        }
    }
}

/// Returns offset information for the first
/// key in the stream matching a given predicate.
///
/// returns (start offset, the data required to load the value)
fn get_offset<'a, V, P: Fn(&[u8]) -> bool>(predicate: P,
                                           mut streamer: TermStreamerImpl<V>)
                                           -> (usize, Vec<u8>)
    where V: 'a + BinarySerializable + Default
{
    let mut prev: &[u8] = streamer.cursor;

    let mut prev_data: Vec<u8> = streamer.current_key.clone();

    while let Some((iter_key, _)) = streamer.next() {
        if !predicate(iter_key.as_ref()) {
            return (prev.as_ptr() as usize, prev_data);
        }
        prev = streamer.cursor;
        prev_data.clear();
        prev_data.extend_from_slice(iter_key.as_ref());
    }
    (prev.as_ptr() as usize, prev_data)
}

impl<'a, V> TermStreamerBuilderImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    pub(crate) fn new(term_dictionary: &'a TermDictionaryImpl<V>) -> Self {
        let data = term_dictionary.stream_data();
        let origin = data.as_ptr() as usize;
        TermStreamerBuilderImpl {
            term_dictionary: term_dictionary,
            origin: origin,
            offset_from: 0,
            offset_to: data.len(),
            current_key: vec![],
        }
    }
}

/// See [`TermStreamer`](./trait.TermStreamer.html)
pub struct TermStreamerImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    cursor: &'a [u8],
    current_key: Vec<u8>,
    current_value: V,
}

impl<'a, V: BinarySerializable> TermStreamerImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    pub(crate) fn extract_value(self) -> V {
        self.current_value
    }
}

impl<'a, V> TermStreamer<V> for TermStreamerImpl<'a, V>
    where V: BinarySerializable + Default
{
    fn advance(&mut self) -> bool {
        if self.cursor.is_empty() {
            return false;
        }
        let common_length: usize = VInt::deserialize(&mut self.cursor).unwrap().0 as usize;
        let new_length: usize = common_length +
                                VInt::deserialize(&mut self.cursor).unwrap().0 as usize;
        self.current_key.reserve(new_length);
        unsafe {
            self.current_key.set_len(new_length);
        }
        self.cursor
            .read_exact(&mut self.current_key[common_length..new_length])
            .unwrap();
        self.current_value = V::deserialize(&mut self.cursor).unwrap();
        true
    }

    fn key(&self) -> &[u8] {
        &self.current_key
    }

    fn value(&self) -> &V {
        &self.current_value
    }
}
<commit_msg>Optimized streamer<commit_after>#![allow(should_implement_trait)]

use std::cmp::max;
use common::BinarySerializable;
use super::TermDictionaryImpl;
use termdict::{TermStreamerBuilder, TermStreamer};
use std::io::Read;

pub(crate) fn stream_before<'a, V>(term_dictionary: &'a TermDictionaryImpl<V>,
                                   target_key: &[u8])
                                   -> TermStreamerImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    let (prev_key, offset) = term_dictionary.strictly_previous_key(target_key.as_ref());
    let offset: usize = offset as usize;
    TermStreamerImpl {
        cursor: &term_dictionary.stream_data()[offset..],
        current_key: Vec::from(prev_key),
        current_value: V::default(),
    }
}

/// See [`TermStreamerBuilder`](./trait.TermStreamerBuilder.html)
pub struct TermStreamerBuilderImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    term_dictionary: &'a TermDictionaryImpl<V>,
    origin: usize,
    offset_from: usize,
    offset_to: usize,
    current_key: Vec<u8>,
}

impl<'a, V> TermStreamerBuilder<V> for TermStreamerBuilderImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    type Streamer = TermStreamerImpl<'a, V>;

    /// Limit the range to terms greater or equal to the bound
    fn ge<T: AsRef<[u8]>>(mut self, bound: T) -> Self {
        let target_key = bound.as_ref();
        let streamer = stream_before(self.term_dictionary, target_key.as_ref());
        let smaller_than = |k: &[u8]| k.lt(target_key);
        let (offset_before, current_key) = get_offset(smaller_than, streamer);
        self.current_key = current_key;
        self.offset_from = offset_before - self.origin;
        self
    }

    /// Limit the range to terms strictly greater than the bound
    fn gt<T: AsRef<[u8]>>(mut self, bound: T) -> Self {
        let target_key = bound.as_ref();
        let streamer = stream_before(self.term_dictionary, target_key.as_ref());
        let smaller_than = |k: &[u8]| k.le(target_key);
        let (offset_before, current_key) = get_offset(smaller_than, streamer);
        self.current_key = current_key;
        self.offset_from = offset_before - self.origin;
        self
    }

    /// Limit the range to terms lesser or equal to the bound
    fn lt<T: AsRef<[u8]>>(mut self, bound: T) -> Self {
        let target_key = bound.as_ref();
        let streamer = stream_before(self.term_dictionary, target_key.as_ref());
        let smaller_than = |k: &[u8]| k.lt(target_key);
        let (offset_before, _) = get_offset(smaller_than, streamer);
        self.offset_to = offset_before - self.origin;
        self
    }

    /// Limit the range to terms lesser or equal to the bound
    fn le<T: AsRef<[u8]>>(mut self, bound: T) -> Self {
        let target_key = bound.as_ref();
        let streamer = stream_before(self.term_dictionary, target_key.as_ref());
        let smaller_than = |k: &[u8]| k.le(target_key);
        let (offset_before, _) = get_offset(smaller_than, streamer);
        self.offset_to = offset_before - self.origin;
        self
    }

    /// Build the streamer.
    fn into_stream(self) -> Self::Streamer {
        let data: &[u8] = self.term_dictionary.stream_data();
        let start = self.offset_from;
        let stop = max(self.offset_to, start);
        TermStreamerImpl {
            cursor: &data[start..stop],
            current_key: self.current_key,
            current_value: V::default(),
        }
    }
}

/// Returns offset information for the first
/// key in the stream matching a given predicate.
///
/// returns (start offset, the data required to load the value)
fn get_offset<'a, V, P: Fn(&[u8]) -> bool>(predicate: P,
                                           mut streamer: TermStreamerImpl<V>)
                                           -> (usize, Vec<u8>)
    where V: 'a + BinarySerializable + Default
{
    let mut prev: &[u8] = streamer.cursor;

    let mut prev_data: Vec<u8> = streamer.current_key.clone();

    while let Some((iter_key, _)) = streamer.next() {
        if !predicate(iter_key.as_ref()) {
            return (prev.as_ptr() as usize, prev_data);
        }
        prev = streamer.cursor;
        prev_data.clear();
        prev_data.extend_from_slice(iter_key.as_ref());
    }
    (prev.as_ptr() as usize, prev_data)
}

impl<'a, V> TermStreamerBuilderImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    pub(crate) fn new(term_dictionary: &'a TermDictionaryImpl<V>) -> Self {
        let data = term_dictionary.stream_data();
        let origin = data.as_ptr() as usize;
        TermStreamerBuilderImpl {
            term_dictionary: term_dictionary,
            origin: origin,
            offset_from: 0,
            offset_to: data.len(),
            current_key: vec![],
        }
    }
}

/// See [`TermStreamer`](./trait.TermStreamer.html)
pub struct TermStreamerImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    cursor: &'a [u8],
    current_key: Vec<u8>,
    current_value: V,
}

impl<'a, V: BinarySerializable> TermStreamerImpl<'a, V>
    where V: 'a + BinarySerializable + Default
{
    pub(crate) fn extract_value(self) -> V {
        self.current_value
    }
}

fn deserialize_vint(data: &mut &[u8]) -> u64 {
    let mut res = 0;
    let mut shift = 0;
    for i in 0.. {
        let b = data[i];
        res += ((b % 128u8) as u64) << shift;
        if b & 128u8 != 0u8 {
            *data = &data[(i + 1)..];
            break;
        }
        shift += 7;
    }
    res
}

impl<'a, V> TermStreamer<V> for TermStreamerImpl<'a, V>
    where V: BinarySerializable + Default
{
    fn advance(&mut self) -> bool {
        if self.cursor.is_empty() {
            return false;
        }
        let common_length: usize = deserialize_vint(&mut self.cursor) as usize;
        self.current_key.truncate(common_length);
        let added_length: usize = deserialize_vint(&mut self.cursor) as usize;
        self.current_key
            .extend_from_slice(&self.cursor[..added_length]);
        self.cursor = &self.cursor[added_length..];
        self.current_value =
            V::deserialize(&mut self.cursor)
                .expect("Term dictionary corrupted. Failed to deserialize a value");
        true
    }

    fn key(&self) -> &[u8] {
        &self.current_key
    }

    fn value(&self) -> &V {
        &self.current_value
    }
}
<|endoftext|>


<commit_before>//! Completion for associated items in a trait implementation.
//!
//! This module adds the completion items related to implementing associated
//! items within a `impl Trait for Struct` block. The current context node
//! must be within either a `FN_DEF`, `TYPE_ALIAS_DEF`, or `CONST_DEF` node
//! and an direct child of an `IMPL_DEF`.
//!
//! # Examples
//!
//! Considering the following trait `impl`:
//!
//! ```ignore
//! trait SomeTrait {
//!     fn foo();
//! }
//!
//! impl SomeTrait for () {
//!     fn f<|>
//! }
//! ```
//!
//! may result in the completion of the following method:
//!
//! ```ignore
//! # trait SomeTrait {
//! #    fn foo();
//! # }
//!
//! impl SomeTrait for () {
//!     fn foo() {}<|>
//! }
//! ```

use hir::{self, Docs, HasSource};
use ra_assists::utils::get_missing_impl_items;
use ra_syntax::{
    ast::{self, edit},
    AstNode, SyntaxKind, SyntaxNode, TextRange,
};
use ra_text_edit::TextEdit;

use crate::{
    completion::{
        CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
    },
    display::FunctionSignature,
};

pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
    let mut tokens = ctx.token.ancestors();
    let completion_match = tokens
        .find(|p| match p.kind() {
            SyntaxKind::FN_DEF
            | SyntaxKind::TYPE_ALIAS_DEF
            | SyntaxKind::CONST_DEF
            | SyntaxKind::NAME_REF
            | SyntaxKind::BLOCK_EXPR => true,
            _ => false,
        })
        .and_then(|trigger| {
            for p in tokens {
                match p.kind() {
                    // No nested completions
                    SyntaxKind::FN_DEF | SyntaxKind::BLOCK => return None,
                    SyntaxKind::IMPL_DEF => return ast::ImplDef::cast(p).map(|p| (trigger, p)),
                    _ => {}
                }
            }
            None
        });

    if let Some((trigger, impl_def)) = completion_match {
        match trigger.kind() {
            SyntaxKind::NAME_REF => {
                get_missing_impl_items(&ctx.sema, &impl_def).iter().for_each(|item| match item {
                    hir::AssocItem::Function(fn_item) => {
                        add_function_impl(&trigger, acc, ctx, &fn_item)
                    }
                    hir::AssocItem::TypeAlias(type_item) => {
                        add_type_alias_impl(&trigger, acc, ctx, &type_item)
                    }
                    hir::AssocItem::Const(const_item) => {
                        add_const_impl(&trigger, acc, ctx, &const_item)
                    }
                })
            }

            SyntaxKind::FN_DEF => {
                for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map(
                    |item| match item {
                        hir::AssocItem::Function(fn_item) => Some(fn_item),
                        _ => None,
                    },
                ) {
                    add_function_impl(&trigger, acc, ctx, &missing_fn);
                }
            }

            SyntaxKind::TYPE_ALIAS_DEF => {
                for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map(
                    |item| match item {
                        hir::AssocItem::TypeAlias(type_item) => Some(type_item),
                        _ => None,
                    },
                ) {
                    add_type_alias_impl(&trigger, acc, ctx, &missing_fn);
                }
            }

            SyntaxKind::CONST_DEF => {
                for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map(
                    |item| match item {
                        hir::AssocItem::Const(const_item) => Some(const_item),
                        _ => None,
                    },
                ) {
                    add_const_impl(&trigger, acc, ctx, &missing_fn);
                }
            }

            _ => {}
        }
    }
}

fn add_function_impl(
    fn_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    func: &hir::Function,
) {
    let display = FunctionSignature::from_hir(ctx.db, *func);

    let fn_name = func.name(ctx.db).to_string();

    let label = if !func.params(ctx.db).is_empty() {
        format!("fn {}(..)", fn_name)
    } else {
        format!("fn {}()", fn_name)
    };

    let builder = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label)
        .lookup_by(fn_name)
        .set_documentation(func.docs(ctx.db));

    let completion_kind = if func.has_self_param(ctx.db) {
        CompletionItemKind::Method
    } else {
        CompletionItemKind::Function
    };

    let snippet = format!("{} {{}}", display);

    let range = TextRange::from_to(fn_def_node.text_range().start(), ctx.source_range().end());

    builder.text_edit(TextEdit::replace(range, snippet)).kind(completion_kind).add_to(acc);
}

fn add_type_alias_impl(
    type_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    type_alias: &hir::TypeAlias,
) {
    let alias_name = type_alias.name(ctx.db).to_string();

    let snippet = format!("type {} = ", alias_name);

    let range = TextRange::from_to(type_def_node.text_range().start(), ctx.source_range().end());

    CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
        .text_edit(TextEdit::replace(range, snippet))
        .lookup_by(alias_name)
        .kind(CompletionItemKind::TypeAlias)
        .set_documentation(type_alias.docs(ctx.db))
        .add_to(acc);
}

fn add_const_impl(
    const_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    const_: &hir::Const,
) {
    let const_name = const_.name(ctx.db).map(|n| n.to_string());

    if let Some(const_name) = const_name {
        let snippet = make_const_compl_syntax(&const_.source(ctx.db).value);

        let range =
            TextRange::from_to(const_def_node.text_range().start(), ctx.source_range().end());

        CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
            .text_edit(TextEdit::replace(range, snippet))
            .lookup_by(const_name)
            .kind(CompletionItemKind::Const)
            .set_documentation(const_.docs(ctx.db))
            .add_to(acc);
    }
}

fn make_const_compl_syntax(const_: &ast::ConstDef) -> String {
    let const_ = edit::strip_attrs_and_docs(const_);

    let const_start = const_.syntax().text_range().start();
    let const_end = const_.syntax().text_range().end();

    let start =
        const_.syntax().first_child_or_token().map_or(const_start, |f| f.text_range().start());

    let end = const_
        .syntax()
        .children_with_tokens()
        .find(|s| s.kind() == SyntaxKind::SEMI || s.kind() == SyntaxKind::EQ)
        .map_or(const_end, |f| f.text_range().start());

    let len = end - start;
    let range = TextRange::from_to(0.into(), len);

    let syntax = const_.syntax().text().slice(range).to_string();

    format!("{} = ", syntax.trim_end())
}

#[cfg(test)]
mod tests {
    use crate::completion::{do_completion, CompletionItem, CompletionKind};
    use insta::assert_debug_snapshot;

    fn complete(code: &str) -> Vec<CompletionItem> {
        do_completion(code, CompletionKind::Magic)
    }

    #[test]
    fn name_ref_function_type_const() {
        let completions = complete(
            r"
            trait Test {
                type TestType;
                const TEST_CONST: u16;
                fn test();
            }

            struct T1;

            impl Test for T1 {
                t<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "const TEST_CONST: u16 = ",
                source_range: [209; 210),
                delete: [209; 210),
                insert: "const TEST_CONST: u16 = ",
                kind: Const,
                lookup: "TEST_CONST",
            },
            CompletionItem {
                label: "fn test()",
                source_range: [209; 210),
                delete: [209; 210),
                insert: "fn test() {}",
                kind: Function,
                lookup: "test",
            },
            CompletionItem {
                label: "type TestType = ",
                source_range: [209; 210),
                delete: [209; 210),
                insert: "type TestType = ",
                kind: TypeAlias,
                lookup: "TestType",
            },
        ]
        "###);
    }

    #[test]
    fn name_ref_single_function() {
        let completions = complete(
            r"
            trait Test {
                fn test();
            }

            struct T1;

            impl Test for T1 {
                t<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn test()",
                source_range: [139; 140),
                delete: [139; 140),
                insert: "fn test() {}",
                kind: Function,
                lookup: "test",
            },
        ]
        "###);
    }

    #[test]
    fn single_function() {
        let completions = complete(
            r"
            trait Test {
                fn foo();
            }

            struct T1;

            impl Test for T1 {
                fn f<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [141; 142),
                delete: [138; 142),
                insert: "fn foo() {}",
                kind: Function,
                lookup: "foo",
            },
        ]
        "###);
    }

    #[test]
    fn hide_implemented_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo();
                fn foo_bar();
            }

            struct T1;

            impl Test for T1 {
                fn foo() {}

                fn f<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo_bar()",
                source_range: [200; 201),
                delete: [197; 201),
                insert: "fn foo_bar() {}",
                kind: Function,
                lookup: "foo_bar",
            },
        ]
        "###);
    }

    #[test]
    fn completes_only_on_top_level() {
        let completions = complete(
            r"
            trait Test {
                fn foo();

                fn foo_bar();
            }

            struct T1;

            impl Test for T1 {
                fn foo() {
                    <|>
                }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"[]"###);
    }

    #[test]
    fn generic_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo<T>();
            }

            struct T1;

            impl Test for T1 {
                fn f<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [144; 145),
                delete: [141; 145),
                insert: "fn foo<T>() {}",
                kind: Function,
                lookup: "foo",
            },
        ]
        "###);
    }

    #[test]
    fn generic_constrait_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo<T>() where T: Into<String>;
            }

            struct T1;

            impl Test for T1 {
                fn f<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [166; 167),
                delete: [163; 167),
                insert: "fn foo<T>()\nwhere T: Into<String> {}",
                kind: Function,
                lookup: "foo",
            },
        ]
        "###);
    }

    #[test]
    fn associated_type() {
        let completions = complete(
            r"
            trait Test {
                type SomeType;
            }

            impl Test for () {
                type S<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "type SomeType = ",
                source_range: [124; 125),
                delete: [119; 125),
                insert: "type SomeType = ",
                kind: TypeAlias,
                lookup: "SomeType",
            },
        ]
        "###);
    }

    #[test]
    fn associated_const() {
        let completions = complete(
            r"
            trait Test {
                const SOME_CONST: u16;
            }

            impl Test for () {
                const S<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "const SOME_CONST: u16 = ",
                source_range: [133; 134),
                delete: [127; 134),
                insert: "const SOME_CONST: u16 = ",
                kind: Const,
                lookup: "SOME_CONST",
            },
        ]
        "###);
    }

    #[test]
    fn associated_const_with_default() {
        let completions = complete(
            r"
            trait Test {
                const SOME_CONST: u16 = 42;
            }

            impl Test for () {
                const S<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "const SOME_CONST: u16 = ",
                source_range: [138; 139),
                delete: [132; 139),
                insert: "const SOME_CONST: u16 = ",
                kind: Const,
                lookup: "SOME_CONST",
            },
        ]
        "###);
    }
}
<commit_msg>Clean up completion matching.<commit_after>//! Completion for associated items in a trait implementation.
//!
//! This module adds the completion items related to implementing associated
//! items within a `impl Trait for Struct` block. The current context node
//! must be within either a `FN_DEF`, `TYPE_ALIAS_DEF`, or `CONST_DEF` node
//! and an direct child of an `IMPL_DEF`.
//!
//! # Examples
//!
//! Considering the following trait `impl`:
//!
//! ```ignore
//! trait SomeTrait {
//!     fn foo();
//! }
//!
//! impl SomeTrait for () {
//!     fn f<|>
//! }
//! ```
//!
//! may result in the completion of the following method:
//!
//! ```ignore
//! # trait SomeTrait {
//! #    fn foo();
//! # }
//!
//! impl SomeTrait for () {
//!     fn foo() {}<|>
//! }
//! ```

use hir::{self, Docs, HasSource};
use ra_assists::utils::get_missing_impl_items;
use ra_syntax::{
    ast::{self, edit, ImplDef},
    AstNode, SyntaxKind, SyntaxNode, TextRange,
};
use ra_text_edit::TextEdit;

use crate::{
    completion::{
        CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
    },
    display::FunctionSignature,
};

pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
    if let Some((trigger, impl_def)) = completion_match(ctx) {
        match trigger.kind() {
            SyntaxKind::NAME_REF => {
                get_missing_impl_items(&ctx.sema, &impl_def).iter().for_each(|item| match item {
                    hir::AssocItem::Function(fn_item) => {
                        add_function_impl(&trigger, acc, ctx, &fn_item)
                    }
                    hir::AssocItem::TypeAlias(type_item) => {
                        add_type_alias_impl(&trigger, acc, ctx, &type_item)
                    }
                    hir::AssocItem::Const(const_item) => {
                        add_const_impl(&trigger, acc, ctx, &const_item)
                    }
                })
            }

            SyntaxKind::FN_DEF => {
                for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map(
                    |item| match item {
                        hir::AssocItem::Function(fn_item) => Some(fn_item),
                        _ => None,
                    },
                ) {
                    add_function_impl(&trigger, acc, ctx, &missing_fn);
                }
            }

            SyntaxKind::TYPE_ALIAS_DEF => {
                for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map(
                    |item| match item {
                        hir::AssocItem::TypeAlias(type_item) => Some(type_item),
                        _ => None,
                    },
                ) {
                    add_type_alias_impl(&trigger, acc, ctx, &missing_fn);
                }
            }

            SyntaxKind::CONST_DEF => {
                for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map(
                    |item| match item {
                        hir::AssocItem::Const(const_item) => Some(const_item),
                        _ => None,
                    },
                ) {
                    add_const_impl(&trigger, acc, ctx, &missing_fn);
                }
            }

            _ => {}
        }
    }
}

fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, ImplDef)> {
    let (trigger_idx, trigger) =
        ctx.token.ancestors().enumerate().find(|(_idx, p)| match p.kind() {
            SyntaxKind::FN_DEF
            | SyntaxKind::TYPE_ALIAS_DEF
            | SyntaxKind::CONST_DEF
            | SyntaxKind::NAME_REF
            | SyntaxKind::BLOCK_EXPR => true,
            _ => false,
        })?;
    let (impl_def_idx, impl_def) =
        ctx.token.ancestors().enumerate().skip(trigger_idx + 1).find_map(|(idx, p)| {
            match p.kind() {
                SyntaxKind::IMPL_DEF => ast::ImplDef::cast(p).map(|p| (idx, p)),
                _ => None,
            }
        })?;
    let _is_nested = ctx
        .token
        .ancestors()
        .skip(trigger_idx + 1)
        .take(impl_def_idx - trigger_idx - 1)
        .find_map(|p| match p.kind() {
            SyntaxKind::FN_DEF | SyntaxKind::BLOCK => Some(()),
            _ => None,
        })
        .xor(Some(()))?;
    Some((trigger, impl_def))
}

fn add_function_impl(
    fn_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    func: &hir::Function,
) {
    let display = FunctionSignature::from_hir(ctx.db, *func);

    let fn_name = func.name(ctx.db).to_string();

    let label = if !func.params(ctx.db).is_empty() {
        format!("fn {}(..)", fn_name)
    } else {
        format!("fn {}()", fn_name)
    };

    let builder = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label)
        .lookup_by(fn_name)
        .set_documentation(func.docs(ctx.db));

    let completion_kind = if func.has_self_param(ctx.db) {
        CompletionItemKind::Method
    } else {
        CompletionItemKind::Function
    };

    let snippet = format!("{} {{}}", display);

    let range = TextRange::from_to(fn_def_node.text_range().start(), ctx.source_range().end());

    builder.text_edit(TextEdit::replace(range, snippet)).kind(completion_kind).add_to(acc);
}

fn add_type_alias_impl(
    type_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    type_alias: &hir::TypeAlias,
) {
    let alias_name = type_alias.name(ctx.db).to_string();

    let snippet = format!("type {} = ", alias_name);

    let range = TextRange::from_to(type_def_node.text_range().start(), ctx.source_range().end());

    CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
        .text_edit(TextEdit::replace(range, snippet))
        .lookup_by(alias_name)
        .kind(CompletionItemKind::TypeAlias)
        .set_documentation(type_alias.docs(ctx.db))
        .add_to(acc);
}

fn add_const_impl(
    const_def_node: &SyntaxNode,
    acc: &mut Completions,
    ctx: &CompletionContext,
    const_: &hir::Const,
) {
    let const_name = const_.name(ctx.db).map(|n| n.to_string());

    if let Some(const_name) = const_name {
        let snippet = make_const_compl_syntax(&const_.source(ctx.db).value);

        let range =
            TextRange::from_to(const_def_node.text_range().start(), ctx.source_range().end());

        CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
            .text_edit(TextEdit::replace(range, snippet))
            .lookup_by(const_name)
            .kind(CompletionItemKind::Const)
            .set_documentation(const_.docs(ctx.db))
            .add_to(acc);
    }
}

fn make_const_compl_syntax(const_: &ast::ConstDef) -> String {
    let const_ = edit::strip_attrs_and_docs(const_);

    let const_start = const_.syntax().text_range().start();
    let const_end = const_.syntax().text_range().end();

    let start =
        const_.syntax().first_child_or_token().map_or(const_start, |f| f.text_range().start());

    let end = const_
        .syntax()
        .children_with_tokens()
        .find(|s| s.kind() == SyntaxKind::SEMI || s.kind() == SyntaxKind::EQ)
        .map_or(const_end, |f| f.text_range().start());

    let len = end - start;
    let range = TextRange::from_to(0.into(), len);

    let syntax = const_.syntax().text().slice(range).to_string();

    format!("{} = ", syntax.trim_end())
}

#[cfg(test)]
mod tests {
    use crate::completion::{do_completion, CompletionItem, CompletionKind};
    use insta::assert_debug_snapshot;

    fn complete(code: &str) -> Vec<CompletionItem> {
        do_completion(code, CompletionKind::Magic)
    }

    #[test]
    fn name_ref_function_type_const() {
        let completions = complete(
            r"
            trait Test {
                type TestType;
                const TEST_CONST: u16;
                fn test();
            }

            struct T1;

            impl Test for T1 {
                t<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "const TEST_CONST: u16 = ",
                source_range: [209; 210),
                delete: [209; 210),
                insert: "const TEST_CONST: u16 = ",
                kind: Const,
                lookup: "TEST_CONST",
            },
            CompletionItem {
                label: "fn test()",
                source_range: [209; 210),
                delete: [209; 210),
                insert: "fn test() {}",
                kind: Function,
                lookup: "test",
            },
            CompletionItem {
                label: "type TestType = ",
                source_range: [209; 210),
                delete: [209; 210),
                insert: "type TestType = ",
                kind: TypeAlias,
                lookup: "TestType",
            },
        ]
        "###);
    }

    #[test]
    fn no_nested_fn_completions() {
        let completions = complete(
            r"
            trait Test {
                fn test();
                fn test2();
            }

            struct T1;

            impl Test for T1 {
                fn test() {
                    t<|>
                }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"[]"###);
    }

    #[test]
    fn name_ref_single_function() {
        let completions = complete(
            r"
            trait Test {
                fn test();
            }

            struct T1;

            impl Test for T1 {
                t<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn test()",
                source_range: [139; 140),
                delete: [139; 140),
                insert: "fn test() {}",
                kind: Function,
                lookup: "test",
            },
        ]
        "###);
    }

    #[test]
    fn single_function() {
        let completions = complete(
            r"
            trait Test {
                fn foo();
            }

            struct T1;

            impl Test for T1 {
                fn f<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [141; 142),
                delete: [138; 142),
                insert: "fn foo() {}",
                kind: Function,
                lookup: "foo",
            },
        ]
        "###);
    }

    #[test]
    fn hide_implemented_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo();
                fn foo_bar();
            }

            struct T1;

            impl Test for T1 {
                fn foo() {}

                fn f<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo_bar()",
                source_range: [200; 201),
                delete: [197; 201),
                insert: "fn foo_bar() {}",
                kind: Function,
                lookup: "foo_bar",
            },
        ]
        "###);
    }

    #[test]
    fn completes_only_on_top_level() {
        let completions = complete(
            r"
            trait Test {
                fn foo();

                fn foo_bar();
            }

            struct T1;

            impl Test for T1 {
                fn foo() {
                    <|>
                }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"[]"###);
    }

    #[test]
    fn generic_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo<T>();
            }

            struct T1;

            impl Test for T1 {
                fn f<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [144; 145),
                delete: [141; 145),
                insert: "fn foo<T>() {}",
                kind: Function,
                lookup: "foo",
            },
        ]
        "###);
    }

    #[test]
    fn generic_constrait_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo<T>() where T: Into<String>;
            }

            struct T1;

            impl Test for T1 {
                fn f<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [166; 167),
                delete: [163; 167),
                insert: "fn foo<T>()\nwhere T: Into<String> {}",
                kind: Function,
                lookup: "foo",
            },
        ]
        "###);
    }

    #[test]
    fn associated_type() {
        let completions = complete(
            r"
            trait Test {
                type SomeType;
            }

            impl Test for () {
                type S<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "type SomeType = ",
                source_range: [124; 125),
                delete: [119; 125),
                insert: "type SomeType = ",
                kind: TypeAlias,
                lookup: "SomeType",
            },
        ]
        "###);
    }

    #[test]
    fn associated_const() {
        let completions = complete(
            r"
            trait Test {
                const SOME_CONST: u16;
            }

            impl Test for () {
                const S<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "const SOME_CONST: u16 = ",
                source_range: [133; 134),
                delete: [127; 134),
                insert: "const SOME_CONST: u16 = ",
                kind: Const,
                lookup: "SOME_CONST",
            },
        ]
        "###);
    }

    #[test]
    fn associated_const_with_default() {
        let completions = complete(
            r"
            trait Test {
                const SOME_CONST: u16 = 42;
            }

            impl Test for () {
                const S<|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "const SOME_CONST: u16 = ",
                source_range: [138; 139),
                delete: [132; 139),
                insert: "const SOME_CONST: u16 = ",
                kind: Const,
                lookup: "SOME_CONST",
            },
        ]
        "###);
    }
}
<|endoftext|>


<commit_before>//! The `is_{target_arch}_feature_detected!` macro are only available on their
//! architecture. These macros provide a better error messages when the user
//! attempts to call them in a different architecture.

#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_x86_feature_detected {
    ($t: tt) => {
        compile_error!(
            r#"
        is_x86_feature_detected can only be used on x86 and x86_64 targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:

            #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
                if is_x86_feature_detected(...) { ... }
            }
        "#
        )
    };
}

#[cfg(not(target_arch = "arm"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_arm_feature_detected {
    ($t:tt) => {
        compile_error!(
            r#"
        is_arm_feature_detected can only be used on ARM targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:

            #[cfg(target_arch = "arm")] {
                if is_arm_feature_detected(...) { ... }
            }
        "#
        )
    };
}

#[cfg(not(target_arch = "aarch64"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_aarch64_feature_detected {
    ($t: tt) => {
        compile_error!(
            r#"
        is_aarch64_feature_detected can only be used on AArch64 targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:

            #[cfg(target_arch = "aarch64")] {
                if is_aarch64_feature_detected(...) { ... }
            }
        "#
        )
    };
}

#[cfg(not(target_arch = "powerpc"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_powerpc_feature_detected {
    ($t:tt) => {
        compile_error!(
            r#"
is_powerpc_feature_detected can only be used on PowerPC targets.
You can prevent it from being used in other architectures by
guarding it behind a cfg(target_arch) as follows:

    #[cfg(target_arch = "powerpc")] {
        if is_powerpc_feature_detected(...) { ... }
    }
"#
        )
    };
}

#[cfg(not(target_arch = "powerpc64"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_powerpc64_feature_detected {
    ($t:tt) => {
        compile_error!(
            r#"
is_powerpc64_feature_detected can only be used on PowerPC64 targets.
You can prevent it from being used in other architectures by
guarding it behind a cfg(target_arch) as follows:

    #[cfg(target_arch = "powerpc64")] {
        if is_powerpc64_feature_detected(...) { ... }
    }
"#
        )
    };
}

#[cfg(not(target_arch = "mips"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_mips_feature_detected {
    ($t:tt) => {
        compile_error!(
            r#"
        is_mips_feature_detected can only be used on MIPS targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:

            #[cfg(target_arch = "mips")] {
                if is_mips_feature_detected(...) { ... }
            }
        "#
        )
    };
}

#[cfg(not(target_arch = "mips64"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_mips64_feature_detected {
    ($t:tt) => {
        compile_error!(
            r#"
        is_mips64_feature_detected can only be used on MIPS64 targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:

            #[cfg(target_arch = "mips64")] {
                if is_mips64_feature_detected(...) { ... }
            }
        "#
        )
    };
}
<commit_msg>Add missing docs<commit_after>//! The `is_{target_arch}_feature_detected!` macro are only available on their
//! architecture. These macros provide a better error messages when the user
//! attempts to call them in a different architecture.

/// Prevents compilation if `is_x86_feature_detected` is used somewhere
/// else than `x86` and `x86_64` targets.
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_x86_feature_detected {
    ($t: tt) => {
        compile_error!(
            r#"
        is_x86_feature_detected can only be used on x86 and x86_64 targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:

            #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
                if is_x86_feature_detected(...) { ... }
            }
        "#
        )
    };
}

/// Prevents compilation if `is_arm_feature_detected` is used somewhere else
/// than `ARM` targets.
#[cfg(not(target_arch = "arm"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_arm_feature_detected {
    ($t:tt) => {
        compile_error!(
            r#"
        is_arm_feature_detected can only be used on ARM targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:

            #[cfg(target_arch = "arm")] {
                if is_arm_feature_detected(...) { ... }
            }
        "#
        )
    };
}

/// Prevents compilation if `is_aarch64_feature_detected` is used somewhere else
/// than `aarch64` targets.
#[cfg(not(target_arch = "aarch64"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_aarch64_feature_detected {
    ($t: tt) => {
        compile_error!(
            r#"
        is_aarch64_feature_detected can only be used on AArch64 targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:

            #[cfg(target_arch = "aarch64")] {
                if is_aarch64_feature_detected(...) { ... }
            }
        "#
        )
    };
}

/// Prevents compilation if `is_powerpc_feature_detected` is used somewhere else
/// than `PowerPC` targets.
#[cfg(not(target_arch = "powerpc"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_powerpc_feature_detected {
    ($t:tt) => {
        compile_error!(
            r#"
is_powerpc_feature_detected can only be used on PowerPC targets.
You can prevent it from being used in other architectures by
guarding it behind a cfg(target_arch) as follows:

    #[cfg(target_arch = "powerpc")] {
        if is_powerpc_feature_detected(...) { ... }
    }
"#
        )
    };
}

/// Prevents compilation if `is_powerpc64_feature_detected` is used somewhere
/// else than `PowerPC64` targets.
#[cfg(not(target_arch = "powerpc64"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_powerpc64_feature_detected {
    ($t:tt) => {
        compile_error!(
            r#"
is_powerpc64_feature_detected can only be used on PowerPC64 targets.
You can prevent it from being used in other architectures by
guarding it behind a cfg(target_arch) as follows:

    #[cfg(target_arch = "powerpc64")] {
        if is_powerpc64_feature_detected(...) { ... }
    }
"#
        )
    };
}

/// Prevents compilation if `is_mips_feature_detected` is used somewhere else
/// than `MIPS` targets.
#[cfg(not(target_arch = "mips"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_mips_feature_detected {
    ($t:tt) => {
        compile_error!(
            r#"
        is_mips_feature_detected can only be used on MIPS targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:

            #[cfg(target_arch = "mips")] {
                if is_mips_feature_detected(...) { ... }
            }
        "#
        )
    };
}

/// Prevents compilation if `is_mips64_feature_detected` is used somewhere else
/// than `MIPS64` targets.
#[cfg(not(target_arch = "mips64"))]
#[macro_export]
#[unstable(feature = "stdsimd", issue = "27731")]
macro_rules! is_mips64_feature_detected {
    ($t:tt) => {
        compile_error!(
            r#"
        is_mips64_feature_detected can only be used on MIPS64 targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:

            #[cfg(target_arch = "mips64")] {
                if is_mips64_feature_detected(...) { ... }
            }
        "#
        )
    };
}
<|endoftext|>