<commit_before>use std::fs::File;
use std::io::{BufReader, Read};
use std::{str, vec, fmt};
use std::path;
use std::io;

use scopes;
use nameres;
use ast;

#[derive(Debug,Clone,PartialEq)]
pub enum MatchType {
    Struct,
    Module,
    MatchArm,
    Function,
    Crate,
    Let,
    IfLet,
    StructField,
    Impl,
    Enum,
    EnumVariant,
    Type,
    FnArg,
    Trait,
    Const,
    Static
}

impl Copy for MatchType {}

#[derive(Debug,Clone)]
pub enum SearchType {
    ExactMatch,
    StartsWith
}

impl Copy for SearchType {}

#[derive(Debug,Clone)]
pub enum Namespace {
    TypeNamespace,
    ValueNamespace,
    BothNamespaces
}

impl Copy for Namespace {}

#[derive(Debug,Clone)]
pub enum CompletionType {
    CompleteField,
    CompletePath
}

impl Copy for CompletionType {}

#[derive(Clone)]
pub struct Match {
    pub matchstr: String,
    pub filepath: path::PathBuf,
    pub point: usize,
    pub local: bool,
    pub mtype: MatchType,
    pub contextstr: String,
    pub generic_args: Vec<String>,
    pub generic_types: Vec<PathSearch>,  // generic types are evaluated lazily
    pub session: Session
}

impl Match {
    pub fn with_generic_types(&self, generic_types: Vec<PathSearch>) -> Match {
        Match {
            matchstr: self.matchstr.clone(),
            filepath: self.filepath.clone(),
            point: self.point,
            local: self.local,
            mtype: self.mtype,
            contextstr: self.contextstr.clone(),
            generic_args: self.generic_args.clone(),
            generic_types: generic_types,
            session: self.session.clone()
        }
    }
}

impl fmt::Debug for Match {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Match [{:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?} |{}|, {:?}]",
               self.matchstr,
               self.filepath.to_str(),
               self.point,
               self.local,
               self.mtype,
               self.generic_args,
               self.generic_types,
               self.contextstr,
               self.session)
    }
}

#[derive(Clone)]
pub struct Scope {
    pub filepath: path::PathBuf,
    pub point: usize,
    pub session: Session
}

impl Scope {
    pub fn from_match(m: &Match) -> Scope {
        Scope{ filepath: m.filepath.clone(), point: m.point, session: m.session.clone() }
    }
}

impl fmt::Debug for Scope {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Scope [{:?}, {:?}, {:?}]",
               self.filepath.to_str(),
               self.point,
               self.session)
    }
}

// Represents a type. Equivilent to rustc's ast::Ty but can be passed across threads
#[derive(Debug,Clone)]
pub enum Ty {
    TyMatch(Match),
    TyPathSearch(Path, Scope),   // A path + the scope to be able to resolve it
    TyTuple(Vec<Ty>),
    TyUnsupported
}

// The racer implementation of an ast::Path. Difference is that it is Send-able
#[derive(Clone)]
pub struct Path {
    pub global: bool,
    pub segments: Vec<PathSegment>
}

impl Path {
    pub fn generic_types(&self) -> ::std::slice::Iter<Path> {
        self.segments[self.segments.len()-1].types.iter()
    }

    pub fn from_vec(global: bool, v: Vec<&str>) -> Path {
        let segs = v
            .into_iter()
            .map(|x| PathSegment{ name: x.to_owned(), types: Vec::new() })
            .collect::<Vec<_>>();
        Path{ global: global, segments: segs }
    }

    pub fn from_svec(global: bool, v: Vec<String>) -> Path {
        let segs = v
            .into_iter()
            .map(|x| PathSegment{ name: x, types: Vec::new() })
            .collect::<Vec<_>>();
        Path{ global: global, segments: segs }
    }
}

impl fmt::Debug for Path {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "P["));
        let mut first = true;
        for seg in &self.segments {
            if first {
                try!(write!(f, "{}", seg.name));
                first = false;
            } else {
                try!(write!(f, "::{}", seg.name));
            }

            if !seg.types.is_empty() {
                try!(write!(f, "<"));
                let mut tfirst = true;
                for typath in &seg.types {
                    if tfirst {
                        try!(write!(f, "{:?}", typath));
                        tfirst = false;
                    } else {
                        try!(write!(f, ",{:?}", typath))
                    }
                }
                try!(write!(f, ">"));
            }
        }
        write!(f, "]")
    }
}

#[derive(Debug,Clone)]
pub struct PathSegment {
    pub name: String,
    pub types: Vec<Path>
}

#[derive(Clone)]
pub struct PathSearch {
    pub path: Path,
    pub filepath: path::PathBuf,
    pub point: usize,
    pub session: Session
}

impl fmt::Debug for PathSearch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Search [{:?}, {:?}, {:?}, {:?}]",
               self.path,
               self.filepath.to_str(),
               self.point,
               self.session)
    }
}

#[derive(Debug,Clone)]
pub struct Session {
    pub query_path: path::PathBuf,            // the input path of the query
    pub substitute_file: path::PathBuf        // the temporary file
}

impl Session {
    pub fn from_path(query_path: &path::Path, substitute_file: &path::Path) -> Session {
        Session {
            query_path: query_path.to_path_buf(),
            substitute_file: substitute_file.to_path_buf()
        }
    }

    pub fn open_file(&self, path: &path::Path) -> io::Result<File> {
        if path == self.query_path.as_path() {
            File::open(&self.substitute_file)
        } else {
            File::open(path)
        }
    }
}

pub fn load_file(filepath: &path::Path, session: &Session) -> String {
    let mut rawbytes = Vec::new();
    if let Ok(f) = session.open_file(filepath) {
        BufReader::new(f).read_to_end(&mut rawbytes).unwrap();
    } else {
        error!("load_file couldn't open {:?}. Returning empty string",filepath);
        return "".into();
    }

    // skip BOF bytes, if present
    if rawbytes.len() > 2 && rawbytes[0..3] == [0xEF, 0xBB, 0xBF] {
        let mut it = rawbytes.into_iter();
        it.next(); it.next(); it.next();
        String::from_utf8(it.collect::<Vec<_>>()).unwrap()
    } else {
        String::from_utf8(rawbytes).unwrap()
    }
}

pub fn load_file_and_mask_comments(filepath: &path::Path, session: &Session) -> String {
    let mut filetxt = Vec::new();
    BufReader::new(session.open_file(filepath).unwrap()).read_to_end(&mut filetxt).unwrap();
    let src = str::from_utf8(&filetxt).unwrap();

    scopes::mask_comments(src)
}

pub fn complete_from_file(src: &str, filepath: &path::Path, pos: usize, session: &Session) -> vec::IntoIter<Match> {
    let start = scopes::get_start_of_search_expr(src, pos);
    let expr = &src[start..pos];

    let (contextstr, searchstr, completetype) = scopes::split_into_context_and_completion(expr);

    debug!("{:?}: contextstr is |{}|, searchstr is |{}|", completetype, contextstr, searchstr);

    let mut out = Vec::new();

    match completetype {
        CompletionType::CompletePath => {
            let mut v = expr.split("::").collect::<Vec<_>>();
            let mut global = false;
            if v[0] == "" {      // i.e. starts with '::' e.g. ::std::old_io::blah
                v.remove(0);
                global = true;
            }

            let path = Path::from_vec(global, v);
            for m in nameres::resolve_path(&path, filepath, pos,
                                         SearchType::StartsWith, Namespace::BothNamespaces,
                                         session) {
                out.push(m);
            }
        },
        CompletionType::CompleteField => {
            let context = ast::get_type_of(contextstr.to_owned(), filepath, pos, session);
            debug!("complete_from_file context is {:?}", context);
            context.map(|ty| {
                if let Ty::TyMatch(m) = ty {
                    for m in nameres::search_for_field_or_method(m, searchstr, SearchType::StartsWith) {
                        out.push(m)
                    }
                }
            });
        }
    }
    out.into_iter()
}

pub fn find_definition(src: &str, filepath: &path::Path, pos: usize, session: &Session) -> Option<Match> {
    find_definition_(src, filepath, pos, session)
}

pub fn find_definition_(src: &str, filepath: &path::Path, pos: usize, session: &Session) -> Option<Match> {
    let (start, end) = scopes::expand_search_expr(src, pos);
    let expr = &src[start..end];

    let (contextstr, searchstr, completetype) = scopes::split_into_context_and_completion(expr);

    debug!("find_definition_ for |{:?}| |{:?}| {:?}", contextstr, searchstr, completetype);

    match completetype {
        CompletionType::CompletePath => {
            let mut v = expr.split("::").collect::<Vec<_>>();
            let mut global = false;
            if v[0] == "" {      // i.e. starts with '::' e.g. ::std::old_io::blah
                v.remove(0);
                global = true;
            }

            let segs = v
                .into_iter()
                .map(|x| PathSegment{ name: x.to_owned(), types: Vec::new() })
                .collect::<Vec<_>>();
            let path = Path{ global: global, segments: segs };

            nameres::resolve_path(&path, filepath, pos,
                                  SearchType::ExactMatch, Namespace::BothNamespaces,
                                  session).nth(0)
        },
        CompletionType::CompleteField => {
            let context = ast::get_type_of(contextstr.to_owned(), filepath, pos, session);
            debug!("context is {:?}", context);

            context.and_then(|ty| {
                // for now, just handle matches
                match ty {
                    Ty::TyMatch(m) => {
                        nameres::search_for_field_or_method(m, searchstr, SearchType::ExactMatch).nth(0)
                    }
                    _ => None
                }
            })
        }
    }
}
<commit_msg>core: derive Copy instead of explicit "impl"<commit_after>use std::fs::File;
use std::io::{BufReader, Read};
use std::{str, vec, fmt};
use std::path;
use std::io;

use scopes;
use nameres;
use ast;

#[derive(Debug,Clone,Copy,PartialEq)]
pub enum MatchType {
    Struct,
    Module,
    MatchArm,
    Function,
    Crate,
    Let,
    IfLet,
    StructField,
    Impl,
    Enum,
    EnumVariant,
    Type,
    FnArg,
    Trait,
    Const,
    Static
}

#[derive(Debug,Clone,Copy)]
pub enum SearchType {
    ExactMatch,
    StartsWith
}

#[derive(Debug,Clone,Copy)]
pub enum Namespace {
    TypeNamespace,
    ValueNamespace,
    BothNamespaces
}

#[derive(Debug,Clone,Copy)]
pub enum CompletionType {
    CompleteField,
    CompletePath
}

#[derive(Clone)]
pub struct Match {
    pub matchstr: String,
    pub filepath: path::PathBuf,
    pub point: usize,
    pub local: bool,
    pub mtype: MatchType,
    pub contextstr: String,
    pub generic_args: Vec<String>,
    pub generic_types: Vec<PathSearch>,  // generic types are evaluated lazily
    pub session: Session
}

impl Match {
    pub fn with_generic_types(&self, generic_types: Vec<PathSearch>) -> Match {
        Match {
            matchstr: self.matchstr.clone(),
            filepath: self.filepath.clone(),
            point: self.point,
            local: self.local,
            mtype: self.mtype,
            contextstr: self.contextstr.clone(),
            generic_args: self.generic_args.clone(),
            generic_types: generic_types,
            session: self.session.clone()
        }
    }
}

impl fmt::Debug for Match {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Match [{:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?} |{}|, {:?}]",
               self.matchstr,
               self.filepath.to_str(),
               self.point,
               self.local,
               self.mtype,
               self.generic_args,
               self.generic_types,
               self.contextstr,
               self.session)
    }
}

#[derive(Clone)]
pub struct Scope {
    pub filepath: path::PathBuf,
    pub point: usize,
    pub session: Session
}

impl Scope {
    pub fn from_match(m: &Match) -> Scope {
        Scope{ filepath: m.filepath.clone(), point: m.point, session: m.session.clone() }
    }
}

impl fmt::Debug for Scope {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Scope [{:?}, {:?}, {:?}]",
               self.filepath.to_str(),
               self.point,
               self.session)
    }
}

// Represents a type. Equivilent to rustc's ast::Ty but can be passed across threads
#[derive(Debug,Clone)]
pub enum Ty {
    TyMatch(Match),
    TyPathSearch(Path, Scope),   // A path + the scope to be able to resolve it
    TyTuple(Vec<Ty>),
    TyUnsupported
}

// The racer implementation of an ast::Path. Difference is that it is Send-able
#[derive(Clone)]
pub struct Path {
    pub global: bool,
    pub segments: Vec<PathSegment>
}

impl Path {
    pub fn generic_types(&self) -> ::std::slice::Iter<Path> {
        self.segments[self.segments.len()-1].types.iter()
    }

    pub fn from_vec(global: bool, v: Vec<&str>) -> Path {
        let segs = v
            .into_iter()
            .map(|x| PathSegment{ name: x.to_owned(), types: Vec::new() })
            .collect::<Vec<_>>();
        Path{ global: global, segments: segs }
    }

    pub fn from_svec(global: bool, v: Vec<String>) -> Path {
        let segs = v
            .into_iter()
            .map(|x| PathSegment{ name: x, types: Vec::new() })
            .collect::<Vec<_>>();
        Path{ global: global, segments: segs }
    }
}

impl fmt::Debug for Path {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "P["));
        let mut first = true;
        for seg in &self.segments {
            if first {
                try!(write!(f, "{}", seg.name));
                first = false;
            } else {
                try!(write!(f, "::{}", seg.name));
            }

            if !seg.types.is_empty() {
                try!(write!(f, "<"));
                let mut tfirst = true;
                for typath in &seg.types {
                    if tfirst {
                        try!(write!(f, "{:?}", typath));
                        tfirst = false;
                    } else {
                        try!(write!(f, ",{:?}", typath))
                    }
                }
                try!(write!(f, ">"));
            }
        }
        write!(f, "]")
    }
}

#[derive(Debug,Clone)]
pub struct PathSegment {
    pub name: String,
    pub types: Vec<Path>
}

#[derive(Clone)]
pub struct PathSearch {
    pub path: Path,
    pub filepath: path::PathBuf,
    pub point: usize,
    pub session: Session
}

impl fmt::Debug for PathSearch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Search [{:?}, {:?}, {:?}, {:?}]",
               self.path,
               self.filepath.to_str(),
               self.point,
               self.session)
    }
}

#[derive(Debug,Clone)]
pub struct Session {
    pub query_path: path::PathBuf,            // the input path of the query
    pub substitute_file: path::PathBuf        // the temporary file
}

impl Session {
    pub fn from_path(query_path: &path::Path, substitute_file: &path::Path) -> Session {
        Session {
            query_path: query_path.to_path_buf(),
            substitute_file: substitute_file.to_path_buf()
        }
    }

    pub fn open_file(&self, path: &path::Path) -> io::Result<File> {
        if path == self.query_path.as_path() {
            File::open(&self.substitute_file)
        } else {
            File::open(path)
        }
    }
}

pub fn load_file(filepath: &path::Path, session: &Session) -> String {
    let mut rawbytes = Vec::new();
    if let Ok(f) = session.open_file(filepath) {
        BufReader::new(f).read_to_end(&mut rawbytes).unwrap();
    } else {
        error!("load_file couldn't open {:?}. Returning empty string",filepath);
        return "".into();
    }

    // skip BOF bytes, if present
    if rawbytes.len() > 2 && rawbytes[0..3] == [0xEF, 0xBB, 0xBF] {
        let mut it = rawbytes.into_iter();
        it.next(); it.next(); it.next();
        String::from_utf8(it.collect::<Vec<_>>()).unwrap()
    } else {
        String::from_utf8(rawbytes).unwrap()
    }
}

pub fn load_file_and_mask_comments(filepath: &path::Path, session: &Session) -> String {
    let mut filetxt = Vec::new();
    BufReader::new(session.open_file(filepath).unwrap()).read_to_end(&mut filetxt).unwrap();
    let src = str::from_utf8(&filetxt).unwrap();

    scopes::mask_comments(src)
}

pub fn complete_from_file(src: &str, filepath: &path::Path, pos: usize, session: &Session) -> vec::IntoIter<Match> {
    let start = scopes::get_start_of_search_expr(src, pos);
    let expr = &src[start..pos];

    let (contextstr, searchstr, completetype) = scopes::split_into_context_and_completion(expr);

    debug!("{:?}: contextstr is |{}|, searchstr is |{}|", completetype, contextstr, searchstr);

    let mut out = Vec::new();

    match completetype {
        CompletionType::CompletePath => {
            let mut v = expr.split("::").collect::<Vec<_>>();
            let mut global = false;
            if v[0] == "" {      // i.e. starts with '::' e.g. ::std::old_io::blah
                v.remove(0);
                global = true;
            }

            let path = Path::from_vec(global, v);
            for m in nameres::resolve_path(&path, filepath, pos,
                                         SearchType::StartsWith, Namespace::BothNamespaces,
                                         session) {
                out.push(m);
            }
        },
        CompletionType::CompleteField => {
            let context = ast::get_type_of(contextstr.to_owned(), filepath, pos, session);
            debug!("complete_from_file context is {:?}", context);
            context.map(|ty| {
                if let Ty::TyMatch(m) = ty {
                    for m in nameres::search_for_field_or_method(m, searchstr, SearchType::StartsWith) {
                        out.push(m)
                    }
                }
            });
        }
    }
    out.into_iter()
}

pub fn find_definition(src: &str, filepath: &path::Path, pos: usize, session: &Session) -> Option<Match> {
    find_definition_(src, filepath, pos, session)
}

pub fn find_definition_(src: &str, filepath: &path::Path, pos: usize, session: &Session) -> Option<Match> {
    let (start, end) = scopes::expand_search_expr(src, pos);
    let expr = &src[start..end];

    let (contextstr, searchstr, completetype) = scopes::split_into_context_and_completion(expr);

    debug!("find_definition_ for |{:?}| |{:?}| {:?}", contextstr, searchstr, completetype);

    match completetype {
        CompletionType::CompletePath => {
            let mut v = expr.split("::").collect::<Vec<_>>();
            let mut global = false;
            if v[0] == "" {      // i.e. starts with '::' e.g. ::std::old_io::blah
                v.remove(0);
                global = true;
            }

            let segs = v
                .into_iter()
                .map(|x| PathSegment{ name: x.to_owned(), types: Vec::new() })
                .collect::<Vec<_>>();
            let path = Path{ global: global, segments: segs };

            nameres::resolve_path(&path, filepath, pos,
                                  SearchType::ExactMatch, Namespace::BothNamespaces,
                                  session).nth(0)
        },
        CompletionType::CompleteField => {
            let context = ast::get_type_of(contextstr.to_owned(), filepath, pos, session);
            debug!("context is {:?}", context);

            context.and_then(|ty| {
                // for now, just handle matches
                match ty {
                    Ty::TyMatch(m) => {
                        nameres::search_for_field_or_method(m, searchstr, SearchType::ExactMatch).nth(0)
                    }
                    _ => None
                }
            })
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![crate_name = "device"]
#![comment = "Back-ends to abstract over the differences between low-level, \
              platform-specific graphics APIs"]
#![license = "ASL2"]
#![crate_type = "lib"]

#![feature(phase)]
#![deny(missing_doc)]

//! Graphics device. Not meant for direct use.

#[phase(plugin, link)] extern crate log;
extern crate libc;

// when cargo is ready, re-enable the cfgs
/* #[cfg(gl)] */ pub use self::gl as back;
/* #[cfg(gl)] */ pub use gl::GlDevice;
/* #[cfg(gl)] */ pub use gl::draw::GlCommandBuffer;
// #[cfg(d3d11)] ... // TODO

use std::mem::size_of;

use blob::{Blob, RefBlobCast};

pub mod attrib;
pub mod blob;
pub mod draw;
pub mod shade;
pub mod state;
pub mod target;
pub mod tex;
/* #[cfg(gl)] */ mod gl;

/// Draw vertex count.
pub type VertexCount = u32;
/// Draw index count.
pub type IndexCount = u32;
/// Draw number of instances
pub type InstanceCount = u32;
/// Index of a uniform block.
pub type UniformBlockIndex = u8;
/// Slot for an attribute.
pub type AttributeSlot = u8;
/// Slot for a uniform buffer object.
pub type UniformBufferSlot = u8;
/// Slot a texture can be bound to.
pub type TextureSlot = u8;

/// A generic handle struct
#[deriving(Clone, Show, PartialEq)]
pub struct Handle<T, I>(T, I);

#[deriving(Clone, Show)]
impl<T: Copy, I> Handle<T, I> {
    /// Get the internal name
    pub fn get_name(&self) -> T {
        let Handle(name, _) = *self;
        name
    }

    /// Get the info reference
    pub fn get_info(&self) -> &I {
        let Handle(_, ref info) = *self;
        info
    }
}

/// Type-safe buffer handle
#[deriving(Show, Clone)]
pub struct BufferHandle<T> {
    raw: RawBufferHandle,
}

impl<T> BufferHandle<T> {
    /// Create a type-safe BufferHandle from a RawBufferHandle
    pub fn from_raw(handle: RawBufferHandle) -> BufferHandle<T> {
        BufferHandle {
            raw: handle,
        }
    }

    /// Cast the type this BufferHandle references
    pub fn cast<U>(self) -> BufferHandle<U> {
        BufferHandle::from_raw(self.raw)
    }

    /// Get the underlying GL name for this BufferHandle
    pub fn get_name(&self) -> back::Buffer {
        self.raw.get_name()
    }

    /// Get the associated information about the buffer
    pub fn get_info(&self) -> &BufferInfo {
        self.raw.get_info()
    }

    /// Get the underlying raw Handle
    pub fn raw(&self) -> RawBufferHandle {
        self.raw
    }
}

/// Raw (untyped) Buffer Handle
pub type RawBufferHandle = Handle<back::Buffer, BufferInfo>;
/// Array Buffer Handle
pub type ArrayBufferHandle = Handle<back::ArrayBuffer, ()>;
/// Shader Handle
pub type ShaderHandle  = Handle<back::Shader, shade::Stage>;
/// Program Handle
pub type ProgramHandle = Handle<back::Program, shade::ProgramInfo>;
/// Frame Buffer Handle
pub type FrameBufferHandle = Handle<back::FrameBuffer, ()>;
/// Surface Handle
pub type SurfaceHandle = Handle<back::Surface, tex::SurfaceInfo>;
/// Texture Handle
pub type TextureHandle = Handle<back::Texture, tex::TextureInfo>;
/// Sampler Handle
pub type SamplerHandle = Handle<back::Sampler, tex::SamplerInfo>;

/// A helper method to test `#[vertex_format]` without GL context
//#[cfg(test)]
pub fn make_fake_buffer<T>() -> BufferHandle<T> {
    let info = BufferInfo {
        usage: UsageStatic,
        size: 0,
    };
    BufferHandle::from_raw(Handle(0, info))
}

/// Return the framebuffer handle for the screen
pub fn get_main_frame_buffer() -> FrameBufferHandle {
    Handle(0, ())
}

/// Features that the device supports.
#[deriving(Show)]
#[allow(missing_doc)] // pretty self-explanatory fields!
pub struct Capabilities {
    pub shader_model: shade::ShaderModel,
    pub max_draw_buffers : uint,
    pub max_texture_size : uint,
    pub max_vertex_attributes: uint,
    pub uniform_block_supported: bool,
    pub array_buffer_supported: bool,
    pub sampler_objects_supported: bool,
    pub immutable_storage_supported: bool,
    pub instance_call_supported: bool,
    pub instance_rate_supported: bool,
}

/// Describes what geometric primitives are created from vertex data.
#[deriving(Clone, PartialEq, Show)]
#[repr(u8)]
pub enum PrimitiveType {
    /// Each vertex represents a single point.
    Point,
    /// Each pair of vertices represent a single line segment. For example, with `[a, b, c, d,
    /// e]`, `a` and `b` form a line, `c` and `d` form a line, and `e` is discarded.
    Line,
    /// Every two consecutive vertices represent a single line segment. Visually forms a "path" of
    /// lines, as they are all connected. For example, with `[a, b, c]`, `a` and `b` form a line
    /// line, and `b` and `c` form a line.
    LineStrip,
    /// Each triplet of vertices represent a single triangle. For example, with `[a, b, c, d, e]`,
    /// `a`, `b`, and `c` form a triangle, `d` and `e` are discarded.
    TriangleList,
    /// Every three consecutive vertices represent a single triangle. For example, with `[a, b, c,
    /// d]`, `a`, `b`, and `c` form a triangle, and `b`, `c`, and `d` form a triangle.
    TriangleStrip,
    /// The first vertex with the last two are forming a triangle. For example, with `[a, b, c, d
    /// ]`, `a` , `b`, and `c` form a triangle, and `a`, `c`, and `d` form a triangle.
    TriangleFan,
    //Quad,
}

/// A type of each index value in the mesh's index buffer
pub type IndexType = attrib::IntSize;

/// A hint as to how this buffer will be used.
///
/// The nature of these hints make them very implementation specific. Different drivers on
/// different hardware will handle them differently. Only careful profiling will tell which is the
/// best to use for a specific buffer.
#[deriving(Clone, PartialEq, Show)]
#[repr(u8)]
pub enum BufferUsage {
    /// Once uploaded, this buffer will rarely change, but will be read from often.
    UsageStatic,
    /// This buffer will be updated "frequently", and will be read from multiple times between
    /// updates.
    UsageDynamic,
    /// This buffer always or almost always be updated after each read.
    UsageStream,
}

/// An information block that is immutable and associated with each buffer
#[deriving(Clone, PartialEq, Show)]
pub struct BufferInfo {
    /// Usage hint
    pub usage: BufferUsage,
    /// Size in bytes
    pub size: uint,
}

/// Serialized device command.
/// While this is supposed to be an internal detail of a device,
/// this particular representation may be used by different backends,
/// such as OpenGL (prior to GLNG) and DirectX (prior to DX12)
#[allow(missing_doc)]
#[deriving(Show)]
pub enum Command {
    BindProgram(back::Program),
    BindArrayBuffer(back::ArrayBuffer),
    BindAttribute(AttributeSlot, back::Buffer, attrib::Format),
    BindIndex(back::Buffer),
    BindFrameBuffer(back::FrameBuffer),
    /// Unbind any surface from the specified target slot
    UnbindTarget(target::Target),
    /// Bind a surface to the specified target slot
    BindTargetSurface(target::Target, back::Surface),
    /// Bind a level of the texture to the specified target slot
    BindTargetTexture(target::Target, back::Texture, target::Level, Option<target::Layer>),
    BindUniformBlock(back::Program, UniformBufferSlot, UniformBlockIndex, back::Buffer),
    BindUniform(shade::Location, shade::UniformValue),
    BindTexture(TextureSlot, tex::TextureKind, back::Texture, Option<SamplerHandle>),
    SetPrimitiveState(state::Primitive),
    SetViewport(target::Rect),
    SetScissor(Option<target::Rect>),
    SetDepthStencilState(Option<state::Depth>, Option<state::Stencil>, state::CullMode),
    SetBlendState(Option<state::Blend>),
    SetColorMask(state::ColorMask),
    UpdateBuffer(back::Buffer, Box<Blob<()> + Send>, uint),
    UpdateTexture(tex::TextureKind, back::Texture, tex::ImageInfo, Box<Blob<()> + Send>),
    // drawing
    Clear(target::ClearData),
    Draw(PrimitiveType, VertexCount, VertexCount, Option<InstanceCount>),
    DrawIndexed(PrimitiveType, IndexType, IndexCount, IndexCount, Option<InstanceCount>),
}

// CommandBuffer is really an associated type, so will look much better when
// Rust supports this natively.
/// An interface for performing draw calls using a specific graphics API
#[allow(missing_doc)]
pub trait Device<C: draw::CommandBuffer> {
    /// Returns the capabilities available to the specific API implementation
    fn get_capabilities<'a>(&'a self) -> &'a Capabilities;
    /// Reset all the states to disabled/default
    fn reset_state(&mut self);
    /// Submit a command buffer for execution
    fn submit(&mut self, cb: &C);
    // resource creation
    fn create_buffer_raw(&mut self, size: uint, usage: BufferUsage) -> BufferHandle<()>;
    fn create_buffer<T>(&mut self, num: uint, usage: BufferUsage) -> BufferHandle<T> {
        self.create_buffer_raw(num * size_of::<T>(), usage).cast()
    }
    fn create_buffer_static<T>(&mut self, &Blob<T>) -> BufferHandle<T>;
    fn create_array_buffer(&mut self) -> Result<ArrayBufferHandle, ()>;
    fn create_shader(&mut self, stage: shade::Stage, code: shade::ShaderSource) ->
                     Result<ShaderHandle, shade::CreateShaderError>;
    fn create_program(&mut self, shaders: &[ShaderHandle]) -> Result<ProgramHandle, ()>;
    fn create_frame_buffer(&mut self) -> FrameBufferHandle;
    fn create_surface(&mut self, info: tex::SurfaceInfo) -> Result<SurfaceHandle, tex::SurfaceError>;
    fn create_texture(&mut self, info: tex::TextureInfo) -> Result<TextureHandle, tex::TextureError>;
    fn create_sampler(&mut self, info: tex::SamplerInfo) -> SamplerHandle;
    // resource deletion
    fn delete_buffer_raw(&mut self, buf: BufferHandle<()>);
    fn delete_buffer<T>(&mut self, buf: BufferHandle<T>) {
        self.delete_buffer_raw(buf.cast());
    }
    fn delete_shader(&mut self, ShaderHandle);
    fn delete_program(&mut self, ProgramHandle);
    fn delete_surface(&mut self, SurfaceHandle);
    fn delete_texture(&mut self, TextureHandle);
    fn delete_sampler(&mut self, SamplerHandle);
    /// Update the information stored in a specific buffer
    fn update_buffer_raw(&mut self, buf: BufferHandle<()>, data: &Blob<()>, offset_bytes: uint);
    fn update_buffer<T>(&mut self, buf: BufferHandle<T>, data: &Blob<T>, offset_elements: uint) {
        self.update_buffer_raw(buf.cast(), data.cast(), size_of::<T>() * offset_elements);
    }
    /// Update the information stored in a texture
    fn update_texture_raw(&mut self, tex: &TextureHandle, img: &tex::ImageInfo,
                          data: &Blob<()>) -> Result<(), tex::TextureError>;
    fn update_texture<T>(&mut self, tex: &TextureHandle, img: &tex::ImageInfo,
                      data: &Blob<T>) -> Result<(), tex::TextureError> {
        self.update_texture_raw(tex, img, data.cast())
    }
    fn generate_mipmap(&mut self, tex: &TextureHandle);
}
<commit_msg>Don't import std::mem::size_of directly<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![crate_name = "device"]
#![comment = "Back-ends to abstract over the differences between low-level, \
              platform-specific graphics APIs"]
#![license = "ASL2"]
#![crate_type = "lib"]

#![feature(phase)]
#![deny(missing_doc)]

//! Graphics device. Not meant for direct use.

#[phase(plugin, link)] extern crate log;
extern crate libc;

// when cargo is ready, re-enable the cfgs
/* #[cfg(gl)] */ pub use self::gl as back;
/* #[cfg(gl)] */ pub use gl::GlDevice;
/* #[cfg(gl)] */ pub use gl::draw::GlCommandBuffer;
// #[cfg(d3d11)] ... // TODO

use std::mem;

use blob::{Blob, RefBlobCast};

pub mod attrib;
pub mod blob;
pub mod draw;
pub mod shade;
pub mod state;
pub mod target;
pub mod tex;
/* #[cfg(gl)] */ mod gl;

/// Draw vertex count.
pub type VertexCount = u32;
/// Draw index count.
pub type IndexCount = u32;
/// Draw number of instances
pub type InstanceCount = u32;
/// Index of a uniform block.
pub type UniformBlockIndex = u8;
/// Slot for an attribute.
pub type AttributeSlot = u8;
/// Slot for a uniform buffer object.
pub type UniformBufferSlot = u8;
/// Slot a texture can be bound to.
pub type TextureSlot = u8;

/// A generic handle struct
#[deriving(Clone, Show, PartialEq)]
pub struct Handle<T, I>(T, I);

#[deriving(Clone, Show)]
impl<T: Copy, I> Handle<T, I> {
    /// Get the internal name
    pub fn get_name(&self) -> T {
        let Handle(name, _) = *self;
        name
    }

    /// Get the info reference
    pub fn get_info(&self) -> &I {
        let Handle(_, ref info) = *self;
        info
    }
}

/// Type-safe buffer handle
#[deriving(Show, Clone)]
pub struct BufferHandle<T> {
    raw: RawBufferHandle,
}

impl<T> BufferHandle<T> {
    /// Create a type-safe BufferHandle from a RawBufferHandle
    pub fn from_raw(handle: RawBufferHandle) -> BufferHandle<T> {
        BufferHandle {
            raw: handle,
        }
    }

    /// Cast the type this BufferHandle references
    pub fn cast<U>(self) -> BufferHandle<U> {
        BufferHandle::from_raw(self.raw)
    }

    /// Get the underlying GL name for this BufferHandle
    pub fn get_name(&self) -> back::Buffer {
        self.raw.get_name()
    }

    /// Get the associated information about the buffer
    pub fn get_info(&self) -> &BufferInfo {
        self.raw.get_info()
    }

    /// Get the underlying raw Handle
    pub fn raw(&self) -> RawBufferHandle {
        self.raw
    }
}

/// Raw (untyped) Buffer Handle
pub type RawBufferHandle = Handle<back::Buffer, BufferInfo>;
/// Array Buffer Handle
pub type ArrayBufferHandle = Handle<back::ArrayBuffer, ()>;
/// Shader Handle
pub type ShaderHandle  = Handle<back::Shader, shade::Stage>;
/// Program Handle
pub type ProgramHandle = Handle<back::Program, shade::ProgramInfo>;
/// Frame Buffer Handle
pub type FrameBufferHandle = Handle<back::FrameBuffer, ()>;
/// Surface Handle
pub type SurfaceHandle = Handle<back::Surface, tex::SurfaceInfo>;
/// Texture Handle
pub type TextureHandle = Handle<back::Texture, tex::TextureInfo>;
/// Sampler Handle
pub type SamplerHandle = Handle<back::Sampler, tex::SamplerInfo>;

/// A helper method to test `#[vertex_format]` without GL context
//#[cfg(test)]
pub fn make_fake_buffer<T>() -> BufferHandle<T> {
    let info = BufferInfo {
        usage: UsageStatic,
        size: 0,
    };
    BufferHandle::from_raw(Handle(0, info))
}

/// Return the framebuffer handle for the screen
pub fn get_main_frame_buffer() -> FrameBufferHandle {
    Handle(0, ())
}

/// Features that the device supports.
#[deriving(Show)]
#[allow(missing_doc)] // pretty self-explanatory fields!
pub struct Capabilities {
    pub shader_model: shade::ShaderModel,
    pub max_draw_buffers : uint,
    pub max_texture_size : uint,
    pub max_vertex_attributes: uint,
    pub uniform_block_supported: bool,
    pub array_buffer_supported: bool,
    pub sampler_objects_supported: bool,
    pub immutable_storage_supported: bool,
    pub instance_call_supported: bool,
    pub instance_rate_supported: bool,
}

/// Describes what geometric primitives are created from vertex data.
#[deriving(Clone, PartialEq, Show)]
#[repr(u8)]
pub enum PrimitiveType {
    /// Each vertex represents a single point.
    Point,
    /// Each pair of vertices represent a single line segment. For example, with `[a, b, c, d,
    /// e]`, `a` and `b` form a line, `c` and `d` form a line, and `e` is discarded.
    Line,
    /// Every two consecutive vertices represent a single line segment. Visually forms a "path" of
    /// lines, as they are all connected. For example, with `[a, b, c]`, `a` and `b` form a line
    /// line, and `b` and `c` form a line.
    LineStrip,
    /// Each triplet of vertices represent a single triangle. For example, with `[a, b, c, d, e]`,
    /// `a`, `b`, and `c` form a triangle, `d` and `e` are discarded.
    TriangleList,
    /// Every three consecutive vertices represent a single triangle. For example, with `[a, b, c,
    /// d]`, `a`, `b`, and `c` form a triangle, and `b`, `c`, and `d` form a triangle.
    TriangleStrip,
    /// The first vertex with the last two are forming a triangle. For example, with `[a, b, c, d
    /// ]`, `a` , `b`, and `c` form a triangle, and `a`, `c`, and `d` form a triangle.
    TriangleFan,
    //Quad,
}

/// A type of each index value in the mesh's index buffer
pub type IndexType = attrib::IntSize;

/// A hint as to how this buffer will be used.
///
/// The nature of these hints make them very implementation specific. Different drivers on
/// different hardware will handle them differently. Only careful profiling will tell which is the
/// best to use for a specific buffer.
#[deriving(Clone, PartialEq, Show)]
#[repr(u8)]
pub enum BufferUsage {
    /// Once uploaded, this buffer will rarely change, but will be read from often.
    UsageStatic,
    /// This buffer will be updated "frequently", and will be read from multiple times between
    /// updates.
    UsageDynamic,
    /// This buffer always or almost always be updated after each read.
    UsageStream,
}

/// An information block that is immutable and associated with each buffer
#[deriving(Clone, PartialEq, Show)]
pub struct BufferInfo {
    /// Usage hint
    pub usage: BufferUsage,
    /// Size in bytes
    pub size: uint,
}

/// Serialized device command.
/// While this is supposed to be an internal detail of a device,
/// this particular representation may be used by different backends,
/// such as OpenGL (prior to GLNG) and DirectX (prior to DX12)
#[allow(missing_doc)]
#[deriving(Show)]
pub enum Command {
    BindProgram(back::Program),
    BindArrayBuffer(back::ArrayBuffer),
    BindAttribute(AttributeSlot, back::Buffer, attrib::Format),
    BindIndex(back::Buffer),
    BindFrameBuffer(back::FrameBuffer),
    /// Unbind any surface from the specified target slot
    UnbindTarget(target::Target),
    /// Bind a surface to the specified target slot
    BindTargetSurface(target::Target, back::Surface),
    /// Bind a level of the texture to the specified target slot
    BindTargetTexture(target::Target, back::Texture, target::Level, Option<target::Layer>),
    BindUniformBlock(back::Program, UniformBufferSlot, UniformBlockIndex, back::Buffer),
    BindUniform(shade::Location, shade::UniformValue),
    BindTexture(TextureSlot, tex::TextureKind, back::Texture, Option<SamplerHandle>),
    SetPrimitiveState(state::Primitive),
    SetViewport(target::Rect),
    SetScissor(Option<target::Rect>),
    SetDepthStencilState(Option<state::Depth>, Option<state::Stencil>, state::CullMode),
    SetBlendState(Option<state::Blend>),
    SetColorMask(state::ColorMask),
    UpdateBuffer(back::Buffer, Box<Blob<()> + Send>, uint),
    UpdateTexture(tex::TextureKind, back::Texture, tex::ImageInfo, Box<Blob<()> + Send>),
    // drawing
    Clear(target::ClearData),
    Draw(PrimitiveType, VertexCount, VertexCount, Option<InstanceCount>),
    DrawIndexed(PrimitiveType, IndexType, IndexCount, IndexCount, Option<InstanceCount>),
}

// CommandBuffer is really an associated type, so will look much better when
// Rust supports this natively.
/// An interface for performing draw calls using a specific graphics API
#[allow(missing_doc)]
pub trait Device<C: draw::CommandBuffer> {
    /// Returns the capabilities available to the specific API implementation
    fn get_capabilities<'a>(&'a self) -> &'a Capabilities;
    /// Reset all the states to disabled/default
    fn reset_state(&mut self);
    /// Submit a command buffer for execution
    fn submit(&mut self, cb: &C);
    // resource creation
    fn create_buffer_raw(&mut self, size: uint, usage: BufferUsage) -> BufferHandle<()>;
    fn create_buffer<T>(&mut self, num: uint, usage: BufferUsage) -> BufferHandle<T> {
        self.create_buffer_raw(num * mem::size_of::<T>(), usage).cast()
    }
    fn create_buffer_static<T>(&mut self, &Blob<T>) -> BufferHandle<T>;
    fn create_array_buffer(&mut self) -> Result<ArrayBufferHandle, ()>;
    fn create_shader(&mut self, stage: shade::Stage, code: shade::ShaderSource) ->
                     Result<ShaderHandle, shade::CreateShaderError>;
    fn create_program(&mut self, shaders: &[ShaderHandle]) -> Result<ProgramHandle, ()>;
    fn create_frame_buffer(&mut self) -> FrameBufferHandle;
    fn create_surface(&mut self, info: tex::SurfaceInfo) -> Result<SurfaceHandle, tex::SurfaceError>;
    fn create_texture(&mut self, info: tex::TextureInfo) -> Result<TextureHandle, tex::TextureError>;
    fn create_sampler(&mut self, info: tex::SamplerInfo) -> SamplerHandle;
    // resource deletion
    fn delete_buffer_raw(&mut self, buf: BufferHandle<()>);
    fn delete_buffer<T>(&mut self, buf: BufferHandle<T>) {
        self.delete_buffer_raw(buf.cast());
    }
    fn delete_shader(&mut self, ShaderHandle);
    fn delete_program(&mut self, ProgramHandle);
    fn delete_surface(&mut self, SurfaceHandle);
    fn delete_texture(&mut self, TextureHandle);
    fn delete_sampler(&mut self, SamplerHandle);
    /// Update the information stored in a specific buffer
    fn update_buffer_raw(&mut self, buf: BufferHandle<()>, data: &Blob<()>, offset_bytes: uint);
    fn update_buffer<T>(&mut self, buf: BufferHandle<T>, data: &Blob<T>, offset_elements: uint) {
        self.update_buffer_raw(buf.cast(), data.cast(), mem::size_of::<T>() * offset_elements);
    }
    /// Update the information stored in a texture
    fn update_texture_raw(&mut self, tex: &TextureHandle, img: &tex::ImageInfo,
                          data: &Blob<()>) -> Result<(), tex::TextureError>;
    fn update_texture<T>(&mut self, tex: &TextureHandle, img: &tex::ImageInfo,
                      data: &Blob<T>) -> Result<(), tex::TextureError> {
        self.update_texture_raw(tex, img, data.cast())
    }
    fn generate_mipmap(&mut self, tex: &TextureHandle);
}
<|endoftext|>


<commit_before>use super::*;
use lsp::request::Request;
use lsp::notification::Notification;

impl State {
    pub fn handle_method_call(
        &mut self,
        languageId: Option<&str>,
        method_call: &rpc::MethodCall,
    ) -> Result<Value> {
        let user_handler = self.get(|state| {
            state
                .user_handlers
                .get(&method_call.method)
                .cloned()
                .ok_or_else(|| err_msg("No user handler"))
        });
        if let Ok(user_handler) = user_handler {
            return self.call(None, &user_handler, method_call.params.clone());
        }

        match method_call.method.as_str() {
            lsp::request::RegisterCapability::METHOD => {
                self.client_registerCapability(languageId.unwrap_or_default(), &method_call.params)
            }
            lsp::request::UnregisterCapability::METHOD => self.client_unregisterCapability(
                languageId.unwrap_or_default(),
                &method_call.params,
            ),
            lsp::request::HoverRequest::METHOD => self.textDocument_hover(&method_call.params),
            m @ lsp::request::GotoDefinition::METHOD
            | m @ REQUEST__CqueryBase
            | m @ REQUEST__CqueryCallers
            | m @ REQUEST__CqueryDerived
            | m @ REQUEST__CqueryVars
            | m @ lsp::request::GotoTypeDefinition::METHOD
            | m @ lsp::request::GotoImplementation::METHOD => {
                self.find_locations(m, &method_call.params)
            }
            lsp::request::Rename::METHOD => self.textDocument_rename(&method_call.params),
            lsp::request::DocumentSymbol::METHOD => {
                self.textDocument_documentSymbol(&method_call.params)
            }
            lsp::request::WorkspaceSymbol::METHOD => self.workspace_symbol(&method_call.params),
            lsp::request::CodeActionRequest::METHOD => {
                self.textDocument_codeAction(&method_call.params)
            }
            lsp::request::Completion::METHOD => self.textDocument_completion(&method_call.params),
            lsp::request::SignatureHelpRequest::METHOD => {
                self.textDocument_signatureHelp(&method_call.params)
            }
            lsp::request::References::METHOD => self.textDocument_references(&method_call.params),
            lsp::request::Formatting::METHOD => self.textDocument_formatting(&method_call.params),
            lsp::request::RangeFormatting::METHOD => {
                self.textDocument_rangeFormatting(&method_call.params)
            }
            lsp::request::ResolveCompletionItem::METHOD => {
                self.completionItem_resolve(&method_call.params)
            }
            lsp::request::ExecuteCommand::METHOD => {
                self.workspace_executeCommand(&method_call.params)
            }
            lsp::request::ApplyWorkspaceEdit::METHOD => {
                self.workspace_applyEdit(&method_call.params)
            }
            REQUEST__RustImplementations => self.rustDocument_implementations(&method_call.params),
            // Extensions.
            REQUEST__GetState => self.languageClient_getState(&method_call.params),
            REQUEST__IsAlive => self.languageClient_isAlive(&method_call.params),
            REQUEST__StartServer => self.languageClient_startServer(&method_call.params),
            REQUEST__RegisterServerCommands => {
                self.languageClient_registerServerCommands(&method_call.params)
            }
            REQUEST__SetLoggingLevel => self.languageClient_setLoggingLevel(&method_call.params),
            REQUEST__RegisterHandlers => self.languageClient_registerHandlers(&method_call.params),
            REQUEST__NCMRefresh => self.NCM_refresh(&method_call.params),
            REQUEST__ExplainErrorAtPoint => {
                self.languageClient_explainErrorAtPoint(&method_call.params)
            }
            REQUEST__OmniComplete => self.languageClient_omniComplete(&method_call.params),

            _ => {
                let languageId_target = if languageId.is_some() {
                    // Message from language server. Proxy to vim.
                    None
                } else {
                    // Message from vim. Proxy to language server.
                    let (languageId_target,): (String,) =
                        self.gather_args(&[VimVar::LanguageId], &method_call.params)?;
                    Some(languageId_target)
                };

                self.call(
                    languageId_target.as_deref(),
                    &method_call.method,
                    &method_call.params,
                )
            }
        }
    }

    pub fn handle_notification(
        &mut self,
        languageId: Option<&str>,
        notification: &rpc::Notification,
    ) -> Result<()> {
        let user_handler = self.get(|state| {
            state
                .user_handlers
                .get(&notification.method)
                .cloned()
                .ok_or_else(|| err_msg("No user handler"))
        });
        if let Ok(user_handler) = user_handler {
            self.call::<_, u8>(None, &user_handler, notification.params.clone())?;
            return Ok(());
        }

        match notification.method.as_str() {
            lsp::notification::DidChangeConfiguration::METHOD => {
                self.workspace_didChangeConfiguration(&notification.params)?
            }
            lsp::notification::DidOpenTextDocument::METHOD => {
                self.textDocument_didOpen(&notification.params)?
            }
            lsp::notification::DidChangeTextDocument::METHOD => {
                self.textDocument_didChange(&notification.params)?
            }
            lsp::notification::DidSaveTextDocument::METHOD => {
                self.textDocument_didSave(&notification.params)?
            }
            lsp::notification::DidCloseTextDocument::METHOD => {
                self.textDocument_didClose(&notification.params)?
            }
            lsp::notification::PublishDiagnostics::METHOD => {
                self.textDocument_publishDiagnostics(&notification.params)?
            }
            lsp::notification::LogMessage::METHOD => self.window_logMessage(&notification.params)?,
            lsp::notification::ShowMessage::METHOD => {
                self.window_showMessage(&notification.params)?
            }
            lsp::notification::Exit::METHOD => self.exit(&notification.params)?,
            // Extensions.
            NOTIFICATION__HandleBufReadPost => {
                self.languageClient_handleBufReadPost(&notification.params)?
            }
            NOTIFICATION__HandleTextChanged => {
                self.languageClient_handleTextChanged(&notification.params)?
            }
            NOTIFICATION__HandleBufWritePost => {
                self.languageClient_handleBufWritePost(&notification.params)?
            }
            NOTIFICATION__HandleBufDelete => {
                self.languageClient_handleBufDelete(&notification.params)?
            }
            NOTIFICATION__HandleCursorMoved => {
                self.languageClient_handleCursorMoved(&notification.params)?
            }
            NOTIFICATION__FZFSinkLocation => {
                self.languageClient_FZFSinkLocation(&notification.params)?
            }
            NOTIFICATION__FZFSinkCommand => {
                self.languageClient_FZFSinkCommand(&notification.params)?
            }
            // Extensions by language servers.
            NOTIFICATION__LanguageStatus => self.language_status(&notification.params)?,
            NOTIFICATION__RustBeginBuild => self.rust_handleBeginBuild(&notification.params)?,
            NOTIFICATION__RustDiagnosticsBegin => {
                self.rust_handleDiagnosticsBegin(&notification.params)?
            }
            NOTIFICATION__RustDiagnosticsEnd => {
                self.rust_handleDiagnosticsEnd(&notification.params)?
            }
            NOTIFICATION__WindowProgress => self.window_progress(&notification.params)?,
            NOTIFICATION__CqueryProgress => self.cquery_handleProgress(&notification.params)?,
            NOTIFICATION__ServerExited => self.languageClient_serverExited(&notification.params)?,

            _ => {
                let languageId_target = if languageId.is_some() {
                    // Message from language server. Proxy to vim.
                    None
                } else {
                    // Message from vim. Proxy to language server.
                    let (languageId_target,): (String,) =
                        self.gather_args(&[VimVar::LanguageId], &notification.params)?;
                    Some(languageId_target)
                };

                self.notify(
                    languageId_target.as_deref(),
                    &notification.method,
                    &notification.params,
                )?;
            }
        };

        Ok(())
    }
}
<commit_msg>Do not error out when extension method is not handled.<commit_after>use super::*;
use lsp::request::Request;
use lsp::notification::Notification;

impl State {
    pub fn handle_method_call(
        &mut self,
        languageId: Option<&str>,
        method_call: &rpc::MethodCall,
    ) -> Result<Value> {
        let user_handler = self.get(|state| {
            state
                .user_handlers
                .get(&method_call.method)
                .cloned()
                .ok_or_else(|| err_msg("No user handler"))
        });
        if let Ok(user_handler) = user_handler {
            return self.call(None, &user_handler, method_call.params.clone());
        }

        match method_call.method.as_str() {
            lsp::request::RegisterCapability::METHOD => {
                self.client_registerCapability(languageId.unwrap_or_default(), &method_call.params)
            }
            lsp::request::UnregisterCapability::METHOD => self.client_unregisterCapability(
                languageId.unwrap_or_default(),
                &method_call.params,
            ),
            lsp::request::HoverRequest::METHOD => self.textDocument_hover(&method_call.params),
            m @ lsp::request::GotoDefinition::METHOD
            | m @ REQUEST__CqueryBase
            | m @ REQUEST__CqueryCallers
            | m @ REQUEST__CqueryDerived
            | m @ REQUEST__CqueryVars
            | m @ lsp::request::GotoTypeDefinition::METHOD
            | m @ lsp::request::GotoImplementation::METHOD => {
                self.find_locations(m, &method_call.params)
            }
            lsp::request::Rename::METHOD => self.textDocument_rename(&method_call.params),
            lsp::request::DocumentSymbol::METHOD => {
                self.textDocument_documentSymbol(&method_call.params)
            }
            lsp::request::WorkspaceSymbol::METHOD => self.workspace_symbol(&method_call.params),
            lsp::request::CodeActionRequest::METHOD => {
                self.textDocument_codeAction(&method_call.params)
            }
            lsp::request::Completion::METHOD => self.textDocument_completion(&method_call.params),
            lsp::request::SignatureHelpRequest::METHOD => {
                self.textDocument_signatureHelp(&method_call.params)
            }
            lsp::request::References::METHOD => self.textDocument_references(&method_call.params),
            lsp::request::Formatting::METHOD => self.textDocument_formatting(&method_call.params),
            lsp::request::RangeFormatting::METHOD => {
                self.textDocument_rangeFormatting(&method_call.params)
            }
            lsp::request::ResolveCompletionItem::METHOD => {
                self.completionItem_resolve(&method_call.params)
            }
            lsp::request::ExecuteCommand::METHOD => {
                self.workspace_executeCommand(&method_call.params)
            }
            lsp::request::ApplyWorkspaceEdit::METHOD => {
                self.workspace_applyEdit(&method_call.params)
            }
            REQUEST__RustImplementations => self.rustDocument_implementations(&method_call.params),
            // Extensions.
            REQUEST__GetState => self.languageClient_getState(&method_call.params),
            REQUEST__IsAlive => self.languageClient_isAlive(&method_call.params),
            REQUEST__StartServer => self.languageClient_startServer(&method_call.params),
            REQUEST__RegisterServerCommands => {
                self.languageClient_registerServerCommands(&method_call.params)
            }
            REQUEST__SetLoggingLevel => self.languageClient_setLoggingLevel(&method_call.params),
            REQUEST__RegisterHandlers => self.languageClient_registerHandlers(&method_call.params),
            REQUEST__NCMRefresh => self.NCM_refresh(&method_call.params),
            REQUEST__ExplainErrorAtPoint => {
                self.languageClient_explainErrorAtPoint(&method_call.params)
            }
            REQUEST__OmniComplete => self.languageClient_omniComplete(&method_call.params),

            _ => {
                let languageId_target = if languageId.is_some() {
                    // Message from language server. No handler found.
                    let msg = format!("Message not handled: {:?}", method_call);
                    if method_call.method.starts_with('$') {
                        warn!("{}", msg);
                        return Ok(Value::default());
                    } else {
                        return Err(err_msg(msg));
                    }
                } else {
                    // Message from vim. Proxy to language server.
                    let (languageId_target,): (String,) =
                        self.gather_args(&[VimVar::LanguageId], &method_call.params)?;
                    Some(languageId_target)
                };

                self.call(
                    languageId_target.as_deref(),
                    &method_call.method,
                    &method_call.params,
                )
            }
        }
    }

    pub fn handle_notification(
        &mut self,
        languageId: Option<&str>,
        notification: &rpc::Notification,
    ) -> Result<()> {
        let user_handler = self.get(|state| {
            state
                .user_handlers
                .get(&notification.method)
                .cloned()
                .ok_or_else(|| err_msg("No user handler"))
        });
        if let Ok(user_handler) = user_handler {
            self.call::<_, u8>(None, &user_handler, notification.params.clone())?;
            return Ok(());
        }

        match notification.method.as_str() {
            lsp::notification::DidChangeConfiguration::METHOD => {
                self.workspace_didChangeConfiguration(&notification.params)?
            }
            lsp::notification::DidOpenTextDocument::METHOD => {
                self.textDocument_didOpen(&notification.params)?
            }
            lsp::notification::DidChangeTextDocument::METHOD => {
                self.textDocument_didChange(&notification.params)?
            }
            lsp::notification::DidSaveTextDocument::METHOD => {
                self.textDocument_didSave(&notification.params)?
            }
            lsp::notification::DidCloseTextDocument::METHOD => {
                self.textDocument_didClose(&notification.params)?
            }
            lsp::notification::PublishDiagnostics::METHOD => {
                self.textDocument_publishDiagnostics(&notification.params)?
            }
            lsp::notification::LogMessage::METHOD => self.window_logMessage(&notification.params)?,
            lsp::notification::ShowMessage::METHOD => {
                self.window_showMessage(&notification.params)?
            }
            lsp::notification::Exit::METHOD => self.exit(&notification.params)?,
            // Extensions.
            NOTIFICATION__HandleBufReadPost => {
                self.languageClient_handleBufReadPost(&notification.params)?
            }
            NOTIFICATION__HandleTextChanged => {
                self.languageClient_handleTextChanged(&notification.params)?
            }
            NOTIFICATION__HandleBufWritePost => {
                self.languageClient_handleBufWritePost(&notification.params)?
            }
            NOTIFICATION__HandleBufDelete => {
                self.languageClient_handleBufDelete(&notification.params)?
            }
            NOTIFICATION__HandleCursorMoved => {
                self.languageClient_handleCursorMoved(&notification.params)?
            }
            NOTIFICATION__FZFSinkLocation => {
                self.languageClient_FZFSinkLocation(&notification.params)?
            }
            NOTIFICATION__FZFSinkCommand => {
                self.languageClient_FZFSinkCommand(&notification.params)?
            }
            // Extensions by language servers.
            NOTIFICATION__LanguageStatus => self.language_status(&notification.params)?,
            NOTIFICATION__RustBeginBuild => self.rust_handleBeginBuild(&notification.params)?,
            NOTIFICATION__RustDiagnosticsBegin => {
                self.rust_handleDiagnosticsBegin(&notification.params)?
            }
            NOTIFICATION__RustDiagnosticsEnd => {
                self.rust_handleDiagnosticsEnd(&notification.params)?
            }
            NOTIFICATION__WindowProgress => self.window_progress(&notification.params)?,
            NOTIFICATION__CqueryProgress => self.cquery_handleProgress(&notification.params)?,
            NOTIFICATION__ServerExited => self.languageClient_serverExited(&notification.params)?,

            _ => {
                let languageId_target = if languageId.is_some() {
                    // Message from language server. No handler found.
                    let msg = format!("Message not handled: {:?}", notification);
                    if notification.method.starts_with('$') {
                        warn!("{}", msg);
                        return Ok(());
                    } else {
                        return Err(err_msg(msg));
                    }
                } else {
                    // Message from vim. Proxy to language server.
                    let (languageId_target,): (String,) =
                        self.gather_args(&[VimVar::LanguageId], &notification.params)?;
                    Some(languageId_target)
                };

                self.notify(
                    languageId_target.as_deref(),
                    &notification.method,
                    &notification.params,
                )?;
            }
        };

        Ok(())
    }
}
<|endoftext|>


<commit_before>use proc_macro2::Ident;

#[derive(Copy, Clone, PartialEq)]
pub enum Atom {
    Bool,
    U8,
    U16,
    U32,
    U64,
    Usize,
    I8,
    I16,
    I32,
    I64,
    Isize,
    CxxString,
    RustString,
}

impl Atom {
    pub fn from(ident: &Ident) -> Option<Self> {
        use self::Atom::*;
        match ident.to_string().as_str() {
            "bool" => Some(Bool),
            "u8" => Some(U8),
            "u16" => Some(U16),
            "u32" => Some(U32),
            "u64" => Some(U64),
            "usize" => Some(Usize),
            "i8" => Some(I8),
            "i16" => Some(I16),
            "i32" => Some(I32),
            "i64" => Some(I64),
            "isize" => Some(Isize),
            "CxxString" => Some(CxxString),
            "String" => Some(RustString),
            _ => None,
        }
    }
}
<commit_msg>Add PartialEq impls for comparison against specific atoms<commit_after>use crate::syntax::Type;
use proc_macro2::Ident;

#[derive(Copy, Clone, PartialEq)]
pub enum Atom {
    Bool,
    U8,
    U16,
    U32,
    U64,
    Usize,
    I8,
    I16,
    I32,
    I64,
    Isize,
    CxxString,
    RustString,
}

impl Atom {
    pub fn from(ident: &Ident) -> Option<Self> {
        use self::Atom::*;
        match ident.to_string().as_str() {
            "bool" => Some(Bool),
            "u8" => Some(U8),
            "u16" => Some(U16),
            "u32" => Some(U32),
            "u64" => Some(U64),
            "usize" => Some(Usize),
            "i8" => Some(I8),
            "i16" => Some(I16),
            "i32" => Some(I32),
            "i64" => Some(I64),
            "isize" => Some(Isize),
            "CxxString" => Some(CxxString),
            "String" => Some(RustString),
            _ => None,
        }
    }
}

impl PartialEq<Atom> for Ident {
    fn eq(&self, atom: &Atom) -> bool {
        Atom::from(self) == Some(*atom)
    }
}

impl PartialEq<Atom> for Type {
    fn eq(&self, atom: &Atom) -> bool {
        match self {
            Type::Ident(ident) => ident == atom,
            _ => false,
        }
    }
}
<|endoftext|>


<commit_before>//! Drivers are responsible for calling [`codegen_mono_item`] and performing any further actions
//! like JIT executing or writing object files.

use std::any::Any;

use rustc_middle::middle::cstore::EncodedMetadata;
use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};

use crate::prelude::*;
use crate::CodegenMode;

mod aot;
#[cfg(feature = "jit")]
mod jit;

pub(crate) fn codegen_crate(
    tcx: TyCtxt<'_>,
    metadata: EncodedMetadata,
    need_metadata_module: bool,
    config: crate::BackendConfig,
) -> Box<dyn Any> {
    tcx.sess.abort_if_errors();

    match config.codegen_mode {
        CodegenMode::Aot => aot::run_aot(tcx, metadata, need_metadata_module),
        CodegenMode::Jit | CodegenMode::JitLazy => {
            let is_executable = tcx
                .sess
                .crate_types()
                .contains(&rustc_session::config::CrateType::Executable);
            if !is_executable {
                tcx.sess.fatal("can't jit non-executable crate");
            }

            #[cfg(feature = "jit")]
            let _: ! = jit::run_jit(tcx, config.codegen_mode);

            #[cfg(not(feature = "jit"))]
            tcx.sess
                .fatal("jit support was disabled when compiling rustc_codegen_cranelift");
        }
    }
}

fn predefine_mono_items<'tcx>(
    cx: &mut crate::CodegenCx<'tcx, impl Module>,
    mono_items: &[(MonoItem<'tcx>, (RLinkage, Visibility))],
) {
    cx.tcx.sess.time("predefine functions", || {
        for &(mono_item, (linkage, visibility)) in mono_items {
            match mono_item {
                MonoItem::Fn(instance) => {
                    let name = cx.tcx.symbol_name(instance).name.to_string();
                    let sig = get_function_sig(cx.tcx, cx.module.isa().triple(), instance);
                    let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
                    cx.module.declare_function(&name, linkage, &sig).unwrap();
                }
                MonoItem::Static(_) | MonoItem::GlobalAsm(_) => {}
            }
        }
    });
}

fn time<R>(tcx: TyCtxt<'_>, name: &'static str, f: impl FnOnce() -> R) -> R {
    if std::env::var("CG_CLIF_DISPLAY_CG_TIME")
        .as_ref()
        .map(|val| &**val)
        == Ok("1")
    {
        println!("[{:<30}: {}] start", tcx.crate_name(LOCAL_CRATE), name);
        let before = std::time::Instant::now();
        let res = tcx.sess.time(name, f);
        let after = std::time::Instant::now();
        println!(
            "[{:<30}: {}] end time: {:?}",
            tcx.crate_name(LOCAL_CRATE),
            name,
            after - before
        );
        res
    } else {
        tcx.sess.time(name, f)
    }
}
<commit_msg>Add print on panic for predefining of a function<commit_after>//! Drivers are responsible for calling [`codegen_mono_item`] and performing any further actions
//! like JIT executing or writing object files.

use std::any::Any;

use rustc_middle::middle::cstore::EncodedMetadata;
use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};

use crate::prelude::*;
use crate::CodegenMode;

mod aot;
#[cfg(feature = "jit")]
mod jit;

pub(crate) fn codegen_crate(
    tcx: TyCtxt<'_>,
    metadata: EncodedMetadata,
    need_metadata_module: bool,
    config: crate::BackendConfig,
) -> Box<dyn Any> {
    tcx.sess.abort_if_errors();

    match config.codegen_mode {
        CodegenMode::Aot => aot::run_aot(tcx, metadata, need_metadata_module),
        CodegenMode::Jit | CodegenMode::JitLazy => {
            let is_executable = tcx
                .sess
                .crate_types()
                .contains(&rustc_session::config::CrateType::Executable);
            if !is_executable {
                tcx.sess.fatal("can't jit non-executable crate");
            }

            #[cfg(feature = "jit")]
            let _: ! = jit::run_jit(tcx, config.codegen_mode);

            #[cfg(not(feature = "jit"))]
            tcx.sess
                .fatal("jit support was disabled when compiling rustc_codegen_cranelift");
        }
    }
}

fn predefine_mono_items<'tcx>(
    cx: &mut crate::CodegenCx<'tcx, impl Module>,
    mono_items: &[(MonoItem<'tcx>, (RLinkage, Visibility))],
) {
    cx.tcx.sess.time("predefine functions", || {
        for &(mono_item, (linkage, visibility)) in mono_items {
            match mono_item {
                MonoItem::Fn(instance) => {
                    let name = cx.tcx.symbol_name(instance).name.to_string();
                    let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name));
                    let sig = get_function_sig(cx.tcx, cx.module.isa().triple(), instance);
                    let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
                    cx.module.declare_function(&name, linkage, &sig).unwrap();
                }
                MonoItem::Static(_) | MonoItem::GlobalAsm(_) => {}
            }
        }
    });
}

fn time<R>(tcx: TyCtxt<'_>, name: &'static str, f: impl FnOnce() -> R) -> R {
    if std::env::var("CG_CLIF_DISPLAY_CG_TIME")
        .as_ref()
        .map(|val| &**val)
        == Ok("1")
    {
        println!("[{:<30}: {}] start", tcx.crate_name(LOCAL_CRATE), name);
        let before = std::time::Instant::now();
        let res = tcx.sess.time(name, f);
        let after = std::time::Instant::now();
        println!(
            "[{:<30}: {}] end time: {:?}",
            tcx.crate_name(LOCAL_CRATE),
            name,
            after - before
        );
        res
    } else {
        tcx.sess.time(name, f)
    }
}
<|endoftext|>


<commit_before><commit_msg>Handle unordered fields in struct patterns<commit_after><|endoftext|>


<commit_before>use core::sync::atomic::{AtomicUsize, Ordering};

use crate::context::timeout;
use crate::device::pic;
use crate::device::serial::{COM1, COM2};
use crate::ipi::{ipi, IpiKind, IpiTarget};
use crate::scheme::debug::debug_input;
use crate::{context, ptrace, time};

//resets to 0 in context::switch()
pub static PIT_TICKS: AtomicUsize = AtomicUsize::new(0);

unsafe fn trigger(irq: u8) {
    extern {
        fn irq_trigger(irq: u8);
    }

    if irq < 16 {
        if irq >= 8 {
            pic::SLAVE.mask_set(irq - 8);
            pic::MASTER.ack();
            pic::SLAVE.ack();
        } else {
            pic::MASTER.mask_set(irq);
            pic::MASTER.ack();
        }
    }

    irq_trigger(irq);
}

pub unsafe fn acknowledge(irq: usize) {
    if irq < 16 {
        if irq >= 8 {
            pic::SLAVE.mask_clear(irq as u8 - 8);
        } else {
            pic::MASTER.mask_clear(irq as u8);
        }
    }
}

interrupt_stack!(pit, stack, {
    // Saves CPU time by not sending IRQ event irq_trigger(0);

    const PIT_RATE: u64 = 2_250_286;

    {
        let mut offset = time::OFFSET.lock();
        let sum = offset.1 + PIT_RATE;
        offset.1 = sum % 1_000_000_000;
        offset.0 += sum / 1_000_000_000;
    }

    pic::MASTER.ack();

    // Wake up other CPUs
    ipi(IpiKind::Pit, IpiTarget::Other);

    // Any better way of doing this?
    timeout::trigger();

    if PIT_TICKS.fetch_add(1, Ordering::SeqCst) >= 10 {
        let _guard = ptrace::set_process_regs(stack);
        let _ = context::switch();
    }
});

interrupt!(keyboard, {
    trigger(1);
});

interrupt!(cascade, {
    // No need to do any operations on cascade
    pic::MASTER.ack();
});

interrupt!(com2, {
    while let Some(c) = COM2.lock().receive() {
        debug_input(c);
    }
    pic::MASTER.ack();
});

interrupt!(com1, {
    while let Some(c) = COM1.lock().receive() {
        debug_input(c);
    }
    pic::MASTER.ack();
});

interrupt!(lpt2, {
    trigger(5);
});

interrupt!(floppy, {
    trigger(6);
});

interrupt!(lpt1, {
    trigger(7);
});

interrupt!(rtc, {
    trigger(8);
});

interrupt!(pci1, {
    trigger(9);
});

interrupt!(pci2, {
    trigger(10);
});

interrupt!(pci3, {
    trigger(11);
});

interrupt!(mouse, {
    trigger(12);
});

interrupt!(fpu, {
    trigger(13);
});

interrupt!(ata1, {
    trigger(14);
});

interrupt!(ata2, {
    trigger(15);
});
<commit_msg>Make PIT_TICKS thread_local<commit_after>use core::sync::atomic::{AtomicUsize, Ordering};

use crate::context::timeout;
use crate::device::pic;
use crate::device::serial::{COM1, COM2};
use crate::ipi::{ipi, IpiKind, IpiTarget};
use crate::scheme::debug::debug_input;
use crate::{context, ptrace, time};

//resets to 0 in context::switch()
#[thread_local]
pub static PIT_TICKS: AtomicUsize = AtomicUsize::new(0);

unsafe fn trigger(irq: u8) {
    extern {
        fn irq_trigger(irq: u8);
    }

    if irq < 16 {
        if irq >= 8 {
            pic::SLAVE.mask_set(irq - 8);
            pic::MASTER.ack();
            pic::SLAVE.ack();
        } else {
            pic::MASTER.mask_set(irq);
            pic::MASTER.ack();
        }
    }

    irq_trigger(irq);
}

pub unsafe fn acknowledge(irq: usize) {
    if irq < 16 {
        if irq >= 8 {
            pic::SLAVE.mask_clear(irq as u8 - 8);
        } else {
            pic::MASTER.mask_clear(irq as u8);
        }
    }
}

interrupt_stack!(pit, stack, {
    // Saves CPU time by not sending IRQ event irq_trigger(0);

    const PIT_RATE: u64 = 2_250_286;

    {
        let mut offset = time::OFFSET.lock();
        let sum = offset.1 + PIT_RATE;
        offset.1 = sum % 1_000_000_000;
        offset.0 += sum / 1_000_000_000;
    }

    pic::MASTER.ack();

    // Wake up other CPUs
    ipi(IpiKind::Pit, IpiTarget::Other);

    // Any better way of doing this?
    timeout::trigger();

    if PIT_TICKS.fetch_add(1, Ordering::SeqCst) >= 10 {
        let _guard = ptrace::set_process_regs(stack);
        let _ = context::switch();
    }
});

interrupt!(keyboard, {
    trigger(1);
});

interrupt!(cascade, {
    // No need to do any operations on cascade
    pic::MASTER.ack();
});

interrupt!(com2, {
    while let Some(c) = COM2.lock().receive() {
        debug_input(c);
    }
    pic::MASTER.ack();
});

interrupt!(com1, {
    while let Some(c) = COM1.lock().receive() {
        debug_input(c);
    }
    pic::MASTER.ack();
});

interrupt!(lpt2, {
    trigger(5);
});

interrupt!(floppy, {
    trigger(6);
});

interrupt!(lpt1, {
    trigger(7);
});

interrupt!(rtc, {
    trigger(8);
});

interrupt!(pci1, {
    trigger(9);
});

interrupt!(pci2, {
    trigger(10);
});

interrupt!(pci3, {
    trigger(11);
});

interrupt!(mouse, {
    trigger(12);
});

interrupt!(fpu, {
    trigger(13);
});

interrupt!(ata1, {
    trigger(14);
});

interrupt!(ata2, {
    trigger(15);
});
<|endoftext|>


<commit_before>use futures_core::{Poll, Stream};
use futures_core::task;
use futures_sink::{Sink};

use core::marker::Unpin;
use core::mem::PinMut;

/// Sink for the `Sink::sink_map_err` combinator.
#[derive(Debug)]
#[must_use = "sinks do nothing unless polled"]
pub struct SinkMapErr<S, F> {
    sink: S,
    f: Option<F>,
}

pub fn new<S, F>(s: S, f: F) -> SinkMapErr<S, F> {
    SinkMapErr { sink: s, f: Some(f) }
}

impl<S: Unpin, F> Unpin for SinkMapErr<S, F> {}

impl<S, F> SinkMapErr<S, F> {
    unsafe_pinned!(sink -> S);
    unsafe_unpinned!(f -> Option<F>);

    /// Get a shared reference to the inner sink.
    pub fn get_ref(&self) -> &S {
        &self.sink
    }

    /// Get a mutable reference to the inner sink.
    pub fn get_mut(&mut self) -> &mut S {
        &mut self.sink
    }

    /// Get a pinned reference to the inner sink.
    pub fn get_pinned_mut<'a>(self: PinMut<'a, Self>) -> PinMut<'a, S> {
        unsafe { PinMut::new_unchecked(&mut PinMut::get_mut_unchecked(self).sink) }
    }

    /// Consumes this combinator, returning the underlying sink.
    ///
    /// Note that this may discard intermediate state of this combinator, so
    /// care should be taken to avoid losing resources when this is called.
    pub fn into_inner(self) -> S {
        self.sink
    }

    fn expect_f(mut self: PinMut<Self>) -> F {
        self.f().take().expect("polled MapErr after completion")
    }
}

impl<S, F, E> Sink for SinkMapErr<S, F>
    where S: Sink,
          F: FnOnce(S::SinkError) -> E,
{
    type SinkItem = S::SinkItem;
    type SinkError = E;

    fn poll_ready(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Result<(), Self::SinkError>> {
        self.sink().poll_ready(cx).map_err(self.expect_f())
    }

    fn start_send(mut self: PinMut<Self>, item: Self::SinkItem) -> Result<(), Self::SinkError> {
        self.sink().start_send(item).map_err(self.expect_f())
    }

    fn poll_flush(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Result<(), Self::SinkError>> {
        self.sink().poll_flush(cx).map_err(self.expect_f())
    }

    fn poll_close(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Result<(), Self::SinkError>> {
        self.sink().poll_close(cx).map_err(self.expect_f())
    }
}

impl<S: Stream, F> Stream for SinkMapErr<S, F> {
    type Item = S::Item;

    fn poll_next(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Option<S::Item>> {
        self.sink().poll_next(cx)
    }
}
<commit_msg>Fix failing test introduced by clippy PR<commit_after>use futures_core::{Poll, Stream};
use futures_core::task;
use futures_sink::{Sink};

use core::marker::Unpin;
use core::mem::PinMut;

/// Sink for the `Sink::sink_map_err` combinator.
#[derive(Debug)]
#[must_use = "sinks do nothing unless polled"]
pub struct SinkMapErr<S, F> {
    sink: S,
    f: Option<F>,
}

pub fn new<S, F>(s: S, f: F) -> SinkMapErr<S, F> {
    SinkMapErr { sink: s, f: Some(f) }
}

impl<S: Unpin, F> Unpin for SinkMapErr<S, F> {}

impl<S, F> SinkMapErr<S, F> {
    unsafe_pinned!(sink -> S);
    unsafe_unpinned!(f -> Option<F>);

    /// Get a shared reference to the inner sink.
    pub fn get_ref(&self) -> &S {
        &self.sink
    }

    /// Get a mutable reference to the inner sink.
    pub fn get_mut(&mut self) -> &mut S {
        &mut self.sink
    }

    /// Get a pinned reference to the inner sink.
    pub fn get_pinned_mut<'a>(self: PinMut<'a, Self>) -> PinMut<'a, S> {
        unsafe { PinMut::new_unchecked(&mut PinMut::get_mut_unchecked(self).sink) }
    }

    /// Consumes this combinator, returning the underlying sink.
    ///
    /// Note that this may discard intermediate state of this combinator, so
    /// care should be taken to avoid losing resources when this is called.
    pub fn into_inner(self) -> S {
        self.sink
    }

    fn expect_f(mut self: PinMut<Self>) -> F {
        self.f().take().expect("polled MapErr after completion")
    }
}

impl<S, F, E> Sink for SinkMapErr<S, F>
    where S: Sink,
          F: FnOnce(S::SinkError) -> E,
{
    type SinkItem = S::SinkItem;
    type SinkError = E;

    fn poll_ready(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Result<(), Self::SinkError>> {
        self.sink().poll_ready(cx).map_err(|e| self.expect_f()(e))
    }

    fn start_send(mut self: PinMut<Self>, item: Self::SinkItem) -> Result<(), Self::SinkError> {
        self.sink().start_send(item).map_err(|e| self.expect_f()(e))
    }

    fn poll_flush(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Result<(), Self::SinkError>> {
        self.sink().poll_flush(cx).map_err(|e| self.expect_f()(e))
    }

    fn poll_close(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Result<(), Self::SinkError>> {
        self.sink().poll_close(cx).map_err(|e| self.expect_f()(e))
    }
}

impl<S: Stream, F> Stream for SinkMapErr<S, F> {
    type Item = S::Item;

    fn poll_next(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Option<S::Item>> {
        self.sink().poll_next(cx)
    }
}
<|endoftext|>