<commit_before>use buffer::Line;

#[deriving(Copy, Show)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl Direction {
    pub fn is_right(&self) -> bool {
        match *self {
            Direction::Right => true,
            _                => false
        }
    }
    pub fn is_left(&self) -> bool {
        match *self {
            Direction::Left => true,
            _               => false
        }
    }
}

pub struct Cursor<'c> {
    /// The number of bytes the cursor is along the line. This must always be on a character
    /// boundary.
    pub offset: uint,
    line: &'c mut Line,
}

impl<'c> Cursor<'c> {
    /// Create a new cursor instance
    pub fn new(line: &'c mut Line, offset: uint) -> Cursor<'c> {
        let mut cursor = Cursor {
            offset: offset,
            line: line,
        };

        // check that the current offset is longer than the length of the line
        let offset = cursor.get_offset();
        let line_length = cursor.get_line().len();
        if offset > line_length {
            cursor.set_offset(line_length);
        }
        cursor
    }

    pub fn get_position(&self) -> (uint, uint) {
        (self.offset, self.get_linenum())
    }

    pub fn get_linenum(&self) -> uint {
        self.line.linenum
    }

    pub fn get_offset(&self) -> uint {
        self.offset
    }

    pub fn get_visible_offset(&self) -> uint {
        ::utils::str_width(self.get_line().data.slice_to(self.get_offset()), false, 4)
    }

    pub fn set_offset(&mut self, offset: uint) {
        self.offset = offset;
    }

    /// Moves the cursor forward one character.
    ///
    /// This can’t simply be `self.offset += 1`, because not all UTF-8 codepoints are exactly one
    /// byte long. This function calculates the width of the current codepoint and increments the
    /// offset by that width, ensuring that the cursor will always be on a character boundary.
    pub fn inc_offset(&mut self) {
        let range = self.get_line().data.char_range_at(self.offset);
        self.set_offset(range.next);
    }

    /// Moves the cursor back one character.
    ///
    /// See `inc_offset` for why this method is needed.
    pub fn dec_offset(&mut self) {
        let range = self.get_line().data.char_range_at_reverse(self.offset);
        self.set_offset(range.next);
    }

    pub fn get_line(&self) -> &Line {
        &*self.line
    }

    pub fn get_line_mut(&mut self) -> &mut Line {
        self.line
    }

    pub fn get_line_length(&self) -> uint {
        self.get_line().len()
    }

    pub fn delete_backward_char(&mut self) {
        let offset = self.get_offset();
        let range = self.get_line().data.char_range_at_reverse(self.offset);
        let back = self.offset - range.next;
        self.dec_offset();
        self.get_line_mut().data.remove(offset-back);
    }

    pub fn delete_forward_char(&mut self) {
        let offset = self.get_offset();
        self.get_line_mut().data.remove(offset);
    }

    pub fn insert_char(&mut self, ch: char) {
        let offset = self.get_offset();
        self.get_line_mut().data.insert(offset, ch);
        self.inc_offset();
    }

    pub fn move_right(&mut self) {
        let line_len = self.get_line().len();
        let current_offset = self.get_offset();
        if line_len > current_offset {
            self.inc_offset();
        }
    }

    pub fn move_left(&mut self) {
        let current_offset = self.get_offset();
        if current_offset > 0 {
            self.dec_offset();
        }
    }

    pub fn get_status_text(&self) -> String {
        let (offset, line_num) = self.get_position();
        format!("({}, {})", offset, line_num)
    }
}

#[cfg(test)]
mod tests {

    use cursor::Cursor;
    use buffer::Line;
    use utils::data_from_str;

    fn setup_cursor<F>(mut f: F) where F: FnMut(Cursor) {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);
        f(cursor);
    }

    #[test]
    fn test_moving_right() {
        setup_cursor( |mut cursor| {
            assert_eq!(cursor.offset, 0);
            cursor.move_right();
            assert_eq!(cursor.offset, 1);
        });
    }

    #[test]
    fn test_moving_left() {
        setup_cursor( |mut cursor| {
            cursor.set_offset(1);

            assert_eq!(cursor.offset, 1);
            cursor.move_left();
            assert_eq!(cursor.offset, 0);
        });
    }

    #[test]
    fn test_get_position() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);
        assert_eq!(cursor.get_position(), (0, 1));
    }

    #[test]
    fn test_get_linenum() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);

        assert_eq!(cursor.get_linenum(), 1);
    }

    #[test]
    fn test_get_offset() {
        setup_cursor( |cursor| {
            assert_eq!(cursor.get_offset(), 0)
        });
    }

    #[test]
    fn test_set_offset() {
        setup_cursor( |mut cursor| {
            cursor.set_offset(3);

            assert_eq!(cursor.offset, 3);
        });
    }

    #[test]
    fn test_moving_to_end_of_line_when_set() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 10);

        assert_eq!(cursor.offset, 4);
    }

    #[test]
    fn test_get_line_length() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);

        assert_eq!(cursor.get_line_length(), 4);
    }

    #[test]
    fn test_delete_backward_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 1);
            cursor.delete_backward_char();
        }

        assert_eq!(line.data, data_from_str("est"));
    }

    #[test]
    fn test_delete_forward_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 0);
            cursor.delete_forward_char();
        }

        assert_eq!(line.data, data_from_str("est"));
    }

    #[test]
    fn test_insert_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 0);
            cursor.insert_char('x');
        }

        assert_eq!(line.data, data_from_str("xtest"));
    }

    #[test]
    fn test_get_status_text() {
        setup_cursor( |cursor| {
            assert_eq!(cursor.get_status_text(), "(0, 1)".to_string());
        } );
    }

}
<commit_msg>Add a test<commit_after>use buffer::Line;

#[deriving(Copy, Show)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl Direction {
    pub fn is_right(&self) -> bool {
        match *self {
            Direction::Right => true,
            _                => false
        }
    }
    pub fn is_left(&self) -> bool {
        match *self {
            Direction::Left => true,
            _               => false
        }
    }
}

pub struct Cursor<'c> {
    /// The number of bytes the cursor is along the line. This must always be on a character
    /// boundary.
    pub offset: uint,
    line: &'c mut Line,
}

impl<'c> Cursor<'c> {
    /// Create a new cursor instance
    pub fn new(line: &'c mut Line, offset: uint) -> Cursor<'c> {
        let mut cursor = Cursor {
            offset: offset,
            line: line,
        };

        // check that the current offset is longer than the length of the line
        let offset = cursor.get_offset();
        let line_length = cursor.get_line().len();
        if offset > line_length {
            cursor.set_offset(line_length);
        }
        cursor
    }

    pub fn get_position(&self) -> (uint, uint) {
        (self.offset, self.get_linenum())
    }

    pub fn get_linenum(&self) -> uint {
        self.line.linenum
    }

    pub fn get_offset(&self) -> uint {
        self.offset
    }

    pub fn get_visible_offset(&self) -> uint {
        ::utils::str_width(self.get_line().data.slice_to(self.get_offset()), false, 4)
    }

    pub fn set_offset(&mut self, offset: uint) {
        self.offset = offset;
    }

    /// Moves the cursor forward one character.
    ///
    /// This can’t simply be `self.offset += 1`, because not all UTF-8 codepoints are exactly one
    /// byte long. This function calculates the width of the current codepoint and increments the
    /// offset by that width, ensuring that the cursor will always be on a character boundary.
    pub fn inc_offset(&mut self) {
        let range = self.get_line().data.char_range_at(self.offset);
        self.set_offset(range.next);
    }

    /// Moves the cursor back one character.
    ///
    /// See `inc_offset` for why this method is needed.
    pub fn dec_offset(&mut self) {
        let range = self.get_line().data.char_range_at_reverse(self.offset);
        self.set_offset(range.next);
    }

    pub fn get_line(&self) -> &Line {
        &*self.line
    }

    pub fn get_line_mut(&mut self) -> &mut Line {
        self.line
    }

    pub fn get_line_length(&self) -> uint {
        self.get_line().len()
    }

    pub fn delete_backward_char(&mut self) {
        let offset = self.get_offset();
        let range = self.get_line().data.char_range_at_reverse(self.offset);
        let back = self.offset - range.next;
        self.dec_offset();
        self.get_line_mut().data.remove(offset-back);
    }

    pub fn delete_forward_char(&mut self) {
        let offset = self.get_offset();
        self.get_line_mut().data.remove(offset);
    }

    pub fn insert_char(&mut self, ch: char) {
        let offset = self.get_offset();
        self.get_line_mut().data.insert(offset, ch);
        self.inc_offset();
    }

    pub fn move_right(&mut self) {
        let line_len = self.get_line().len();
        let current_offset = self.get_offset();
        if line_len > current_offset {
            self.inc_offset();
        }
    }

    pub fn move_left(&mut self) {
        let current_offset = self.get_offset();
        if current_offset > 0 {
            self.dec_offset();
        }
    }

    pub fn get_status_text(&self) -> String {
        let (offset, line_num) = self.get_position();
        format!("({}, {})", offset, line_num)
    }
}

#[cfg(test)]
mod tests {

    use cursor::Cursor;
    use buffer::Line;
    use utils::data_from_str;

    fn setup_cursor<F>(mut f: F) where F: FnMut(Cursor) {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);
        f(cursor);
    }

    #[test]
    fn test_moving_right() {
        setup_cursor( |mut cursor| {
            assert_eq!(cursor.offset, 0);
            cursor.move_right();
            assert_eq!(cursor.offset, 1);
        });
    }

    #[test]
    fn test_moving_left() {
        setup_cursor( |mut cursor| {
            cursor.set_offset(1);

            assert_eq!(cursor.offset, 1);
            cursor.move_left();
            assert_eq!(cursor.offset, 0);
        });
    }

    #[test]
    fn test_get_position() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);
        assert_eq!(cursor.get_position(), (0, 1));
    }

    #[test]
    fn test_get_linenum() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);

        assert_eq!(cursor.get_linenum(), 1);
    }

    #[test]
    fn test_get_offset() {
        setup_cursor( |cursor| {
            assert_eq!(cursor.get_offset(), 0)
        });
    }

    #[test]
    fn test_set_offset() {
        setup_cursor( |mut cursor| {
            cursor.set_offset(3);

            assert_eq!(cursor.offset, 3);
        });
    }

    #[test]
    fn test_moving_to_end_of_line_when_set() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 10);

        assert_eq!(cursor.offset, 4);
    }

    #[test]
    fn test_get_line_length() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);

        assert_eq!(cursor.get_line_length(), 4);
    }

    #[test]
    fn test_delete_backward_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 1);
            cursor.delete_backward_char();
        }

        assert_eq!(line.data, data_from_str("est"));
    }

    #[test]
    fn test_delete_forward_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 0);
            cursor.delete_forward_char();
        }

        assert_eq!(line.data, data_from_str("est"));
    }

    #[test]
    fn test_insert_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 0);
            cursor.insert_char('x');
        }

        assert_eq!(line.data, data_from_str("xtest"));
    }

    #[test]
    fn test_get_status_text() {
        setup_cursor( |cursor| {
            assert_eq!(cursor.get_status_text(), "(0, 1)".to_string());
        } );
    }

    #[test]
    fn test_tab_width() {
        let ref mut line = Line::new(data_from_str("a\ttest"), 1);
        let cursor = Cursor::new(line, 2);
        assert_eq!(cursor.get_visible_offset(), 4)
    }

}
<|endoftext|>


<commit_before>//! Intermediate representation for C/C++ functions and methods.

use super::context::{BindgenContext, ItemId};
use super::dot::DotAttributes;
use super::item::Item;
use super::traversal::{EdgeKind, Trace, Tracer};
use super::ty::TypeKind;
use clang;
use clang_sys::CXCallingConv;
use ir::derive::CanDeriveDebug;
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
use std::io;
use syntax::abi;

/// A function declaration, with a signature, arguments, and argument names.
///
/// The argument names vector must be the same length as the ones in the
/// signature.
#[derive(Debug)]
pub struct Function {
    /// The name of this function.
    name: String,

    /// The mangled name, that is, the symbol.
    mangled_name: Option<String>,

    /// The id pointing to the current function signature.
    signature: ItemId,

    /// The doc comment on the function, if any.
    comment: Option<String>,
}

impl Function {
    /// Construct a new function.
    pub fn new(name: String,
               mangled_name: Option<String>,
               sig: ItemId,
               comment: Option<String>)
               -> Self {
        Function {
            name: name,
            mangled_name: mangled_name,
            signature: sig,
            comment: comment,
        }
    }

    /// Get this function's name.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Get this function's name.
    pub fn mangled_name(&self) -> Option<&str> {
        self.mangled_name.as_ref().map(|n| &**n)
    }

    /// Get this function's signature.
    pub fn signature(&self) -> ItemId {
        self.signature
    }
}

impl DotAttributes for Function {
    fn dot_attributes<W>(&self,
                         _ctx: &BindgenContext,
                         out: &mut W)
                         -> io::Result<()>
        where W: io::Write,
    {
        if let Some(ref mangled) = self.mangled_name {
            try!(writeln!(out,
                          "
mangled name	{}
",
                          mangled));
        }

        Ok(())
    }
}

/// A function signature.
#[derive(Debug)]
pub struct FunctionSig {
    /// The return type of the function.
    return_type: ItemId,

    /// The type of the arguments, optionally with the name of the argument when
    /// declared.
    argument_types: Vec<(Option<String>, ItemId)>,

    /// Whether this function is variadic.
    is_variadic: bool,

    /// The ABI of this function.
    abi: Option<abi::Abi>,
}

fn get_abi(cc: CXCallingConv) -> Option<abi::Abi> {
    use clang_sys::*;
    match cc {
        CXCallingConv_Default => Some(abi::Abi::C),
        CXCallingConv_C => Some(abi::Abi::C),
        CXCallingConv_X86StdCall => Some(abi::Abi::Stdcall),
        CXCallingConv_X86FastCall => Some(abi::Abi::Fastcall),
        CXCallingConv_AAPCS => Some(abi::Abi::Aapcs),
        CXCallingConv_X86_64Win64 => Some(abi::Abi::Win64),
        CXCallingConv_Invalid => None,
        other => panic!("unsupported calling convention: {:?}", other),
    }
}

/// Get the mangled name for the cursor's referent.
pub fn cursor_mangling(ctx: &BindgenContext,
                       cursor: &clang::Cursor)
                       -> Option<String> {
    use clang_sys;
    if !ctx.options().enable_mangling {
        return None;
    }

    // We early return here because libclang may crash in some case
    // if we pass in a variable inside a partial specialized template.
    // See servo/rust-bindgen#67, and servo/rust-bindgen#462.
    if cursor.is_in_non_fully_specialized_template() {
        return None;
    }

    if let Ok(mut manglings) = cursor.cxx_manglings() {
        if let Some(m) = manglings.pop() {
            return Some(m);
        }
    }

    let mut mangling = cursor.mangling();
    if mangling.is_empty() {
        return None;
    }

    // Try to undo backend linkage munging (prepended _, generally)
    //
    // TODO(emilio): This is wrong when the target system is not the host
    // system. See https://github.com/servo/rust-bindgen/issues/593
    if cfg!(target_os = "macos") {
        mangling.remove(0);
    }

    if cursor.kind() == clang_sys::CXCursor_Destructor {
        // With old (3.8-) libclang versions, and the Itanium ABI, clang returns
        // the "destructor group 0" symbol, which means that it'll try to free
        // memory, which definitely isn't what we want.
        //
        // Explicitly force the destructor group 1 symbol.
        //
        // See http://refspecs.linuxbase.org/cxxabi-1.83.html#mangling-special
        // for the reference, and http://stackoverflow.com/a/6614369/1091587 for
        // a more friendly explanation.
        //
        // We don't need to do this for constructors since clang seems to always
        // have returned the C1 constructor.
        //
        // FIXME(emilio): Can a legit symbol in other ABIs end with this string?
        // I don't think so, but if it can this would become a linker error
        // anyway, not an invalid free at runtime.
        //
        // TODO(emilio, #611): Use cpp_demangle if this becomes nastier with
        // time.
        if mangling.ends_with("D0Ev") {
            let new_len = mangling.len() - 4;
            mangling.truncate(new_len);
            mangling.push_str("D1Ev");
        }
    }

    Some(mangling)
}

impl FunctionSig {
    /// Construct a new function signature.
    pub fn new(return_type: ItemId,
               arguments: Vec<(Option<String>, ItemId)>,
               is_variadic: bool,
               abi: Option<abi::Abi>)
               -> Self {
        FunctionSig {
            return_type: return_type,
            argument_types: arguments,
            is_variadic: is_variadic,
            abi: abi,
        }
    }

    /// Construct a new function signature from the given Clang type.
    pub fn from_ty(ty: &clang::Type,
                   cursor: &clang::Cursor,
                   ctx: &mut BindgenContext)
                   -> Result<Self, ParseError> {
        use clang_sys::*;
        debug!("FunctionSig::from_ty {:?} {:?}", ty, cursor);

        // Skip function templates
        if cursor.kind() == CXCursor_FunctionTemplate {
            return Err(ParseError::Continue);
        }

        // Don't parse operatorxx functions in C++
        let spelling = cursor.spelling();
        if spelling.starts_with("operator") {
            return Err(ParseError::Continue);
        }

        let cursor = if cursor.is_valid() {
            *cursor
        } else {
            ty.declaration()
        };

        let mut args: Vec<_> = match cursor.kind() {
            CXCursor_FunctionDecl |
            CXCursor_Constructor |
            CXCursor_CXXMethod |
            CXCursor_ObjCInstanceMethodDecl |
            CXCursor_ObjCClassMethodDecl => {
                // For CXCursor_FunctionDecl, cursor.args() is the reliable way
                // to get parameter names and types.
                cursor.args()
                    .unwrap()
                    .iter()
                    .map(|arg| {
                        let arg_ty = arg.cur_type();
                        let name = arg.spelling();
                        let name =
                            if name.is_empty() { None } else { Some(name) };
                        let ty = Item::from_ty_or_ref(arg_ty, *arg, None, ctx);
                        (name, ty)
                    })
                    .collect()
            }
            _ => {
                // For non-CXCursor_FunctionDecl, visiting the cursor's children
                // is the only reliable way to get parameter names.
                let mut args = vec![];
                cursor.visit(|c| {
                    if c.kind() == CXCursor_ParmDecl {
                        let ty =
                            Item::from_ty_or_ref(c.cur_type(), c, None, ctx);
                        let name = c.spelling();
                        let name =
                            if name.is_empty() { None } else { Some(name) };
                        args.push((name, ty));
                    }
                    CXChildVisit_Continue
                });
                args
            }
        };

        let is_method = cursor.kind() == CXCursor_CXXMethod;
        let is_constructor = cursor.kind() == CXCursor_Constructor;
        let is_destructor = cursor.kind() == CXCursor_Destructor;
        if (is_constructor || is_destructor || is_method) &&
           cursor.lexical_parent() != cursor.semantic_parent() {
            // Only parse constructors once.
            return Err(ParseError::Continue);
        }

        if is_method || is_constructor || is_destructor {
            let is_const = is_method && cursor.method_is_const();
            let is_virtual = is_method && cursor.method_is_virtual();
            let is_static = is_method && cursor.method_is_static();
            if !is_static && !is_virtual {
                let class = Item::parse(cursor.semantic_parent(), None, ctx)
                    .expect("Expected to parse the class");
                let ptr =
                    Item::builtin_type(TypeKind::Pointer(class), is_const, ctx);
                args.insert(0, (Some("this".into()), ptr));
            } else if is_virtual {
                let void = Item::builtin_type(TypeKind::Void, false, ctx);
                let ptr =
                    Item::builtin_type(TypeKind::Pointer(void), false, ctx);
                args.insert(0, (Some("this".into()), ptr));
            }
        }

        let ty_ret_type = if cursor.kind() == CXCursor_ObjCInstanceMethodDecl ||
                             cursor.kind() == CXCursor_ObjCClassMethodDecl {
            try!(ty.ret_type()
                   .or_else(|| cursor.ret_type())
                   .ok_or(ParseError::Continue))
        } else {
            try!(ty.ret_type().ok_or(ParseError::Continue))
        };
        let ret = Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx);
        let abi = get_abi(ty.call_conv());

        if abi.is_none() {
            assert!(cursor.kind() == CXCursor_ObjCInstanceMethodDecl ||
                    cursor.kind() == CXCursor_ObjCClassMethodDecl,
                       "Invalid ABI for function signature")
        }

        Ok(Self::new(ret, args, ty.is_variadic(), abi))
    }

    /// Get this function signature's return type.
    pub fn return_type(&self) -> ItemId {
        self.return_type
    }

    /// Get this function signature's argument (name, type) pairs.
    pub fn argument_types(&self) -> &[(Option<String>, ItemId)] {
        &self.argument_types
    }

    /// Get this function signature's ABI.
    pub fn abi(&self) -> Option<abi::Abi> {
        self.abi
    }

    /// Is this function signature variadic?
    pub fn is_variadic(&self) -> bool {
        // Clang reports some functions as variadic when they *might* be
        // variadic. We do the argument check because rust doesn't codegen well
        // variadic functions without an initial argument.
        self.is_variadic && !self.argument_types.is_empty()
    }
}

impl ClangSubItemParser for Function {
    fn parse(cursor: clang::Cursor,
             context: &mut BindgenContext)
             -> Result<ParseResult<Self>, ParseError> {
        use clang_sys::*;
        match cursor.kind() {
            CXCursor_FunctionDecl |
            CXCursor_Constructor |
            CXCursor_Destructor |
            CXCursor_CXXMethod => {}
            _ => return Err(ParseError::Continue),
        };

        debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type());

        let visibility = cursor.visibility();
        if visibility != CXVisibility_Default {
            return Err(ParseError::Continue);
        }

        if cursor.access_specifier() == CX_CXXPrivate {
            return Err(ParseError::Continue);
        }

        if !context.options().generate_inline_functions &&
            cursor.is_inlined_function() {
            return Err(ParseError::Continue);
        }

        let linkage = cursor.linkage();
        if linkage != CXLinkage_External &&
           linkage != CXLinkage_UniqueExternal {
            return Err(ParseError::Continue);
        }

        // Grab the signature using Item::from_ty.
        let sig =
            try!(Item::from_ty(&cursor.cur_type(), cursor, None, context));

        let mut name = cursor.spelling();
        assert!(!name.is_empty(), "Empty function name?");

        if cursor.kind() == CXCursor_Destructor {
            // Remove the leading `~`. The alternative to this is special-casing
            // code-generation for destructor functions, which seems less than
            // ideal.
            if name.starts_with('~') {
                name.remove(0);
            }

            // Add a suffix to avoid colliding with constructors. This would be
            // technically fine (since we handle duplicated functions/methods),
            // but seems easy enough to handle it here.
            name.push_str("_destructor");
        }

        let mut mangled_name = cursor_mangling(context, &cursor);
        if mangled_name.as_ref() == Some(&name) {
            mangled_name = None;
        }

        let comment = cursor.raw_comment();

        let function = Self::new(name, mangled_name, sig, comment);
        Ok(ParseResult::New(function, Some(cursor)))
    }
}

impl Trace for FunctionSig {
    type Extra = ();

    fn trace<T>(&self, _: &BindgenContext, tracer: &mut T, _: &())
        where T: Tracer,
    {
        tracer.visit_kind(self.return_type(), EdgeKind::FunctionReturn);

        for &(_, ty) in self.argument_types() {
            tracer.visit_kind(ty, EdgeKind::FunctionParameter);
        }
    }
}

// Function pointers follow special rules, see:
//
// https://github.com/servo/rust-bindgen/issues/547,
// https://github.com/rust-lang/rust/issues/38848,
// and https://github.com/rust-lang/rust/issues/40158
//
// Note that copy is always derived, so we don't need to implement it.
impl CanDeriveDebug for FunctionSig {
    type Extra = ();

    fn can_derive_debug(&self, _ctx: &BindgenContext, _: ()) -> bool {
        const RUST_DERIVE_FUNPTR_LIMIT: usize = 12;
        if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
            return false;
        }

        match self.abi {
            Some(abi::Abi::C) |
            None => true,
            _ => false,
        }
    }
}
<commit_msg>Auto merge of #717 - photoszzt:fix_osx_mangling, r=emilio<commit_after>//! Intermediate representation for C/C++ functions and methods.

use super::context::{BindgenContext, ItemId};
use super::dot::DotAttributes;
use super::item::Item;
use super::traversal::{EdgeKind, Trace, Tracer};
use super::ty::TypeKind;
use clang;
use clang_sys::CXCallingConv;
use ir::derive::CanDeriveDebug;
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
use std::io;
use syntax::abi;

/// A function declaration, with a signature, arguments, and argument names.
///
/// The argument names vector must be the same length as the ones in the
/// signature.
#[derive(Debug)]
pub struct Function {
    /// The name of this function.
    name: String,

    /// The mangled name, that is, the symbol.
    mangled_name: Option<String>,

    /// The id pointing to the current function signature.
    signature: ItemId,

    /// The doc comment on the function, if any.
    comment: Option<String>,
}

impl Function {
    /// Construct a new function.
    pub fn new(name: String,
               mangled_name: Option<String>,
               sig: ItemId,
               comment: Option<String>)
               -> Self {
        Function {
            name: name,
            mangled_name: mangled_name,
            signature: sig,
            comment: comment,
        }
    }

    /// Get this function's name.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Get this function's name.
    pub fn mangled_name(&self) -> Option<&str> {
        self.mangled_name.as_ref().map(|n| &**n)
    }

    /// Get this function's signature.
    pub fn signature(&self) -> ItemId {
        self.signature
    }
}

impl DotAttributes for Function {
    fn dot_attributes<W>(&self,
                         _ctx: &BindgenContext,
                         out: &mut W)
                         -> io::Result<()>
        where W: io::Write,
    {
        if let Some(ref mangled) = self.mangled_name {
            try!(writeln!(out,
                          "
mangled name	{}
",
                          mangled));
        }

        Ok(())
    }
}

/// A function signature.
#[derive(Debug)]
pub struct FunctionSig {
    /// The return type of the function.
    return_type: ItemId,

    /// The type of the arguments, optionally with the name of the argument when
    /// declared.
    argument_types: Vec<(Option<String>, ItemId)>,

    /// Whether this function is variadic.
    is_variadic: bool,

    /// The ABI of this function.
    abi: Option<abi::Abi>,
}

fn get_abi(cc: CXCallingConv) -> Option<abi::Abi> {
    use clang_sys::*;
    match cc {
        CXCallingConv_Default => Some(abi::Abi::C),
        CXCallingConv_C => Some(abi::Abi::C),
        CXCallingConv_X86StdCall => Some(abi::Abi::Stdcall),
        CXCallingConv_X86FastCall => Some(abi::Abi::Fastcall),
        CXCallingConv_AAPCS => Some(abi::Abi::Aapcs),
        CXCallingConv_X86_64Win64 => Some(abi::Abi::Win64),
        CXCallingConv_Invalid => None,
        other => panic!("unsupported calling convention: {:?}", other),
    }
}

// Mac os needs __ for mangled symbols but rust will automatically prepend the extra _.
// We need to make sure that we don't include __ because rust will turn into ___.
//
// TODO(emilio): This is wrong when the target system is not the host
// system. See https://github.com/servo/rust-bindgen/issues/593
fn macos_mangling(symbol: &mut String) {
    if cfg!(target_os = "macos") && symbol.starts_with("_") {
        symbol.remove(0);
    }
}

/// Get the mangled name for the cursor's referent.
pub fn cursor_mangling(ctx: &BindgenContext,
                       cursor: &clang::Cursor)
                       -> Option<String> {
    use clang_sys;
    if !ctx.options().enable_mangling {
        return None;
    }

    // We early return here because libclang may crash in some case
    // if we pass in a variable inside a partial specialized template.
    // See servo/rust-bindgen#67, and servo/rust-bindgen#462.
    if cursor.is_in_non_fully_specialized_template() {
        return None;
    }

    if let Ok(mut manglings) = cursor.cxx_manglings() {
        if let Some(mut m) = manglings.pop() {
            macos_mangling(&mut m);
            return Some(m);
        }
    }

    let mut mangling = cursor.mangling();
    if mangling.is_empty() {
        return None;
    }

    macos_mangling(&mut mangling);

    if cursor.kind() == clang_sys::CXCursor_Destructor {
        // With old (3.8-) libclang versions, and the Itanium ABI, clang returns
        // the "destructor group 0" symbol, which means that it'll try to free
        // memory, which definitely isn't what we want.
        //
        // Explicitly force the destructor group 1 symbol.
        //
        // See http://refspecs.linuxbase.org/cxxabi-1.83.html#mangling-special
        // for the reference, and http://stackoverflow.com/a/6614369/1091587 for
        // a more friendly explanation.
        //
        // We don't need to do this for constructors since clang seems to always
        // have returned the C1 constructor.
        //
        // FIXME(emilio): Can a legit symbol in other ABIs end with this string?
        // I don't think so, but if it can this would become a linker error
        // anyway, not an invalid free at runtime.
        //
        // TODO(emilio, #611): Use cpp_demangle if this becomes nastier with
        // time.
        if mangling.ends_with("D0Ev") {
            let new_len = mangling.len() - 4;
            mangling.truncate(new_len);
            mangling.push_str("D1Ev");
        }
    }

    Some(mangling)
}

impl FunctionSig {
    /// Construct a new function signature.
    pub fn new(return_type: ItemId,
               arguments: Vec<(Option<String>, ItemId)>,
               is_variadic: bool,
               abi: Option<abi::Abi>)
               -> Self {
        FunctionSig {
            return_type: return_type,
            argument_types: arguments,
            is_variadic: is_variadic,
            abi: abi,
        }
    }

    /// Construct a new function signature from the given Clang type.
    pub fn from_ty(ty: &clang::Type,
                   cursor: &clang::Cursor,
                   ctx: &mut BindgenContext)
                   -> Result<Self, ParseError> {
        use clang_sys::*;
        debug!("FunctionSig::from_ty {:?} {:?}", ty, cursor);

        // Skip function templates
        if cursor.kind() == CXCursor_FunctionTemplate {
            return Err(ParseError::Continue);
        }

        // Don't parse operatorxx functions in C++
        let spelling = cursor.spelling();
        if spelling.starts_with("operator") {
            return Err(ParseError::Continue);
        }

        let cursor = if cursor.is_valid() {
            *cursor
        } else {
            ty.declaration()
        };

        let mut args: Vec<_> = match cursor.kind() {
            CXCursor_FunctionDecl |
            CXCursor_Constructor |
            CXCursor_CXXMethod |
            CXCursor_ObjCInstanceMethodDecl |
            CXCursor_ObjCClassMethodDecl => {
                // For CXCursor_FunctionDecl, cursor.args() is the reliable way
                // to get parameter names and types.
                cursor.args()
                    .unwrap()
                    .iter()
                    .map(|arg| {
                        let arg_ty = arg.cur_type();
                        let name = arg.spelling();
                        let name =
                            if name.is_empty() { None } else { Some(name) };
                        let ty = Item::from_ty_or_ref(arg_ty, *arg, None, ctx);
                        (name, ty)
                    })
                    .collect()
            }
            _ => {
                // For non-CXCursor_FunctionDecl, visiting the cursor's children
                // is the only reliable way to get parameter names.
                let mut args = vec![];
                cursor.visit(|c| {
                    if c.kind() == CXCursor_ParmDecl {
                        let ty =
                            Item::from_ty_or_ref(c.cur_type(), c, None, ctx);
                        let name = c.spelling();
                        let name =
                            if name.is_empty() { None } else { Some(name) };
                        args.push((name, ty));
                    }
                    CXChildVisit_Continue
                });
                args
            }
        };

        let is_method = cursor.kind() == CXCursor_CXXMethod;
        let is_constructor = cursor.kind() == CXCursor_Constructor;
        let is_destructor = cursor.kind() == CXCursor_Destructor;
        if (is_constructor || is_destructor || is_method) &&
           cursor.lexical_parent() != cursor.semantic_parent() {
            // Only parse constructors once.
            return Err(ParseError::Continue);
        }

        if is_method || is_constructor || is_destructor {
            let is_const = is_method && cursor.method_is_const();
            let is_virtual = is_method && cursor.method_is_virtual();
            let is_static = is_method && cursor.method_is_static();
            if !is_static && !is_virtual {
                let class = Item::parse(cursor.semantic_parent(), None, ctx)
                    .expect("Expected to parse the class");
                let ptr =
                    Item::builtin_type(TypeKind::Pointer(class), is_const, ctx);
                args.insert(0, (Some("this".into()), ptr));
            } else if is_virtual {
                let void = Item::builtin_type(TypeKind::Void, false, ctx);
                let ptr =
                    Item::builtin_type(TypeKind::Pointer(void), false, ctx);
                args.insert(0, (Some("this".into()), ptr));
            }
        }

        let ty_ret_type = if cursor.kind() == CXCursor_ObjCInstanceMethodDecl ||
                             cursor.kind() == CXCursor_ObjCClassMethodDecl {
            try!(ty.ret_type()
                   .or_else(|| cursor.ret_type())
                   .ok_or(ParseError::Continue))
        } else {
            try!(ty.ret_type().ok_or(ParseError::Continue))
        };
        let ret = Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx);
        let abi = get_abi(ty.call_conv());

        if abi.is_none() {
            assert!(cursor.kind() == CXCursor_ObjCInstanceMethodDecl ||
                    cursor.kind() == CXCursor_ObjCClassMethodDecl,
                       "Invalid ABI for function signature")
        }

        Ok(Self::new(ret, args, ty.is_variadic(), abi))
    }

    /// Get this function signature's return type.
    pub fn return_type(&self) -> ItemId {
        self.return_type
    }

    /// Get this function signature's argument (name, type) pairs.
    pub fn argument_types(&self) -> &[(Option<String>, ItemId)] {
        &self.argument_types
    }

    /// Get this function signature's ABI.
    pub fn abi(&self) -> Option<abi::Abi> {
        self.abi
    }

    /// Is this function signature variadic?
    pub fn is_variadic(&self) -> bool {
        // Clang reports some functions as variadic when they *might* be
        // variadic. We do the argument check because rust doesn't codegen well
        // variadic functions without an initial argument.
        self.is_variadic && !self.argument_types.is_empty()
    }
}

impl ClangSubItemParser for Function {
    fn parse(cursor: clang::Cursor,
             context: &mut BindgenContext)
             -> Result<ParseResult<Self>, ParseError> {
        use clang_sys::*;
        match cursor.kind() {
            CXCursor_FunctionDecl |
            CXCursor_Constructor |
            CXCursor_Destructor |
            CXCursor_CXXMethod => {}
            _ => return Err(ParseError::Continue),
        };

        debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type());

        let visibility = cursor.visibility();
        if visibility != CXVisibility_Default {
            return Err(ParseError::Continue);
        }

        if cursor.access_specifier() == CX_CXXPrivate {
            return Err(ParseError::Continue);
        }

        if !context.options().generate_inline_functions &&
            cursor.is_inlined_function() {
            return Err(ParseError::Continue);
        }

        let linkage = cursor.linkage();
        if linkage != CXLinkage_External &&
           linkage != CXLinkage_UniqueExternal {
            return Err(ParseError::Continue);
        }

        // Grab the signature using Item::from_ty.
        let sig =
            try!(Item::from_ty(&cursor.cur_type(), cursor, None, context));

        let mut name = cursor.spelling();
        assert!(!name.is_empty(), "Empty function name?");

        if cursor.kind() == CXCursor_Destructor {
            // Remove the leading `~`. The alternative to this is special-casing
            // code-generation for destructor functions, which seems less than
            // ideal.
            if name.starts_with('~') {
                name.remove(0);
            }

            // Add a suffix to avoid colliding with constructors. This would be
            // technically fine (since we handle duplicated functions/methods),
            // but seems easy enough to handle it here.
            name.push_str("_destructor");
        }

        let mut mangled_name = cursor_mangling(context, &cursor);
        if mangled_name.as_ref() == Some(&name) {
            mangled_name = None;
        }

        let comment = cursor.raw_comment();

        let function = Self::new(name, mangled_name, sig, comment);
        Ok(ParseResult::New(function, Some(cursor)))
    }
}

impl Trace for FunctionSig {
    type Extra = ();

    fn trace<T>(&self, _: &BindgenContext, tracer: &mut T, _: &())
        where T: Tracer,
    {
        tracer.visit_kind(self.return_type(), EdgeKind::FunctionReturn);

        for &(_, ty) in self.argument_types() {
            tracer.visit_kind(ty, EdgeKind::FunctionParameter);
        }
    }
}

// Function pointers follow special rules, see:
//
// https://github.com/servo/rust-bindgen/issues/547,
// https://github.com/rust-lang/rust/issues/38848,
// and https://github.com/rust-lang/rust/issues/40158
//
// Note that copy is always derived, so we don't need to implement it.
impl CanDeriveDebug for FunctionSig {
    type Extra = ();

    fn can_derive_debug(&self, _ctx: &BindgenContext, _: ()) -> bool {
        const RUST_DERIVE_FUNPTR_LIMIT: usize = 12;
        if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
            return false;
        }

        match self.abi {
            Some(abi::Abi::C) |
            None => true,
            _ => false,
        }
    }
}
<|endoftext|>


<commit_before>
use super::internal::*;
use super::*;
use std::cmp;
use std::iter;

#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct ZipEq<A: IndexedParallelIterator, B: IndexedParallelIterator> {
    zip: Zip<A, B>
}

/// Create a new `ZipEq` iterator.
///
/// NB: a free fn because it is NOT part of the end-user API.
#[inline]
pub fn new<A, B>(a: A, b: B) -> ZipEq<A, B>
    where A: IndexedParallelIterator,
          B: IndexedParallelIterator
{
    ZipEq { zip: super::zip::new(a, b) }
}

impl<A, B> ParallelIterator for ZipEq<A, B>
    where A: IndexedParallelIterator,
          B: IndexedParallelIterator
{
    type Item = (A::Item, B::Item);

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge(self.zip, consumer)
    }

    fn opt_len(&mut self) -> Option<usize> {
        Some(self.zip.len())
    }
}

impl<A, B> IndexedParallelIterator for ZipEq<A, B>
    where A: IndexedParallelIterator,
          B: IndexedParallelIterator
{
    fn drive<C>(self, consumer: C) -> C::Result
        where C: Consumer<Self::Item>
    {
        bridge(self.zip, consumer)
    }

    fn len(&mut self) -> usize {
        self.zip.len()
    }

    fn with_producer<CB>(self, callback: CB) -> CB::Output
        where CB: ProducerCallback<Self::Item>
    {
        self.zip.with_producer(callback)
    }
}
<commit_msg>Add documentation for ZipEq<commit_after>
use super::internal::*;
use super::*;
use std::cmp;
use std::iter;

/// An [`IndexedParallelIterator`] that iterates over two parallel iterators of equal
/// length simultaneously.
///
/// This struct is created by the [`zip_eq`] method on [`IndexedParallelIterator`],
/// see its documentation for more information.
///
/// [`zip_eq`]: trait.IndexedParallelIterator.html#method.zip_eq
/// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct ZipEq<A: IndexedParallelIterator, B: IndexedParallelIterator> {
    zip: Zip<A, B>
}

/// Create a new `ZipEq` iterator.
///
/// NB: a free fn because it is NOT part of the end-user API.
#[inline]
pub fn new<A, B>(a: A, b: B) -> ZipEq<A, B>
    where A: IndexedParallelIterator,
          B: IndexedParallelIterator
{
    ZipEq { zip: super::zip::new(a, b) }
}

impl<A, B> ParallelIterator for ZipEq<A, B>
    where A: IndexedParallelIterator,
          B: IndexedParallelIterator
{
    type Item = (A::Item, B::Item);

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge(self.zip, consumer)
    }

    fn opt_len(&mut self) -> Option<usize> {
        Some(self.zip.len())
    }
}

impl<A, B> IndexedParallelIterator for ZipEq<A, B>
    where A: IndexedParallelIterator,
          B: IndexedParallelIterator
{
    fn drive<C>(self, consumer: C) -> C::Result
        where C: Consumer<Self::Item>
    {
        bridge(self.zip, consumer)
    }

    fn len(&mut self) -> usize {
        self.zip.len()
    }

    fn with_producer<CB>(self, callback: CB) -> CB::Output
        where CB: ProducerCallback<Self::Item>
    {
        self.zip.with_producer(callback)
    }
}
<|endoftext|>


<commit_before>#![deny(unused)]
#![cfg_attr(test, deny(warnings))]

#[cfg(test)] extern crate hamcrest;
#[macro_use] extern crate log;
extern crate crates_io as registry;
extern crate crossbeam;
extern crate curl;
extern crate docopt;
extern crate filetime;
extern crate flate2;
extern crate fs2;
extern crate git2;
extern crate glob;
extern crate libc;
extern crate libgit2_sys;
extern crate num_cpus;
extern crate regex;
extern crate rustc_serialize;
extern crate semver;
extern crate tar;
extern crate tempdir;
extern crate term;
extern crate toml;
extern crate url;

use std::env;
use std::io::prelude::*;
use std::io;
use rustc_serialize::{Decodable, Encodable};
use rustc_serialize::json::{self, Json};
use docopt::Docopt;

use core::{Shell, MultiShell, ShellConfig, Verbosity, ColorConfig};
use core::shell::Verbosity::{Verbose};
use core::shell::ColorConfig::{Auto};
use term::color::{BLACK};

pub use util::{CargoError, CargoResult, CliError, CliResult, human, Config, ChainError};

macro_rules! bail {
    ($($fmt:tt)*) => (
        return Err(::util::human(&format_args!($($fmt)*)))
    )
}

pub mod core;
pub mod ops;
pub mod sources;
pub mod util;

pub fn execute_main<T, U, V>(
                        exec: fn(T, U, &Config) -> CliResult<Option<V>>,
                        options_first: bool,
                        usage: &str)
    where V: Encodable, T: Decodable, U: Decodable
{
    process::<V, _>(|rest, shell| {
        call_main(exec, shell, usage, rest, options_first)
    });
}

pub fn call_main<T, U, V>(
            exec: fn(T, U, &Config) -> CliResult<Option<V>>,
            shell: &Config,
            usage: &str,
            args: &[String],
            options_first: bool) -> CliResult<Option<V>>
    where V: Encodable, T: Decodable, U: Decodable
{
    let flags = try!(flags_from_args::<T>(usage, args, options_first));
    let json = try!(json_from_stdin::<U>());

    exec(flags, json, shell)
}

pub fn execute_main_without_stdin<T, V>(
                                      exec: fn(T, &Config) -> CliResult<Option<V>>,
                                      options_first: bool,
                                      usage: &str)
    where V: Encodable, T: Decodable
{
    process::<V, _>(|rest, shell| {
        call_main_without_stdin(exec, shell, usage, rest, options_first)
    });
}

pub fn call_main_without_stdin<T, V>(
            exec: fn(T, &Config) -> CliResult<Option<V>>,
            shell: &Config,
            usage: &str,
            args: &[String],
            options_first: bool) -> CliResult<Option<V>>
    where V: Encodable, T: Decodable
{
    let flags = try!(flags_from_args::<T>(usage, args, options_first));
    exec(flags, shell)
}

fn process<V, F>(mut callback: F)
    where F: FnMut(&[String], &Config) -> CliResult<Option<V>>,
          V: Encodable
{
    let mut config = None;
    let result = (|| {
        config = Some(try!(Config::default()));
        let args: Vec<_> = try!(env::args_os().map(|s| {
            s.into_string().map_err(|s| {
                human(format!("invalid unicode in argument: {:?}", s))
            })
        }).collect());
        callback(&args, config.as_ref().unwrap())
    })();
    let mut verbose_shell = shell(Verbose, Auto);
    let mut shell = config.as_ref().map(|s| s.shell());
    let shell = shell.as_mut().map(|s| &mut **s).unwrap_or(&mut verbose_shell);
    process_executed(result, shell)
}

pub fn process_executed<T>(result: CliResult<Option<T>>, shell: &mut MultiShell)
    where T: Encodable
{
    match result {
        Err(e) => handle_error(e, shell),
        Ok(Some(encodable)) => {
            let encoded = json::encode(&encodable).unwrap();
            println!("{}", encoded);
        }
        Ok(None) => {}
    }
}

pub fn shell(verbosity: Verbosity, color_config: ColorConfig) -> MultiShell {
    enum Output {
        Stdout,
        Stderr,
    }

    let tty = isatty(Output::Stderr);

    let config = ShellConfig { color_config: color_config, tty: tty };
    let err = Shell::create(|| Box::new(io::stderr()), config);

    let tty = isatty(Output::Stdout);

    let config = ShellConfig { color_config: color_config, tty: tty };
    let out = Shell::create(|| Box::new(io::stdout()), config);

    return MultiShell::new(out, err, verbosity);

    #[cfg(unix)]
    fn isatty(output: Output) -> bool {
        let fd = match output {
            Output::Stdout => libc::STDOUT_FILENO,
            Output::Stderr => libc::STDERR_FILENO,
        };

        unsafe { libc::isatty(fd) != 0 }
    }
    #[cfg(windows)]
    fn isatty(output: Output) -> bool {
        extern crate kernel32;
        extern crate winapi;

        let handle = match output {
            Output::Stdout => winapi::winbase::STD_OUTPUT_HANDLE,
            Output::Stderr => winapi::winbase::STD_ERROR_HANDLE,
        };

        unsafe {
            let handle = kernel32::GetStdHandle(handle);
            let mut out = 0;
            kernel32::GetConsoleMode(handle, &mut out) != 0
        }
    }
}

pub fn handle_error(err: CliError, shell: &mut MultiShell) {
    debug!("handle_error; err={:?}", err);

    let CliError { error, exit_code, unknown } = err;
    // exit_code == 0 is non-fatal error, e.g. docopt version info
    let fatal = exit_code != 0;

    let hide = unknown && shell.get_verbose() != Verbose;

    if let Some(error) = error {
        let _ignored_result = if hide {
            shell.error("An unknown error occurred")
        } else if fatal {
            shell.error(&error)
        } else {
            shell.say(&error, BLACK)
        };

        if !handle_cause(&error, shell) || hide {
            let _ = shell.err().say("\nTo learn more, run the command again \
                                     with --verbose.".to_string(), BLACK);
        }
    }

    std::process::exit(exit_code);
}

fn handle_cause(mut cargo_err: &CargoError, shell: &mut MultiShell) -> bool {
    let verbose = shell.get_verbose();
    let mut err;
    loop {
        cargo_err = match cargo_err.cargo_cause() {
            Some(cause) => cause,
            None => { err = cargo_err.cause(); break }
        };
        if verbose != Verbose && !cargo_err.is_human() { return false }
        print(cargo_err.to_string(), shell);
    }
    loop {
        let cause = match err { Some(err) => err, None => return true };
        if verbose != Verbose { return false }
        print(cause.to_string(), shell);
        err = cause.cause();
    }

    fn print(error: String, shell: &mut MultiShell) {
        let _ = shell.err().say("\nCaused by:", BLACK);
        let _ = shell.err().say(format!("  {}", error), BLACK);
    }
}

pub fn version() -> String {
    format!("cargo {}", match option_env!("CFG_VERSION") {
        Some(s) => s.to_string(),
        None => format!("{}.{}.{}{}",
                        env!("CARGO_PKG_VERSION_MAJOR"),
                        env!("CARGO_PKG_VERSION_MINOR"),
                        env!("CARGO_PKG_VERSION_PATCH"),
                        option_env!("CARGO_PKG_VERSION_PRE").unwrap_or(""))
    })
}

fn flags_from_args<T>(usage: &str, args: &[String],
                          options_first: bool) -> CliResult<T>
    where T: Decodable
{
    let docopt = Docopt::new(usage).unwrap()
                                   .options_first(options_first)
                                   .argv(args.iter().map(|s| &s[..]))
                                   .help(true);
    docopt.decode().map_err(|e| {
        let code = if e.fatal() {1} else {0};
        CliError::new(human(e.to_string()), code)
    })
}

fn json_from_stdin<T: Decodable>() -> CliResult<T> {
    let mut reader = io::stdin();
    let mut input = String::new();
    try!(reader.read_to_string(&mut input).map_err(|_| {
        CliError::new(human("Standard in did not exist or was not UTF-8"), 1)
    }));

    let json = try!(Json::from_str(&input).map_err(|_| {
        CliError::new(human("Could not parse standard in as JSON"), 1)
    }));
    let mut decoder = json::Decoder::new(json);

    Decodable::decode(&mut decoder).map_err(|_| {
        CliError::new(human("Could not process standard in as input"), 1)
    })
}
<commit_msg>Auto merge of #2840 - matklad:remove-dead-code, r=alexcrichton<commit_after>#![deny(unused)]
#![cfg_attr(test, deny(warnings))]

#[cfg(test)] extern crate hamcrest;
#[macro_use] extern crate log;
extern crate crates_io as registry;
extern crate crossbeam;
extern crate curl;
extern crate docopt;
extern crate filetime;
extern crate flate2;
extern crate fs2;
extern crate git2;
extern crate glob;
extern crate libc;
extern crate libgit2_sys;
extern crate num_cpus;
extern crate regex;
extern crate rustc_serialize;
extern crate semver;
extern crate tar;
extern crate tempdir;
extern crate term;
extern crate toml;
extern crate url;

use std::env;
use std::io;
use rustc_serialize::{Decodable, Encodable};
use rustc_serialize::json;
use docopt::Docopt;

use core::{Shell, MultiShell, ShellConfig, Verbosity, ColorConfig};
use core::shell::Verbosity::{Verbose};
use core::shell::ColorConfig::{Auto};
use term::color::{BLACK};

pub use util::{CargoError, CargoResult, CliError, CliResult, human, Config, ChainError};

macro_rules! bail {
    ($($fmt:tt)*) => (
        return Err(::util::human(&format_args!($($fmt)*)))
    )
}

pub mod core;
pub mod ops;
pub mod sources;
pub mod util;

pub fn execute_main_without_stdin<T, V>(
                                      exec: fn(T, &Config) -> CliResult<Option<V>>,
                                      options_first: bool,
                                      usage: &str)
    where V: Encodable, T: Decodable
{
    process::<V, _>(|rest, shell| {
        call_main_without_stdin(exec, shell, usage, rest, options_first)
    });
}

pub fn call_main_without_stdin<T, V>(
            exec: fn(T, &Config) -> CliResult<Option<V>>,
            shell: &Config,
            usage: &str,
            args: &[String],
            options_first: bool) -> CliResult<Option<V>>
    where V: Encodable, T: Decodable
{
    let flags = try!(flags_from_args::<T>(usage, args, options_first));
    exec(flags, shell)
}

fn process<V, F>(mut callback: F)
    where F: FnMut(&[String], &Config) -> CliResult<Option<V>>,
          V: Encodable
{
    let mut config = None;
    let result = (|| {
        config = Some(try!(Config::default()));
        let args: Vec<_> = try!(env::args_os().map(|s| {
            s.into_string().map_err(|s| {
                human(format!("invalid unicode in argument: {:?}", s))
            })
        }).collect());
        callback(&args, config.as_ref().unwrap())
    })();
    let mut verbose_shell = shell(Verbose, Auto);
    let mut shell = config.as_ref().map(|s| s.shell());
    let shell = shell.as_mut().map(|s| &mut **s).unwrap_or(&mut verbose_shell);
    process_executed(result, shell)
}

pub fn process_executed<T>(result: CliResult<Option<T>>, shell: &mut MultiShell)
    where T: Encodable
{
    match result {
        Err(e) => handle_error(e, shell),
        Ok(Some(encodable)) => {
            let encoded = json::encode(&encodable).unwrap();
            println!("{}", encoded);
        }
        Ok(None) => {}
    }
}

pub fn shell(verbosity: Verbosity, color_config: ColorConfig) -> MultiShell {
    enum Output {
        Stdout,
        Stderr,
    }

    let tty = isatty(Output::Stderr);

    let config = ShellConfig { color_config: color_config, tty: tty };
    let err = Shell::create(|| Box::new(io::stderr()), config);

    let tty = isatty(Output::Stdout);

    let config = ShellConfig { color_config: color_config, tty: tty };
    let out = Shell::create(|| Box::new(io::stdout()), config);

    return MultiShell::new(out, err, verbosity);

    #[cfg(unix)]
    fn isatty(output: Output) -> bool {
        let fd = match output {
            Output::Stdout => libc::STDOUT_FILENO,
            Output::Stderr => libc::STDERR_FILENO,
        };

        unsafe { libc::isatty(fd) != 0 }
    }
    #[cfg(windows)]
    fn isatty(output: Output) -> bool {
        extern crate kernel32;
        extern crate winapi;

        let handle = match output {
            Output::Stdout => winapi::winbase::STD_OUTPUT_HANDLE,
            Output::Stderr => winapi::winbase::STD_ERROR_HANDLE,
        };

        unsafe {
            let handle = kernel32::GetStdHandle(handle);
            let mut out = 0;
            kernel32::GetConsoleMode(handle, &mut out) != 0
        }
    }
}

pub fn handle_error(err: CliError, shell: &mut MultiShell) {
    debug!("handle_error; err={:?}", err);

    let CliError { error, exit_code, unknown } = err;
    // exit_code == 0 is non-fatal error, e.g. docopt version info
    let fatal = exit_code != 0;

    let hide = unknown && shell.get_verbose() != Verbose;

    if let Some(error) = error {
        let _ignored_result = if hide {
            shell.error("An unknown error occurred")
        } else if fatal {
            shell.error(&error)
        } else {
            shell.say(&error, BLACK)
        };

        if !handle_cause(&error, shell) || hide {
            let _ = shell.err().say("\nTo learn more, run the command again \
                                     with --verbose.".to_string(), BLACK);
        }
    }

    std::process::exit(exit_code);
}

fn handle_cause(mut cargo_err: &CargoError, shell: &mut MultiShell) -> bool {
    let verbose = shell.get_verbose();
    let mut err;
    loop {
        cargo_err = match cargo_err.cargo_cause() {
            Some(cause) => cause,
            None => { err = cargo_err.cause(); break }
        };
        if verbose != Verbose && !cargo_err.is_human() { return false }
        print(cargo_err.to_string(), shell);
    }
    loop {
        let cause = match err { Some(err) => err, None => return true };
        if verbose != Verbose { return false }
        print(cause.to_string(), shell);
        err = cause.cause();
    }

    fn print(error: String, shell: &mut MultiShell) {
        let _ = shell.err().say("\nCaused by:", BLACK);
        let _ = shell.err().say(format!("  {}", error), BLACK);
    }
}

pub fn version() -> String {
    format!("cargo {}", match option_env!("CFG_VERSION") {
        Some(s) => s.to_string(),
        None => format!("{}.{}.{}{}",
                        env!("CARGO_PKG_VERSION_MAJOR"),
                        env!("CARGO_PKG_VERSION_MINOR"),
                        env!("CARGO_PKG_VERSION_PATCH"),
                        option_env!("CARGO_PKG_VERSION_PRE").unwrap_or(""))
    })
}

fn flags_from_args<T>(usage: &str, args: &[String],
                          options_first: bool) -> CliResult<T>
    where T: Decodable
{
    let docopt = Docopt::new(usage).unwrap()
                                   .options_first(options_first)
                                   .argv(args.iter().map(|s| &s[..]))
                                   .help(true);
    docopt.decode().map_err(|e| {
        let code = if e.fatal() {1} else {0};
        CliError::new(human(e.to_string()), code)
    })
}
<|endoftext|>


<commit_before>static RUST_KEYWORDS: [&str; 76] = [
    "abstract",
    "alignof",
    "as",
    "become",
    "bool",
    "box",
    "Box",
    "break",
    "BytesReader",
    "const",
    "continue",
    "crate",
    "Cow",
    "Default",
    "do",
    "else",
    "enum",
    "Err",
    "extern",
    "f32",
    "f64",
    "false",
    "final",
    "fn",
    "for",
    "HashMap",
    "i32",
    "i64",
    "if",
    "impl",
    "in",
    "let",
    "loop",
    "match",
    "mod",
    "move",
    "mut",
    "None",
    "MessageWrite",
    "offsetof",
    "Ok",
    "Option",
    "override",
    "priv",
    "proc",
    "pub",
    "pure",
    "ref",
    "Result",
    "return",
    "self",
    "Self",
    "sizeof",
    "Some",
    "static",
    "str",
    "String",
    "struct",
    "super",
    "trait",
    "true",
    "type",
    "typeof",
    "u8",
    "u32",
    "u64",
    "unsafe",
    "unsized",
    "use",
    "Vec",
    "virtual",
    "where",
    "while",
    "Write",
    "Writer",
    "yield",
];

/// Ckeck is the identifier is a rust keyword and appends a '_pb' if that's the case
pub fn sanitize_keyword(ident: &mut String) {
    if !ident.contains('.') && RUST_KEYWORDS.contains(&&**ident) {
        ident.push_str("_pb");
    } else {
        *ident = ident
            .split('.')
            .map(|s| {
                if RUST_KEYWORDS.contains(&s) {
                    format!("{}_pb", s)
                } else {
                    s.to_string()
                }
            })
            .collect::<Vec<_>>()
            .join(".");
    }
}
<commit_msg>Update keywords.rs<commit_after>static RUST_KEYWORDS: [&str; 76] = [
    "abstract",
    "alignof",
    "as",
    "become",
    "bool",
    "box",
    "Box",
    "break",
    "BytesReader",
    "const",
    "continue",
    "crate",
    "Cow",
    "Default",
    "do",
    "else",
    "enum",
    "Err",
    "extern",
    "f32",
    "f64",
    "false",
    "final",
    "fn",
    "for",
    "HashMap",
    "i32",
    "i64",
    "if",
    "impl",
    "in",
    "let",
    "loop",
    "match",
    "mod",
    "move",
    "mut",
    "None",
    "MessageWrite",
    "offsetof",
    "Ok",
    "Option",
    "override",
    "priv",
    "pub",
    "pure",
    "ref",
    "Result",
    "return",
    "self",
    "Self",
    "sizeof",
    "Some",
    "static",
    "str",
    "String",
    "struct",
    "super",
    "trait",
    "true",
    "type",
    "typeof",
    "u8",
    "u32",
    "u64",
    "unsafe",
    "unsized",
    "use",
    "Vec",
    "virtual",
    "where",
    "while",
    "Write",
    "Writer",
    "yield",
];

/// Ckeck is the identifier is a rust keyword and appends a '_pb' if that's the case
pub fn sanitize_keyword(ident: &mut String) {
    if !ident.contains('.') && RUST_KEYWORDS.contains(&&**ident) {
        ident.push_str("_pb");
    } else {
        *ident = ident
            .split('.')
            .map(|s| {
                if RUST_KEYWORDS.contains(&s) {
                    format!("{}_pb", s)
                } else {
                    s.to_string()
                }
            })
            .collect::<Vec<_>>()
            .join(".");
    }
}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/phf_shared/0.10")]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "std")]
extern crate std as core;

use core::fmt;
use core::hash::{Hash, Hasher};
use core::num::Wrapping;
use siphasher::sip128::{Hash128, Hasher128, SipHasher13};

#[non_exhaustive]
pub struct Hashes {
    pub g: u32,
    pub f1: u32,
    pub f2: u32,
}

/// A central typedef for hash keys
///
/// Makes experimentation easier by only needing to be updated here.
pub type HashKey = u64;

#[inline]
pub fn displace(f1: u32, f2: u32, d1: u32, d2: u32) -> u32 {
    (Wrapping(d2) + Wrapping(f1) * Wrapping(d1) + Wrapping(f2)).0
}

/// `key` is from `phf_generator::HashState`.
#[inline]
pub fn hash<T: ?Sized + PhfHash>(x: &T, key: &HashKey) -> Hashes {
    let mut hasher = SipHasher13::new_with_keys(0, *key);
    x.phf_hash(&mut hasher);

    let Hash128 {
        h1: lower,
        h2: upper,
    } = hasher.finish128();

    Hashes {
        g: (lower >> 32) as u32,
        f1: lower as u32,
        f2: upper as u32,
    }
}

/// Return an index into `phf_generator::HashState::map`.
///
/// * `hash` is from `hash()` in this crate.
/// * `disps` is from `phf_generator::HashState::disps`.
/// * `len` is the length of `phf_generator::HashState::map`.
#[inline]
pub fn get_index(hashes: &Hashes, disps: &[(u32, u32)], len: usize) -> u32 {
    let (d1, d2) = disps[(hashes.g % (disps.len() as u32)) as usize];
    displace(hashes.f1, hashes.f2, d1, d2) % (len as u32)
}

/// A trait implemented by types which can be used in PHF data structures.
///
/// This differs from the standard library's `Hash` trait in that `PhfHash`'s
/// results must be architecture independent so that hashes will be consistent
/// between the host and target when cross compiling.
pub trait PhfHash {
    /// Feeds the value into the state given, updating the hasher as necessary.
    fn phf_hash<H: Hasher>(&self, state: &mut H);

    /// Feeds a slice of this type into the state provided.
    fn phf_hash_slice<H: Hasher>(data: &[Self], state: &mut H)
    where
        Self: Sized,
    {
        for piece in data {
            piece.phf_hash(state);
        }
    }
}

/// Trait for printing types with `const` constructors, used by `phf_codegen` and `phf_macros`.
pub trait FmtConst {
    /// Print a `const` expression representing this value.
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
}

/// Identical to `std::borrow::Borrow` except omitting blanket impls to facilitate other
/// borrowing patterns.
///
/// The same semantic requirements apply:
///
/// > In particular `Eq`, `Ord` and `Hash` must be equivalent for borrowed and owned values:
/// `x.borrow() == y.borrow()` should give the same result as `x == y`.
///
/// (This crate's API only requires `Eq` and `PhfHash`, however.)
///
/// ### Motivation
/// The conventional signature for lookup methods on collections looks something like this:
///
/// ```rust,ignore
/// impl<K, V> Map<K, V> where K: PhfHash + Eq {
///     fn get<T: ?Sized>(&self, key: &T) -> Option<&V> where T: PhfHash + Eq, K: Borrow<T> {
///         ...
///     }
/// }
/// ```
///
/// This allows the key type used for lookup to be different than the key stored in the map so for
/// example you can use `&str` to look up a value in a `Map<String, _>`. However, this runs into
/// a problem in the case where `T` and `K` are both a `Foo<_>` type constructor but
/// the contained type is different (even being the same type with different lifetimes).
///
/// The main issue for this crate's API is that, with this method signature, you cannot perform a
/// lookup on a `Map<UniCase<&'static str>, _>` with a `UniCase<&'a str>` where `'a` is not
/// `'static`; there is no impl of `Borrow` that resolves to
/// `impl Borrow<UniCase<'a>> for UniCase<&'static str>` and one cannot be added either because of
/// all the blanket impls.
///
/// Instead, this trait is implemented conservatively, without blanket impls, so that impls like
/// this may be added. This is feasible since the set of types that implement `PhfHash` is
/// intentionally small.
///
/// This likely won't be fixable with specialization alone but will require full support for lattice
/// impls since we technically want to add overlapping blanket impls.
pub trait PhfBorrow<B: ?Sized> {
    /// Convert a reference to `self` to a reference to the borrowed type.
    fn borrow(&self) -> &B;
}

/// Create an impl of `FmtConst` delegating to `fmt::Debug` for types that can deal with it.
///
/// Ideally with specialization this could be just one default impl and then specialized where
/// it doesn't apply.
macro_rules! delegate_debug (
    ($ty:ty) => {
        impl FmtConst for $ty {
            fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                write!(f, "{:?}", self)
            }
        }
    }
);

delegate_debug!(str);
delegate_debug!(char);
delegate_debug!(u8);
delegate_debug!(i8);
delegate_debug!(u16);
delegate_debug!(i16);
delegate_debug!(u32);
delegate_debug!(i32);
delegate_debug!(u64);
delegate_debug!(i64);
delegate_debug!(u128);
delegate_debug!(i128);
delegate_debug!(bool);

/// `impl PhfBorrow<T> for T`
macro_rules! impl_reflexive(
    ($($t:ty),*) => (
        $(impl PhfBorrow<$t> for $t {
            fn borrow(&self) -> &$t {
                self
            }
        })*
    )
);

impl_reflexive!(
    str,
    char,
    u8,
    i8,
    u16,
    i16,
    u32,
    i32,
    u64,
    i64,
    u128,
    i128,
    bool,
    [u8]
);

#[cfg(feature = "std")]
impl PhfBorrow<str> for String {
    fn borrow(&self) -> &str {
        self
    }
}

#[cfg(feature = "std")]
impl PhfBorrow<[u8]> for Vec<u8> {
    fn borrow(&self) -> &[u8] {
        self
    }
}

#[cfg(feature = "std")]
delegate_debug!(String);

#[cfg(feature = "std")]
impl PhfHash for String {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (**self).phf_hash(state)
    }
}

#[cfg(feature = "std")]
impl PhfHash for Vec<u8> {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (**self).phf_hash(state)
    }
}

impl<'a, T: 'a + PhfHash + ?Sized> PhfHash for &'a T {
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (*self).phf_hash(state)
    }
}

impl<'a, T: 'a + FmtConst + ?Sized> FmtConst for &'a T {
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (*self).fmt_const(f)
    }
}

impl<'a> PhfBorrow<str> for &'a str {
    fn borrow(&self) -> &str {
        self
    }
}

impl<'a> PhfBorrow<[u8]> for &'a [u8] {
    fn borrow(&self) -> &[u8] {
        self
    }
}

impl PhfHash for str {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        self.as_bytes().phf_hash(state)
    }
}

impl PhfHash for [u8] {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        state.write(self);
    }
}

impl FmtConst for [u8] {
    #[inline]
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // slices need a leading reference
        write!(f, "&{:?}", self)
    }
}

#[cfg(feature = "unicase")]
impl<S> PhfHash for unicase::UniCase<S>
where
    unicase::UniCase<S>: Hash,
{
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        self.hash(state)
    }
}

#[cfg(feature = "unicase")]
impl<S> FmtConst for unicase::UniCase<S>
where
    S: AsRef<str>,
{
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if self.is_ascii() {
            f.write_str("UniCase::ascii(")?;
        } else {
            f.write_str("UniCase::unicode(")?;
        }

        self.as_ref().fmt_const(f)?;
        f.write_str(")")
    }
}

#[cfg(feature = "unicase")]
impl<'b, 'a: 'b, S: ?Sized + 'a> PhfBorrow<unicase::UniCase<&'b S>> for unicase::UniCase<&'a S> {
    fn borrow(&self) -> &unicase::UniCase<&'b S> {
        self
    }
}

#[cfg(feature = "uncased")]
impl PhfHash for uncased::UncasedStr {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        self.hash(state)
    }
}

#[cfg(feature = "uncased")]
impl FmtConst for uncased::UncasedStr {
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // transmute is not stable in const fns (rust-lang/rust#53605), so
        // `UncasedStr::new` can't be a const fn itself, but we can inline the
        // call to transmute here in the meantime.
        f.write_str("unsafe { ::std::mem::transmute::<&'static str, &'static UncasedStr>(")?;
        self.as_str().fmt_const(f)?;
        f.write_str(") }")
    }
}

#[cfg(feature = "uncased")]
impl PhfBorrow<uncased::UncasedStr> for &uncased::UncasedStr {
    fn borrow(&self) -> &uncased::UncasedStr {
        self
    }
}

macro_rules! sip_impl (
    (le $t:ty) => (
        impl PhfHash for $t {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                self.to_le().hash(state);
            }
        }
    );
    ($t:ty) => (
        impl PhfHash for $t {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                self.hash(state);
            }
        }
    )
);

sip_impl!(u8);
sip_impl!(i8);
sip_impl!(le u16);
sip_impl!(le i16);
sip_impl!(le u32);
sip_impl!(le i32);
sip_impl!(le u64);
sip_impl!(le i64);
sip_impl!(le u128);
sip_impl!(le i128);
sip_impl!(bool);

impl PhfHash for char {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (*self as u32).phf_hash(state)
    }
}

// minimize duplicated code since formatting drags in quite a bit
fn fmt_array(array: &[u8], f: &mut fmt::Formatter<'_>) -> fmt::Result {
    write!(f, "{:?}", array)
}

macro_rules! array_impl (
    ($t:ty, $n:expr) => (
        impl PhfHash for [$t; $n] {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                state.write(self);
            }
        }

        impl FmtConst for [$t; $n] {
            fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                fmt_array(self, f)
            }
        }

        impl PhfBorrow<[$t]> for [$t; $n] {
            fn borrow(&self) -> &[$t] {
                self
            }
        }
    )
);

array_impl!(u8, 1);
array_impl!(u8, 2);
array_impl!(u8, 3);
array_impl!(u8, 4);
array_impl!(u8, 5);
array_impl!(u8, 6);
array_impl!(u8, 7);
array_impl!(u8, 8);
array_impl!(u8, 9);
array_impl!(u8, 10);
array_impl!(u8, 11);
array_impl!(u8, 12);
array_impl!(u8, 13);
array_impl!(u8, 14);
array_impl!(u8, 15);
array_impl!(u8, 16);
array_impl!(u8, 17);
array_impl!(u8, 18);
array_impl!(u8, 19);
array_impl!(u8, 20);
array_impl!(u8, 21);
array_impl!(u8, 22);
array_impl!(u8, 23);
array_impl!(u8, 24);
array_impl!(u8, 25);
array_impl!(u8, 26);
array_impl!(u8, 27);
array_impl!(u8, 28);
array_impl!(u8, 29);
array_impl!(u8, 30);
array_impl!(u8, 31);
array_impl!(u8, 32);
<commit_msg>phf_shared: make uncased feature compatible with no_std<commit_after>#![doc(html_root_url = "https://docs.rs/phf_shared/0.10")]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "std")]
extern crate std as core;

use core::fmt;
use core::hash::{Hash, Hasher};
use core::num::Wrapping;
use siphasher::sip128::{Hash128, Hasher128, SipHasher13};

#[non_exhaustive]
pub struct Hashes {
    pub g: u32,
    pub f1: u32,
    pub f2: u32,
}

/// A central typedef for hash keys
///
/// Makes experimentation easier by only needing to be updated here.
pub type HashKey = u64;

#[inline]
pub fn displace(f1: u32, f2: u32, d1: u32, d2: u32) -> u32 {
    (Wrapping(d2) + Wrapping(f1) * Wrapping(d1) + Wrapping(f2)).0
}

/// `key` is from `phf_generator::HashState`.
#[inline]
pub fn hash<T: ?Sized + PhfHash>(x: &T, key: &HashKey) -> Hashes {
    let mut hasher = SipHasher13::new_with_keys(0, *key);
    x.phf_hash(&mut hasher);

    let Hash128 {
        h1: lower,
        h2: upper,
    } = hasher.finish128();

    Hashes {
        g: (lower >> 32) as u32,
        f1: lower as u32,
        f2: upper as u32,
    }
}

/// Return an index into `phf_generator::HashState::map`.
///
/// * `hash` is from `hash()` in this crate.
/// * `disps` is from `phf_generator::HashState::disps`.
/// * `len` is the length of `phf_generator::HashState::map`.
#[inline]
pub fn get_index(hashes: &Hashes, disps: &[(u32, u32)], len: usize) -> u32 {
    let (d1, d2) = disps[(hashes.g % (disps.len() as u32)) as usize];
    displace(hashes.f1, hashes.f2, d1, d2) % (len as u32)
}

/// A trait implemented by types which can be used in PHF data structures.
///
/// This differs from the standard library's `Hash` trait in that `PhfHash`'s
/// results must be architecture independent so that hashes will be consistent
/// between the host and target when cross compiling.
pub trait PhfHash {
    /// Feeds the value into the state given, updating the hasher as necessary.
    fn phf_hash<H: Hasher>(&self, state: &mut H);

    /// Feeds a slice of this type into the state provided.
    fn phf_hash_slice<H: Hasher>(data: &[Self], state: &mut H)
    where
        Self: Sized,
    {
        for piece in data {
            piece.phf_hash(state);
        }
    }
}

/// Trait for printing types with `const` constructors, used by `phf_codegen` and `phf_macros`.
pub trait FmtConst {
    /// Print a `const` expression representing this value.
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
}

/// Identical to `std::borrow::Borrow` except omitting blanket impls to facilitate other
/// borrowing patterns.
///
/// The same semantic requirements apply:
///
/// > In particular `Eq`, `Ord` and `Hash` must be equivalent for borrowed and owned values:
/// `x.borrow() == y.borrow()` should give the same result as `x == y`.
///
/// (This crate's API only requires `Eq` and `PhfHash`, however.)
///
/// ### Motivation
/// The conventional signature for lookup methods on collections looks something like this:
///
/// ```rust,ignore
/// impl<K, V> Map<K, V> where K: PhfHash + Eq {
///     fn get<T: ?Sized>(&self, key: &T) -> Option<&V> where T: PhfHash + Eq, K: Borrow<T> {
///         ...
///     }
/// }
/// ```
///
/// This allows the key type used for lookup to be different than the key stored in the map so for
/// example you can use `&str` to look up a value in a `Map<String, _>`. However, this runs into
/// a problem in the case where `T` and `K` are both a `Foo<_>` type constructor but
/// the contained type is different (even being the same type with different lifetimes).
///
/// The main issue for this crate's API is that, with this method signature, you cannot perform a
/// lookup on a `Map<UniCase<&'static str>, _>` with a `UniCase<&'a str>` where `'a` is not
/// `'static`; there is no impl of `Borrow` that resolves to
/// `impl Borrow<UniCase<'a>> for UniCase<&'static str>` and one cannot be added either because of
/// all the blanket impls.
///
/// Instead, this trait is implemented conservatively, without blanket impls, so that impls like
/// this may be added. This is feasible since the set of types that implement `PhfHash` is
/// intentionally small.
///
/// This likely won't be fixable with specialization alone but will require full support for lattice
/// impls since we technically want to add overlapping blanket impls.
pub trait PhfBorrow<B: ?Sized> {
    /// Convert a reference to `self` to a reference to the borrowed type.
    fn borrow(&self) -> &B;
}

/// Create an impl of `FmtConst` delegating to `fmt::Debug` for types that can deal with it.
///
/// Ideally with specialization this could be just one default impl and then specialized where
/// it doesn't apply.
macro_rules! delegate_debug (
    ($ty:ty) => {
        impl FmtConst for $ty {
            fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                write!(f, "{:?}", self)
            }
        }
    }
);

delegate_debug!(str);
delegate_debug!(char);
delegate_debug!(u8);
delegate_debug!(i8);
delegate_debug!(u16);
delegate_debug!(i16);
delegate_debug!(u32);
delegate_debug!(i32);
delegate_debug!(u64);
delegate_debug!(i64);
delegate_debug!(u128);
delegate_debug!(i128);
delegate_debug!(bool);

/// `impl PhfBorrow<T> for T`
macro_rules! impl_reflexive(
    ($($t:ty),*) => (
        $(impl PhfBorrow<$t> for $t {
            fn borrow(&self) -> &$t {
                self
            }
        })*
    )
);

impl_reflexive!(
    str,
    char,
    u8,
    i8,
    u16,
    i16,
    u32,
    i32,
    u64,
    i64,
    u128,
    i128,
    bool,
    [u8]
);

#[cfg(feature = "std")]
impl PhfBorrow<str> for String {
    fn borrow(&self) -> &str {
        self
    }
}

#[cfg(feature = "std")]
impl PhfBorrow<[u8]> for Vec<u8> {
    fn borrow(&self) -> &[u8] {
        self
    }
}

#[cfg(feature = "std")]
delegate_debug!(String);

#[cfg(feature = "std")]
impl PhfHash for String {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (**self).phf_hash(state)
    }
}

#[cfg(feature = "std")]
impl PhfHash for Vec<u8> {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (**self).phf_hash(state)
    }
}

impl<'a, T: 'a + PhfHash + ?Sized> PhfHash for &'a T {
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (*self).phf_hash(state)
    }
}

impl<'a, T: 'a + FmtConst + ?Sized> FmtConst for &'a T {
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (*self).fmt_const(f)
    }
}

impl<'a> PhfBorrow<str> for &'a str {
    fn borrow(&self) -> &str {
        self
    }
}

impl<'a> PhfBorrow<[u8]> for &'a [u8] {
    fn borrow(&self) -> &[u8] {
        self
    }
}

impl PhfHash for str {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        self.as_bytes().phf_hash(state)
    }
}

impl PhfHash for [u8] {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        state.write(self);
    }
}

impl FmtConst for [u8] {
    #[inline]
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // slices need a leading reference
        write!(f, "&{:?}", self)
    }
}

#[cfg(feature = "unicase")]
impl<S> PhfHash for unicase::UniCase<S>
where
    unicase::UniCase<S>: Hash,
{
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        self.hash(state)
    }
}

#[cfg(feature = "unicase")]
impl<S> FmtConst for unicase::UniCase<S>
where
    S: AsRef<str>,
{
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if self.is_ascii() {
            f.write_str("UniCase::ascii(")?;
        } else {
            f.write_str("UniCase::unicode(")?;
        }

        self.as_ref().fmt_const(f)?;
        f.write_str(")")
    }
}

#[cfg(feature = "unicase")]
impl<'b, 'a: 'b, S: ?Sized + 'a> PhfBorrow<unicase::UniCase<&'b S>> for unicase::UniCase<&'a S> {
    fn borrow(&self) -> &unicase::UniCase<&'b S> {
        self
    }
}

#[cfg(feature = "uncased")]
impl PhfHash for uncased::UncasedStr {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        self.hash(state)
    }
}

#[cfg(feature = "uncased")]
impl FmtConst for uncased::UncasedStr {
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // transmute is not stable in const fns (rust-lang/rust#53605), so
        // `UncasedStr::new` can't be a const fn itself, but we can inline the
        // call to transmute here in the meantime.
        f.write_str("unsafe { ::core::mem::transmute::<&'static str, &'static UncasedStr>(")?;
        self.as_str().fmt_const(f)?;
        f.write_str(") }")
    }
}

#[cfg(feature = "uncased")]
impl PhfBorrow<uncased::UncasedStr> for &uncased::UncasedStr {
    fn borrow(&self) -> &uncased::UncasedStr {
        self
    }
}

macro_rules! sip_impl (
    (le $t:ty) => (
        impl PhfHash for $t {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                self.to_le().hash(state);
            }
        }
    );
    ($t:ty) => (
        impl PhfHash for $t {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                self.hash(state);
            }
        }
    )
);

sip_impl!(u8);
sip_impl!(i8);
sip_impl!(le u16);
sip_impl!(le i16);
sip_impl!(le u32);
sip_impl!(le i32);
sip_impl!(le u64);
sip_impl!(le i64);
sip_impl!(le u128);
sip_impl!(le i128);
sip_impl!(bool);

impl PhfHash for char {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (*self as u32).phf_hash(state)
    }
}

// minimize duplicated code since formatting drags in quite a bit
fn fmt_array(array: &[u8], f: &mut fmt::Formatter<'_>) -> fmt::Result {
    write!(f, "{:?}", array)
}

macro_rules! array_impl (
    ($t:ty, $n:expr) => (
        impl PhfHash for [$t; $n] {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                state.write(self);
            }
        }

        impl FmtConst for [$t; $n] {
            fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                fmt_array(self, f)
            }
        }

        impl PhfBorrow<[$t]> for [$t; $n] {
            fn borrow(&self) -> &[$t] {
                self
            }
        }
    )
);

array_impl!(u8, 1);
array_impl!(u8, 2);
array_impl!(u8, 3);
array_impl!(u8, 4);
array_impl!(u8, 5);
array_impl!(u8, 6);
array_impl!(u8, 7);
array_impl!(u8, 8);
array_impl!(u8, 9);
array_impl!(u8, 10);
array_impl!(u8, 11);
array_impl!(u8, 12);
array_impl!(u8, 13);
array_impl!(u8, 14);
array_impl!(u8, 15);
array_impl!(u8, 16);
array_impl!(u8, 17);
array_impl!(u8, 18);
array_impl!(u8, 19);
array_impl!(u8, 20);
array_impl!(u8, 21);
array_impl!(u8, 22);
array_impl!(u8, 23);
array_impl!(u8, 24);
array_impl!(u8, 25);
array_impl!(u8, 26);
array_impl!(u8, 27);
array_impl!(u8, 28);
array_impl!(u8, 29);
array_impl!(u8, 30);
array_impl!(u8, 31);
array_impl!(u8, 32);
<|endoftext|>


<commit_before><commit_msg>correctly throw error on invalid queue in spline callbacks<commit_after><|endoftext|>