<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> {
    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;
    }

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

    // Try to undo backend linkage munging (prepended _, generally)
    if cfg!(target_os = "macos") {
        mangling.remove(0);
    }

    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;
        if (is_constructor || is_method) &&
           cursor.lexical_parent() != cursor.semantic_parent() {
            // Only parse constructors once.
            return Err(ParseError::Continue);
        }

        if is_method || is_constructor {
            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!(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() {
            // FIXME(emilio): Generate destructors properly.
            CXCursor_FunctionDecl |
            CXCursor_Constructor |
            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 name = cursor.spelling();
        assert!(!name.is_empty(), "Empty function name?");

        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>ir: Force the D1 destructor symbol even in older libclang versions.<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),
    }
}

/// 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;
    }

    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.
        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;
        if (is_constructor || is_method) &&
           cursor.lexical_parent() != cursor.semantic_parent() {
            // Only parse constructors once.
            return Err(ParseError::Continue);
        }

        if is_method || is_constructor {
            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!(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() {
            // FIXME(emilio): Generate destructors properly.
            CXCursor_FunctionDecl |
            CXCursor_Constructor |
            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 name = cursor.spelling();
        assert!(!name.is_empty(), "Empty function name?");

        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>pub fn main() {
    let number = 13;
    // TODO ^ Try different values for `number`

    println!("Tell me about {}", number);
    match number {
        // Match a single value
        1 => println!("One!"),
        // Match several values
        2 | 3 | 5 | 7 | 11 => println!("This is a prime"),
        // Match an inclusive range
        13...19 => println!("A teen"),
        // Handle the rest of cases
        _ => println!("Ain't special"),
    }

    let boolean = true;
    // Match is an expression too
    let binary = match boolean {
        // The arms of a match must cover all the possible values
        false => 0,
        //true => 1,
        _ => 1,
        // TODO ^ Try commenting out one of these arms
    };

    println!("{} -> {}", boolean, binary);

    destructured_tuples();
    destructured_enums();
    destructured_pointers_ref();
    destructured_structs();
}

fn destructured_tuples() {
    let pair = (0, -2);
    // TODO ^ Try different values for `pair`

    println!("Tell me about {:?}", pair);
    // Match can be used to destructure a tuple
    match pair {
        // Destructure the second
        (0, y) => println!("First is `0` and `y` is `{:?}`", y),
        (x, 0) => println!("`x` is `{:?}` and last is `0`", x),
        _      => println!("It doesn't matter what they are"),
        // `_` means don't bind the value to a variable
    }
}

// `allow` required to silence warnings because only
// one variant is used.
#[allow(dead_code)]
enum Color {
    // These 3 are specified solely by their name.
    Red,
    Blue,
    Green,
    // These likewise tie `u32` tuples to different names: color models.
    RGB(u32, u32, u32),
    HSV(u32, u32, u32),
    HSL(u32, u32, u32),
    CMY(u32, u32, u32),
    CMYK(u32, u32, u32, u32),
}

/// Match - Desctuctured Enums
fn destructured_enums() {
    let color = Color::RGB(122, 17, 40);
    // TODO ^ Try different variants for `color`

    println!("What color is it?");
    // An `enum` can be destructured using a `match`.
    match color {
        Color::Red   => println!("The color is Red!"),
        Color::Blue  => println!("The color is Blue!"),
        Color::Green => println!("The color is Green!"),
        Color::RGB(r, g, b) =>
            println!("Red: {}, green: {}, and blue: {}!", r, g, b),
        Color::HSV(h, s, v) =>
            println!("Hue: {}, saturation: {}, value: {}!", h, s, v),
        Color::HSL(h, s, l) =>
            println!("Hue: {}, saturation: {}, lightness: {}!", h, s, l),
        Color::CMY(c, m, y) =>
            println!("Cyan: {}, magenta: {}, yellow: {}!", c, m, y),
        Color::CMYK(c, m, y, k) =>
            println!("Cyan: {}, magenta: {}, yellow: {}, key (black): {}!",
                c, m, y, k),
        // Don't need another arm because all variants have been examined
    }
}

fn destructured_pointers_ref() {
    // Assign a reference of type `i32`. The `&` signifies there
    // is a reference being assigned.
    let reference = &4;

    match reference {
        // If `reference`s is pattern matched against `&val`, it results
        // in a comparison like:
        // `&i32`
        // `&val`
        // ^ We see that if the matching `&`s are dropped, then the `i32`
        // should be assigned to `val`.
        &val => println!("Got a value via destructuring: {:?}", val),
    }

    // To avoid the `&`, you dereference before matching.
    match *reference {
        val => println!("Got a value via dereferencing: {:?}", val),
    }

    // What if you don't start with a reference? `reference` was a `&`
    // because the right side was already a reference. This is not
    // a reference because the right side is not one.
    let _not_a_reference = 3;

    // Rust provides `ref` for exactly this purpose. It modifies the
    // assignment so that a reference is created for the element; this
    // reference is assigned.
    let ref _is_a_reference = 3;

    // Accordingly, by defining 2 values without references, references
    // can be retrieved via `ref` and `ref mut`.
    let value = 5;
    let mut mut_value = 6;

    // Use `ref` keyword to create a reference.
    match value {
        ref r => println!("Got a reference to a value: {:?}", r),
    }

    // Use `ref mut` similarly.
    match mut_value {
        ref mut m => {
            // Got a reference. Gotta dereference it before we can
            // add anything to it.
            *m += 10;
            println!("We added 10. `mut_value`: {:?}", m);
        },
    }
}

fn destructured_structs() {
    struct Foo { x: (u32, u32), y: u32 }

    // destructure members of the struct
    let foo = Foo { x: (1, 2), y: 3 };
    let Foo { x: (a, b), y } = foo;

    println!("a = {}, b = {},  y = {} ", a, b, y);

    // you can destructure structs and rename the variables,
    // the order is not important

    let Foo { y: i, x: j } = foo;
    println!("i = {:?}, j = {:?}", i, j);

    // and you can also ignore some variables:
    let Foo { y, .. } = foo;
    println!("y = {}", y);

    // this will give an error: pattern does not mention field `x`
    // let Foo { y } = foo;
}
<commit_msg>Rust By Examples [RBE] - 7.5.2 Guards<commit_after>pub fn main() {
    let number = 13;
    // TODO ^ Try different values for `number`

    println!("Tell me about {}", number);
    match number {
        // Match a single value
        1 => println!("One!"),
        // Match several values
        2 | 3 | 5 | 7 | 11 => println!("This is a prime"),
        // Match an inclusive range
        13...19 => println!("A teen"),
        // Handle the rest of cases
        _ => println!("Ain't special"),
    }

    let boolean = true;
    // Match is an expression too
    let binary = match boolean {
        // The arms of a match must cover all the possible values
        false => 0,
        //true => 1,
        _ => 1,
        // TODO ^ Try commenting out one of these arms
    };

    println!("{} -> {}", boolean, binary);

    destructured_tuples();
    destructured_enums();
    destructured_pointers_ref();
    destructured_structs();
    guards();
}

fn destructured_tuples() {
    let pair = (0, -2);
    // TODO ^ Try different values for `pair`

    println!("Tell me about {:?}", pair);
    // Match can be used to destructure a tuple
    match pair {
        // Destructure the second
        (0, y) => println!("First is `0` and `y` is `{:?}`", y),
        (x, 0) => println!("`x` is `{:?}` and last is `0`", x),
        _      => println!("It doesn't matter what they are"),
        // `_` means don't bind the value to a variable
    }
}

// `allow` required to silence warnings because only
// one variant is used.
#[allow(dead_code)]
enum Color {
    // These 3 are specified solely by their name.
    Red,
    Blue,
    Green,
    // These likewise tie `u32` tuples to different names: color models.
    RGB(u32, u32, u32),
    HSV(u32, u32, u32),
    HSL(u32, u32, u32),
    CMY(u32, u32, u32),
    CMYK(u32, u32, u32, u32),
}

/// Match - Desctuctured Enums
fn destructured_enums() {
    let color = Color::RGB(122, 17, 40);
    // TODO ^ Try different variants for `color`

    println!("What color is it?");
    // An `enum` can be destructured using a `match`.
    match color {
        Color::Red   => println!("The color is Red!"),
        Color::Blue  => println!("The color is Blue!"),
        Color::Green => println!("The color is Green!"),
        Color::RGB(r, g, b) =>
            println!("Red: {}, green: {}, and blue: {}!", r, g, b),
        Color::HSV(h, s, v) =>
            println!("Hue: {}, saturation: {}, value: {}!", h, s, v),
        Color::HSL(h, s, l) =>
            println!("Hue: {}, saturation: {}, lightness: {}!", h, s, l),
        Color::CMY(c, m, y) =>
            println!("Cyan: {}, magenta: {}, yellow: {}!", c, m, y),
        Color::CMYK(c, m, y, k) =>
            println!("Cyan: {}, magenta: {}, yellow: {}, key (black): {}!",
                c, m, y, k),
        // Don't need another arm because all variants have been examined
    }
}

fn destructured_pointers_ref() {
    // Assign a reference of type `i32`. The `&` signifies there
    // is a reference being assigned.
    let reference = &4;

    match reference {
        // If `reference`s is pattern matched against `&val`, it results
        // in a comparison like:
        // `&i32`
        // `&val`
        // ^ We see that if the matching `&`s are dropped, then the `i32`
        // should be assigned to `val`.
        &val => println!("Got a value via destructuring: {:?}", val),
    }

    // To avoid the `&`, you dereference before matching.
    match *reference {
        val => println!("Got a value via dereferencing: {:?}", val),
    }

    // What if you don't start with a reference? `reference` was a `&`
    // because the right side was already a reference. This is not
    // a reference because the right side is not one.
    let _not_a_reference = 3;

    // Rust provides `ref` for exactly this purpose. It modifies the
    // assignment so that a reference is created for the element; this
    // reference is assigned.
    let ref _is_a_reference = 3;

    // Accordingly, by defining 2 values without references, references
    // can be retrieved via `ref` and `ref mut`.
    let value = 5;
    let mut mut_value = 6;

    // Use `ref` keyword to create a reference.
    match value {
        ref r => println!("Got a reference to a value: {:?}", r),
    }

    // Use `ref mut` similarly.
    match mut_value {
        ref mut m => {
            // Got a reference. Gotta dereference it before we can
            // add anything to it.
            *m += 10;
            println!("We added 10. `mut_value`: {:?}", m);
        },
    }
}

fn destructured_structs() {
    struct Foo { x: (u32, u32), y: u32 }

    // destructure members of the struct
    let foo = Foo { x: (1, 2), y: 3 };
    let Foo { x: (a, b), y } = foo;

    println!("a = {}, b = {},  y = {} ", a, b, y);

    // you can destructure structs and rename the variables,
    // the order is not important

    let Foo { y: i, x: j } = foo;
    println!("i = {:?}, j = {:?}", i, j);

    // and you can also ignore some variables:
    let Foo { y, .. } = foo;
    println!("y = {}", y);

    // this will give an error: pattern does not mention field `x`
    // let Foo { y } = foo;
}

fn guards() {
    let pair = (2, -2);
    // TODO ^ Try different values for `pair`

    println!("Tell me about {:?}", pair);
    match pair {
        (x, y) if x == y => println!("guards |> These are twins"),
        // The ^ `if condition` part is a guard
        (x, y) if x + y == 0 => println!("guards |> Antimatter, kaboom!"),
        (x, _) if x % 2 == 1 => println!("guards |> The first one is odd"),
        _  => println!("guards |> No correlation..."),
    }
}<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! TcpRelay server that running on the server side

use std::io;
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::Arc;
use std::collections::HashSet;

use config::{Config, ServerConfig};

use crypto::CryptoMode;
use crypto::cipher;

use super::stream::{EncryptedWriter, DecryptedReader};

use relay::socks5::Address;

use futures::{self, Future, BoxFuture};
use futures::stream::Stream;

use futures_cpupool::CpuPool;

use tokio_core::reactor::Handle;
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::io::Io;
use tokio_core::io::{ReadHalf, WriteHalf};
use tokio_core::io::{read_exact, write_all, copy, flush};

use ip::IpAddr;

type ClientRead = ReadHalf<TcpStream>;
type ClientWrite = WriteHalf<TcpStream>;

type EncryptedHalf = EncryptedWriter<ClientWrite>;
type DecryptedHalf = DecryptedReader<ClientRead>;

/// TCP Relay backend
pub struct TcpRelayServer {
    config: Arc<Config>,
    cpu_pool: CpuPool,
}

impl TcpRelayServer {
    /// Creates an instance
    pub fn new(config: Arc<Config>, threads: usize) -> TcpRelayServer {
        TcpRelayServer {
            config: config,
            cpu_pool: CpuPool::new(threads),
        }
    }

    fn handshake((r, w): (ClientRead, ClientWrite),
                 svr_cfg: Arc<ServerConfig>)
                 -> BoxFuture<(DecryptedHalf, EncryptedHalf), io::Error> {
        let iv_len = svr_cfg.method.iv_size();

        let svr_cfg_cloned = svr_cfg.clone();
        let read_fut = read_exact(r, vec![0u8; iv_len]).and_then(move |(r, iv)| {
            trace!("Got handshake iv: {:?}", iv);
            let decryptor = cipher::with_type(svr_cfg.method,
                                              svr_cfg.password.as_bytes(),
                                              &iv[..],
                                              CryptoMode::Decrypt);
            let decrypt_stream = DecryptedReader::new(r, decryptor);

            Ok(decrypt_stream)
        });

        let write_fut = futures::lazy(move || {
            let svr_cfg = svr_cfg_cloned;

            let iv = svr_cfg.method.gen_init_vec();
            trace!("Going to send handshake iv: {:?}", iv);
            write_all(w, iv)
                .and_then(|(w, iv)| flush(w).map(|w| (w, iv)))
                .and_then(move |(w, iv)| {
                    let encryptor = cipher::with_type(svr_cfg.method,
                                                      svr_cfg.password.as_bytes(),
                                                      &iv[..],
                                                      CryptoMode::Encrypt);
                    let encrypt_stream = EncryptedWriter::new(w, encryptor);

                    Ok(encrypt_stream)
                })
        });

        read_fut.join(write_fut).boxed()
    }

    fn resolve_address(addr: Address, cpu_pool: CpuPool) -> BoxFuture<SocketAddr, io::Error> {
        match addr {
            Address::SocketAddress(addr) => futures::finished(addr).boxed(),
            Address::DomainNameAddress(dname, port) => {
                cpu_pool.spawn(futures::lazy(move || {
                        let dname = format!("{}:{}", dname, port);
                        let mut addrs = try!(dname.to_socket_addrs());
                        addrs.next().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to resolve domain"))
                    }))
                    .boxed()
            }
        }
    }

    fn resolve_remote(cpu_pool: CpuPool,
                      addr: Address,
                      forbidden_ip: Arc<HashSet<IpAddr>>)
                      -> BoxFuture<SocketAddr, io::Error> {
        TcpRelayServer::resolve_address(addr, cpu_pool)
            .and_then(move |addr| {
                trace!("Resolved address as {}", addr);
                let ipaddr = match addr.clone() {
                    SocketAddr::V4(v4) => IpAddr::V4(v4.ip().clone()),
                    SocketAddr::V6(v6) => IpAddr::V6(v6.ip().clone()),
                };

                if forbidden_ip.contains(&ipaddr) {
                    info!("{} has been forbidden", ipaddr);
                    let err = io::Error::new(io::ErrorKind::Other, "Forbidden IP");
                    Err(err)
                } else {
                    Ok(addr)
                }
            })
            .boxed()
    }

    fn connect_remote(cpu_pool: CpuPool,
                      handle: Handle,
                      addr: Address,
                      forbidden_ip: Arc<HashSet<IpAddr>>)
                      -> Box<Future<Item = TcpStream, Error = io::Error>> {
        trace!("Connecting to remote {}", addr);
        Box::new(TcpRelayServer::resolve_remote(cpu_pool, addr, forbidden_ip)
            .and_then(move |addr| TcpStream::connect(&addr, &handle)))
    }

    pub fn handle_client(handle: &Handle,
                         cpu_pool: CpuPool,
                         s: TcpStream,
                         svr_cfg: Arc<ServerConfig>,
                         forbidden_ip: Arc<HashSet<IpAddr>>)
                         -> io::Result<()> {
        let peer_addr = try!(s.peer_addr());
        trace!("Got connection from {}", peer_addr);

        let cloned_handle = handle.clone();
        let fut = futures::lazy(|| Ok(s.split()))
            .and_then(move |(r, w)| TcpRelayServer::handshake((r, w), svr_cfg))
            .and_then(|(r, w)| Address::read_from(r).map(|(r, addr)| (r, w, addr)).map_err(From::from))
            .and_then(move |(r, w, addr)| {
                info!("Connecting {}", addr);
                let cloned_addr = addr.clone();
                TcpRelayServer::connect_remote(cpu_pool, cloned_handle, addr, forbidden_ip)
                    .map(|svr_s| (svr_s, r, w, cloned_addr))
            })
            .and_then(|(svr_s, r, w, addr)| {
                let (svr_r, svr_w) = svr_s.split();
                let c2s = copy(r, svr_w);
                let s2c = copy(svr_r, w);
                c2s.select(s2c)
                    .then(move |_| {
                        trace!("Relay {} is finished", addr);
                        Ok(())
                    })
            });

        handle.spawn(fut.then(|res| {
            match res {
                Ok(..) => Ok(()),
                Err(err) => {
                    error!("Failed to handle client: {}", err);
                    Err(())
                }
            }
        }));

        Ok(())
    }

    /// Runs the server
    pub fn run(self, handle: Handle) -> Box<Future<Item = (), Error = io::Error>> {
        let mut fut: Option<Box<Future<Item = (), Error = io::Error>>> = None;

        for svr_cfg in &self.config.server {
            let listener = {
                let addr = &svr_cfg.addr;
                let listener = TcpListener::bind(addr, &handle).unwrap();
                trace!("ShadowSocks TCP Listening on {}", addr);
                listener
            };

            let svr_cfg = svr_cfg.clone();
            let handle = handle.clone();
            let forbidden_ip = self.config.forbidden_ip.clone();
            let cpu_pool = self.cpu_pool.clone();
            let listening = listener.incoming()
                .for_each(move |(socket, addr)| {
                    let server_cfg = svr_cfg.clone();
                    let forbidden_ip = forbidden_ip.clone();
                    let cpu_pool = cpu_pool.clone();

                    trace!("Got connection, addr: {}", addr);
                    trace!("Picked proxy server: {:?}", server_cfg);
                    TcpRelayServer::handle_client(&handle, cpu_pool, socket, server_cfg, forbidden_ip)
                })
                .map_err(|err| {
                    error!("Server run failed: {}", err);
                    err
                });

            fut = Some(match fut.take() {
                Some(fut) => Box::new(fut.join(listening).map(|_| ())) as Box<Future<Item = (), Error = io::Error>>,
                None => Box::new(listening) as Box<Future<Item = (), Error = io::Error>>,
            })
        }

        fut.expect("Must have at least one server")
    }
}
<commit_msg>Fixed partial relay by restoring select to join<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! TcpRelay server that running on the server side

use std::io;
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::Arc;
use std::collections::HashSet;

use config::{Config, ServerConfig};

use crypto::CryptoMode;
use crypto::cipher;

use super::stream::{EncryptedWriter, DecryptedReader};

use relay::socks5::Address;

use futures::{self, Future, BoxFuture};
use futures::stream::Stream;

use futures_cpupool::CpuPool;

use tokio_core::reactor::Handle;
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::io::Io;
use tokio_core::io::{ReadHalf, WriteHalf};
use tokio_core::io::{read_exact, write_all, copy, flush};

use ip::IpAddr;

type ClientRead = ReadHalf<TcpStream>;
type ClientWrite = WriteHalf<TcpStream>;

type EncryptedHalf = EncryptedWriter<ClientWrite>;
type DecryptedHalf = DecryptedReader<ClientRead>;

/// TCP Relay backend
pub struct TcpRelayServer {
    config: Arc<Config>,
    cpu_pool: CpuPool,
}

impl TcpRelayServer {
    /// Creates an instance
    pub fn new(config: Arc<Config>, threads: usize) -> TcpRelayServer {
        TcpRelayServer {
            config: config,
            cpu_pool: CpuPool::new(threads),
        }
    }

    fn handshake((r, w): (ClientRead, ClientWrite),
                 svr_cfg: Arc<ServerConfig>)
                 -> BoxFuture<(DecryptedHalf, EncryptedHalf), io::Error> {
        let iv_len = svr_cfg.method.iv_size();

        let svr_cfg_cloned = svr_cfg.clone();
        let read_fut = read_exact(r, vec![0u8; iv_len]).and_then(move |(r, iv)| {
            trace!("Got handshake iv: {:?}", iv);
            let decryptor = cipher::with_type(svr_cfg.method,
                                              svr_cfg.password.as_bytes(),
                                              &iv[..],
                                              CryptoMode::Decrypt);
            let decrypt_stream = DecryptedReader::new(r, decryptor);

            Ok(decrypt_stream)
        });

        let write_fut = futures::lazy(move || {
            let svr_cfg = svr_cfg_cloned;

            let iv = svr_cfg.method.gen_init_vec();
            trace!("Going to send handshake iv: {:?}", iv);
            write_all(w, iv)
                .and_then(|(w, iv)| flush(w).map(|w| (w, iv)))
                .and_then(move |(w, iv)| {
                    let encryptor = cipher::with_type(svr_cfg.method,
                                                      svr_cfg.password.as_bytes(),
                                                      &iv[..],
                                                      CryptoMode::Encrypt);
                    let encrypt_stream = EncryptedWriter::new(w, encryptor);

                    Ok(encrypt_stream)
                })
        });

        read_fut.join(write_fut).boxed()
    }

    fn resolve_address(addr: Address, cpu_pool: CpuPool) -> BoxFuture<SocketAddr, io::Error> {
        match addr {
            Address::SocketAddress(addr) => futures::finished(addr).boxed(),
            Address::DomainNameAddress(dname, port) => {
                cpu_pool.spawn(futures::lazy(move || {
                        let dname = format!("{}:{}", dname, port);
                        let mut addrs = try!(dname.to_socket_addrs());
                        addrs.next().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to resolve domain"))
                    }))
                    .boxed()
            }
        }
    }

    fn resolve_remote(cpu_pool: CpuPool,
                      addr: Address,
                      forbidden_ip: Arc<HashSet<IpAddr>>)
                      -> BoxFuture<SocketAddr, io::Error> {
        TcpRelayServer::resolve_address(addr, cpu_pool)
            .and_then(move |addr| {
                trace!("Resolved address as {}", addr);
                let ipaddr = match addr.clone() {
                    SocketAddr::V4(v4) => IpAddr::V4(v4.ip().clone()),
                    SocketAddr::V6(v6) => IpAddr::V6(v6.ip().clone()),
                };

                if forbidden_ip.contains(&ipaddr) {
                    info!("{} has been forbidden", ipaddr);
                    let err = io::Error::new(io::ErrorKind::Other, "Forbidden IP");
                    Err(err)
                } else {
                    Ok(addr)
                }
            })
            .boxed()
    }

    fn connect_remote(cpu_pool: CpuPool,
                      handle: Handle,
                      addr: Address,
                      forbidden_ip: Arc<HashSet<IpAddr>>)
                      -> Box<Future<Item = TcpStream, Error = io::Error>> {
        trace!("Connecting to remote {}", addr);
        Box::new(TcpRelayServer::resolve_remote(cpu_pool, addr, forbidden_ip)
            .and_then(move |addr| TcpStream::connect(&addr, &handle)))
    }

    pub fn handle_client(handle: &Handle,
                         cpu_pool: CpuPool,
                         s: TcpStream,
                         svr_cfg: Arc<ServerConfig>,
                         forbidden_ip: Arc<HashSet<IpAddr>>)
                         -> io::Result<()> {
        let peer_addr = try!(s.peer_addr());
        trace!("Got connection from {}", peer_addr);

        let cloned_handle = handle.clone();
        let fut = futures::lazy(|| Ok(s.split()))
            .and_then(move |(r, w)| TcpRelayServer::handshake((r, w), svr_cfg))
            .and_then(|(r, w)| Address::read_from(r).map(|(r, addr)| (r, w, addr)).map_err(From::from))
            .and_then(move |(r, w, addr)| {
                info!("Connecting {}", addr);
                let cloned_addr = addr.clone();
                TcpRelayServer::connect_remote(cpu_pool, cloned_handle, addr, forbidden_ip)
                    .map(|svr_s| (svr_s, r, w, cloned_addr))
            })
            .and_then(|(svr_s, r, w, addr)| {
                let (svr_r, svr_w) = svr_s.split();
                let c2s = copy(r, svr_w);
                let s2c = copy(svr_r, w);
                c2s.join(s2c)
                    .then(move |_| {
                        trace!("Relay {} is finished", addr);
                        Ok(())
                    })
            });

        handle.spawn(fut.then(|res| {
            match res {
                Ok(..) => Ok(()),
                Err(err) => {
                    error!("Failed to handle client: {}", err);
                    Err(())
                }
            }
        }));

        Ok(())
    }

    /// Runs the server
    pub fn run(self, handle: Handle) -> Box<Future<Item = (), Error = io::Error>> {
        let mut fut: Option<Box<Future<Item = (), Error = io::Error>>> = None;

        for svr_cfg in &self.config.server {
            let listener = {
                let addr = &svr_cfg.addr;
                let listener = TcpListener::bind(addr, &handle).unwrap();
                trace!("ShadowSocks TCP Listening on {}", addr);
                listener
            };

            let svr_cfg = svr_cfg.clone();
            let handle = handle.clone();
            let forbidden_ip = self.config.forbidden_ip.clone();
            let cpu_pool = self.cpu_pool.clone();
            let listening = listener.incoming()
                .for_each(move |(socket, addr)| {
                    let server_cfg = svr_cfg.clone();
                    let forbidden_ip = forbidden_ip.clone();
                    let cpu_pool = cpu_pool.clone();

                    trace!("Got connection, addr: {}", addr);
                    trace!("Picked proxy server: {:?}", server_cfg);
                    TcpRelayServer::handle_client(&handle, cpu_pool, socket, server_cfg, forbidden_ip)
                })
                .map_err(|err| {
                    error!("Server run failed: {}", err);
                    err
                });

            fut = Some(match fut.take() {
                Some(fut) => Box::new(fut.join(listening).map(|_| ())) as Box<Future<Item = (), Error = io::Error>>,
                None => Box::new(listening) as Box<Future<Item = (), Error = io::Error>>,
            })
        }

        fut.expect("Must have at least one server")
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobProvide {
    id: i32,
    fk_job: i32,
    fk_provider: i32,
}

pub fn table_create_job_provide(conn: &Connection) -> Result<(), &'static str> {
    let load_table = conn.execute_batch(
        "CREATE TABLE JOBPROVIDE (
                  id            INTEGER PRIMARY KEY ASC,
                  fk_job           INTEGER,
                  fk_provider      INTEGER,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_provider) REFERENCES PROVIDER(id) ON UPDATE CASCADE
                  )",
    );
    if load_table.is_err() {
        return Err("table_create_session Failed");
    }
    load_table.unwrap();
    return Ok(());
}

pub fn insert_job_provide(
    conn: &Connection,
    job: &i32,
    provider: &i32,
) -> Result<i32, &'static str> {

    let me = JobProvide {
        id: 0,
        fk_job: *job,
        fk_provider: *provider,
    };
    let load_instance = conn.execute(
        "INSERT INTO JOBPROVIDE (fk_job, fk_provider)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_provider],
    );
    if load_instance.is_err() {
        return Err("Insert failed");
    }
    load_instance.unwrap();
    return Ok(0);
}

pub fn list_job_provide(conn: &Connection) -> Vec<JobProvide> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_provider FROM JOBPROVIDE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobProvide {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
        }
    });
    let mut items = Vec::<JobProvide>::new();
    if wraped_fs_file_iter.is_err() {
        return items;
    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_provide_by_all(
    conn: &Connection,
    fk_job: &i32,
    provider: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT JOBPROVIDE.id, JOBPROVIDE.fk_job, JOBPROVIDE.fk_provider FROM JOBPROVIDE WHERE JOBPROVIDE.fk_job = ?1 AND JOBPROVIDE.fk_provider=?2").unwrap();
    let job_provide_iter = stmt.query_map(&[fk_job, provider], |row| {
        JobProvide {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
        }
    });
    if job_provide_iter.is_err() {
        return Err("Insert failed");
    }
    let result = job_provide_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<commit_msg>Remove unused variables<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobProvide {
    id: i32,
    fk_job: i32,
    fk_provider: i32,
}

pub fn table_create_job_provide(conn: &Connection) -> Result<(), &'static str> {
    let load_table = conn.execute_batch(
        "CREATE TABLE JOBPROVIDE (
                  id            INTEGER PRIMARY KEY ASC,
                  fk_job           INTEGER,
                  fk_provider      INTEGER,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_provider) REFERENCES PROVIDER(id) ON UPDATE CASCADE
                  )",
    );
    if load_table.is_err() {
        return Err("table_create_session Failed");
    }
    load_table.unwrap();
    return Ok(());
}

pub fn insert_job_provide(
    conn: &Connection,
    job: &i32,
    provider: &i32,
) -> Result<i32, &'static str> {

    let me = JobProvide {
        id: 0,
        fk_job: *job,
        fk_provider: *provider,
    };
    let load_instance = conn.execute(
        "INSERT INTO JOBPROVIDE (fk_job, fk_provider)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_provider],
    );
    if load_instance.is_err() {
        return Err("Insert failed");
    }
    load_instance.unwrap();
    return Ok(0);
}

pub fn list_job_provide(conn: &Connection) -> Vec<JobProvide> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_provider FROM JOBPROVIDE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobProvide {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
        }
    });
    let mut items = Vec::<JobProvide>::new();
    if wraped_fs_file_iter.is_err() {
        return items;
    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_provide_by_all(
    conn: &Connection,
    fk_job: &i32,
    provider: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT JOBPROVIDE.id, JOBPROVIDE.fk_job, JOBPROVIDE.fk_provider FROM JOBPROVIDE WHERE JOBPROVIDE.fk_job = ?1 AND JOBPROVIDE.fk_provider=?2").unwrap();
    let job_provide_iter = stmt.query_map(&[fk_job, provider], |row| {
        JobProvide {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
        }
    });
    if job_provide_iter.is_err() {
        return Err("Insert failed");
    }
    let result = job_provide_iter.unwrap();
    let mut found = 0;
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>use tokenizer::new;
use tokenizer::Tokenizer;
use tokenizer::StateFunction;
use token::Token;
use token::Category;

fn initial_state(lexer: &mut Tokenizer) -> Option<StateFunction> {
    match lexer.current_char() {
        Some(c) => {
            match c {
                '{' => {
                    lexer.tokenize_next(1, Category::Brace);
                },
                '[' => {
                    lexer.tokenize_next(1, Category::Bracket);
                },
                ' ' | '\n' => {
                    lexer.tokenize(Category::Text);
                    lexer.advance();
                    return Some(StateFunction(whitespace));
                },
                '"' => {
                    lexer.tokenize(Category::Text);
                    lexer.advance();
                    return Some(StateFunction(inside_string));
                },
                ':' => {
                    lexer.tokenize_next(1, Category::AssignmentOperator);
                },
                '}' => {
                    lexer.tokenize_next(1, Category::Brace);
                },
                ']' => {
                    lexer.tokenize_next(1, Category::Bracket);
                },
                _ => {
                    if lexer.token_position == lexer.token_start {
                        let remaining_data =
                            lexer.data[lexer.token_position..].to_string();

                        if remaining_data.starts_with("true") {
                            lexer.tokenize_next(4, Category::Boolean);
                        } else if remaining_data.starts_with("false") {
                            lexer.tokenize_next(5, Category::Boolean);
                        } else if remaining_data.starts_with("null") {
                            lexer.tokenize_next(4, Category::Keyword);
                        } else {
                            lexer.advance();
                        }
                    } else {
                        lexer.advance();
                    }
                }
            }

            Some(StateFunction(initial_state))
        }

        None => {
            lexer.tokenize(Category::Text);
            None
        }
    }
}

fn inside_string(lexer: &mut Tokenizer) -> Option<StateFunction> {
    match lexer.current_char() {
        Some(c) => {
            match c {
                '"' => {
                    lexer.advance();
                    lexer.tokenize(Category::String);
                    Some(StateFunction(initial_state))
                },
                '\\' => {
                    lexer.advance();
                    lexer.advance();
                    Some(StateFunction(inside_string))
                }
                _ => {
                    lexer.advance();
                    Some(StateFunction(inside_string))
                }
            }
        }

        None => {
            lexer.tokenize(Category::String);
            None
        }
    }
}

fn whitespace(lexer: &mut Tokenizer) -> Option<StateFunction> {
    match lexer.current_char() {
        Some(c) => {
            match c {
                ' ' | '\n' => {
                    lexer.advance();
                    Some(StateFunction(whitespace))
                },
                _ => {
                    lexer.tokenize(Category::Whitespace);
                    Some(StateFunction(initial_state))
                }
            }
        }

        None => {
            lexer.tokenize(Category::Whitespace);
            None
        }
    }
}

pub fn lex(data: &str) -> Vec<Token> {
    let mut lexer = new(data);
    let mut state_function = StateFunction(initial_state);
    loop {
        let StateFunction(actual_function) = state_function;
        match actual_function(&mut lexer) {
            Some(f) => state_function = f,
            None => return lexer.tokens(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::lex;
    use token::Token;
    use token::Category;
    use std::old_io::{File, Open, Read};

    #[test]
    fn it_works() {
        let data = File::open_mode(&Path::new("test_data/data.json"), Open, Read)
            .unwrap().read_to_string().unwrap();
        let tokens = lex(&data);
        let expected_tokens = vec![
            Token{ lexeme: "{".to_string(), category: Category::Brace },
            Token{ lexeme: "\n  ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "\"key\"".to_string(), category: Category::String },
            Token{ lexeme: ":".to_string(), category: Category::AssignmentOperator },
            Token{ lexeme: " ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "\"4032\"".to_string(), category: Category::String },
            Token{ lexeme: ",".to_string(), category: Category::Text },
            Token{ lexeme: "\n  ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "'single'".to_string(), category: Category::Text },
            Token{ lexeme: ":".to_string(), category: Category::AssignmentOperator },
            Token{ lexeme: " ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "'quotes\\'',".to_string(), category: Category::Text },
            Token{ lexeme: "\n  ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "\"literals\"".to_string(), category: Category::String },
            Token{ lexeme: ":".to_string(), category: Category::AssignmentOperator },
            Token{ lexeme: " ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "[".to_string(), category: Category::Bracket },
            Token{ lexeme: "\n    ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "true".to_string(), category: Category::Boolean },
            Token{ lexeme: ",".to_string(), category: Category::Text },
            Token{ lexeme: "\n    ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "false".to_string(), category: Category::Boolean },
            Token{ lexeme: ",".to_string(), category: Category::Text },
            Token{ lexeme: "\n    ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "null".to_string(), category: Category::Keyword },
            Token{ lexeme: "\n  ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "]".to_string(), category: Category::Bracket },
            Token{ lexeme: "\n".to_string(), category: Category::Whitespace },
            Token{ lexeme: "}".to_string(), category: Category::Brace },
            Token{ lexeme: "\n".to_string(), category: Category::Whitespace },
        ];

        for (index, token) in tokens.iter().enumerate() {
            assert_eq!(*token, expected_tokens[index]);
        }
    }

    #[test]
    fn it_can_handle_garbage() {
        let tokens = lex("} adwyx123&*_ ");
        let expected_tokens = vec![
            Token{ lexeme: "}".to_string(), category: Category::Brace },
            Token{ lexeme: " ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "adwyx123&*_".to_string(), category: Category::Text },
            Token{ lexeme: " ".to_string(), category: Category::Whitespace },
        ];

        for (index, token) in tokens.iter().enumerate() {
            assert_eq!(*token, expected_tokens[index]);
        }
    }

    #[test]
    fn it_can_handle_open_strings() {
        let tokens = lex("\"open!");
        let expected_tokens = vec![
            Token{ lexeme: "\"open!".to_string(), category: Category::String },
        ];

        for (index, token) in tokens.iter().enumerate() {
            assert_eq!(*token, expected_tokens[index]);
        }
    }

    #[test]
    fn it_can_handle_utf8_data() {
        let tokens = lex("différent");
        let expected_tokens = vec![
            Token{ lexeme: "différent".to_string(), category: Category::Text },
        ];

        for (index, token) in tokens.iter().enumerate() {
            assert_eq!(*token, expected_tokens[index]);
        }
    }
}
<commit_msg>Include `test_data/data.json` as static string into tests.<commit_after>use tokenizer::new;
use tokenizer::Tokenizer;
use tokenizer::StateFunction;
use token::Token;
use token::Category;

fn initial_state(lexer: &mut Tokenizer) -> Option<StateFunction> {
    match lexer.current_char() {
        Some(c) => {
            match c {
                '{' => {
                    lexer.tokenize_next(1, Category::Brace);
                },
                '[' => {
                    lexer.tokenize_next(1, Category::Bracket);
                },
                ' ' | '\n' => {
                    lexer.tokenize(Category::Text);
                    lexer.advance();
                    return Some(StateFunction(whitespace));
                },
                '"' => {
                    lexer.tokenize(Category::Text);
                    lexer.advance();
                    return Some(StateFunction(inside_string));
                },
                ':' => {
                    lexer.tokenize_next(1, Category::AssignmentOperator);
                },
                '}' => {
                    lexer.tokenize_next(1, Category::Brace);
                },
                ']' => {
                    lexer.tokenize_next(1, Category::Bracket);
                },
                _ => {
                    if lexer.token_position == lexer.token_start {
                        let remaining_data =
                            lexer.data[lexer.token_position..].to_string();

                        if remaining_data.starts_with("true") {
                            lexer.tokenize_next(4, Category::Boolean);
                        } else if remaining_data.starts_with("false") {
                            lexer.tokenize_next(5, Category::Boolean);
                        } else if remaining_data.starts_with("null") {
                            lexer.tokenize_next(4, Category::Keyword);
                        } else {
                            lexer.advance();
                        }
                    } else {
                        lexer.advance();
                    }
                }
            }

            Some(StateFunction(initial_state))
        }

        None => {
            lexer.tokenize(Category::Text);
            None
        }
    }
}

fn inside_string(lexer: &mut Tokenizer) -> Option<StateFunction> {
    match lexer.current_char() {
        Some(c) => {
            match c {
                '"' => {
                    lexer.advance();
                    lexer.tokenize(Category::String);
                    Some(StateFunction(initial_state))
                },
                '\\' => {
                    lexer.advance();
                    lexer.advance();
                    Some(StateFunction(inside_string))
                }
                _ => {
                    lexer.advance();
                    Some(StateFunction(inside_string))
                }
            }
        }

        None => {
            lexer.tokenize(Category::String);
            None
        }
    }
}

fn whitespace(lexer: &mut Tokenizer) -> Option<StateFunction> {
    match lexer.current_char() {
        Some(c) => {
            match c {
                ' ' | '\n' => {
                    lexer.advance();
                    Some(StateFunction(whitespace))
                },
                _ => {
                    lexer.tokenize(Category::Whitespace);
                    Some(StateFunction(initial_state))
                }
            }
        }

        None => {
            lexer.tokenize(Category::Whitespace);
            None
        }
    }
}

pub fn lex(data: &str) -> Vec<Token> {
    let mut lexer = new(data);
    let mut state_function = StateFunction(initial_state);
    loop {
        let StateFunction(actual_function) = state_function;
        match actual_function(&mut lexer) {
            Some(f) => state_function = f,
            None => return lexer.tokens(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::lex;
    use token::Token;
    use token::Category;

    #[test]
    fn it_works() {
        let data = include_str!("../../test_data/data.json");
        let tokens = lex(data);
        let expected_tokens = vec![
            Token{ lexeme: "{".to_string(), category: Category::Brace },
            Token{ lexeme: "\n  ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "\"key\"".to_string(), category: Category::String },
            Token{ lexeme: ":".to_string(), category: Category::AssignmentOperator },
            Token{ lexeme: " ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "\"4032\"".to_string(), category: Category::String },
            Token{ lexeme: ",".to_string(), category: Category::Text },
            Token{ lexeme: "\n  ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "'single'".to_string(), category: Category::Text },
            Token{ lexeme: ":".to_string(), category: Category::AssignmentOperator },
            Token{ lexeme: " ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "'quotes\\'',".to_string(), category: Category::Text },
            Token{ lexeme: "\n  ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "\"literals\"".to_string(), category: Category::String },
            Token{ lexeme: ":".to_string(), category: Category::AssignmentOperator },
            Token{ lexeme: " ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "[".to_string(), category: Category::Bracket },
            Token{ lexeme: "\n    ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "true".to_string(), category: Category::Boolean },
            Token{ lexeme: ",".to_string(), category: Category::Text },
            Token{ lexeme: "\n    ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "false".to_string(), category: Category::Boolean },
            Token{ lexeme: ",".to_string(), category: Category::Text },
            Token{ lexeme: "\n    ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "null".to_string(), category: Category::Keyword },
            Token{ lexeme: "\n  ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "]".to_string(), category: Category::Bracket },
            Token{ lexeme: "\n".to_string(), category: Category::Whitespace },
            Token{ lexeme: "}".to_string(), category: Category::Brace },
            Token{ lexeme: "\n".to_string(), category: Category::Whitespace },
        ];

        for (index, token) in tokens.iter().enumerate() {
            assert_eq!(*token, expected_tokens[index]);
        }
    }

    #[test]
    fn it_can_handle_garbage() {
        let tokens = lex("} adwyx123&*_ ");
        let expected_tokens = vec![
            Token{ lexeme: "}".to_string(), category: Category::Brace },
            Token{ lexeme: " ".to_string(), category: Category::Whitespace },
            Token{ lexeme: "adwyx123&*_".to_string(), category: Category::Text },
            Token{ lexeme: " ".to_string(), category: Category::Whitespace },
        ];

        for (index, token) in tokens.iter().enumerate() {
            assert_eq!(*token, expected_tokens[index]);
        }
    }

    #[test]
    fn it_can_handle_open_strings() {
        let tokens = lex("\"open!");
        let expected_tokens = vec![
            Token{ lexeme: "\"open!".to_string(), category: Category::String },
        ];

        for (index, token) in tokens.iter().enumerate() {
            assert_eq!(*token, expected_tokens[index]);
        }
    }

    #[test]
    fn it_can_handle_utf8_data() {
        let tokens = lex("différent");
        let expected_tokens = vec![
            Token{ lexeme: "différent".to_string(), category: Category::Text },
        ];

        for (index, token) in tokens.iter().enumerate() {
            assert_eq!(*token, expected_tokens[index]);
        }
    }
}
<|endoftext|>


<commit_before>use core::iter::TrustedLen;
use core::ptr::{self};

use super::{SpecExtend, Vec};

/// Another specialization trait for Vec::from_iter
/// necessary to manually prioritize overlapping specializations
/// see [`SpecFromIter`] for details.
pub(super) trait SpecFromIterNested<T, I> {
    fn from_iter(iter: I) -> Self;
}

impl<T, I> SpecFromIterNested<T, I> for Vec<T>
where
    I: Iterator<Item = T>,
{
    default fn from_iter(mut iterator: I) -> Self {
        // Unroll the first iteration, as the vector is going to be
        // expanded on this iteration in every case when the iterable is not
        // empty, but the loop in extend_desugared() is not going to see the
        // vector being full in the few subsequent loop iterations.
        // So we get better branch prediction.
        let mut vector = match iterator.next() {
            None => return Vec::new(),
            Some(element) => {
                let (lower, _) = iterator.size_hint();
                let mut vector = Vec::with_capacity(lower.saturating_add(1));
                unsafe {
                    ptr::write(vector.as_mut_ptr(), element);
                    vector.set_len(1);
                }
                vector
            }
        };
        // must delegate to spec_extend() since extend() itself delegates
        // to spec_from for empty Vecs
        <Vec<T> as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);
        vector
    }
}

impl<T, I> SpecFromIterNested<T, I> for Vec<T>
where
    I: TrustedLen<Item = T>,
{
    fn from_iter(iterator: I) -> Self {
        let mut vector = match iterator.size_hint() {
            (_, Some(upper)) => Vec::with_capacity(upper),
            _ => Vec::new(),
        };
        // must delegate to spec_extend() since extend() itself delegates
        // to spec_from for empty Vecs
        vector.spec_extend(iterator);
        vector
    }
}
<commit_msg>Rollup merge of #81179 - CPerezz:fix_interal_doc_warns, r=jyn514<commit_after>use core::iter::TrustedLen;
use core::ptr::{self};

use super::{SpecExtend, Vec};

/// Another specialization trait for Vec::from_iter
/// necessary to manually prioritize overlapping specializations
/// see [`SpecFromIter`](super::SpecFromIter) for details.
pub(super) trait SpecFromIterNested<T, I> {
    fn from_iter(iter: I) -> Self;
}

impl<T, I> SpecFromIterNested<T, I> for Vec<T>
where
    I: Iterator<Item = T>,
{
    default fn from_iter(mut iterator: I) -> Self {
        // Unroll the first iteration, as the vector is going to be
        // expanded on this iteration in every case when the iterable is not
        // empty, but the loop in extend_desugared() is not going to see the
        // vector being full in the few subsequent loop iterations.
        // So we get better branch prediction.
        let mut vector = match iterator.next() {
            None => return Vec::new(),
            Some(element) => {
                let (lower, _) = iterator.size_hint();
                let mut vector = Vec::with_capacity(lower.saturating_add(1));
                unsafe {
                    ptr::write(vector.as_mut_ptr(), element);
                    vector.set_len(1);
                }
                vector
            }
        };
        // must delegate to spec_extend() since extend() itself delegates
        // to spec_from for empty Vecs
        <Vec<T> as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);
        vector
    }
}

impl<T, I> SpecFromIterNested<T, I> for Vec<T>
where
    I: TrustedLen<Item = T>,
{
    fn from_iter(iterator: I) -> Self {
        let mut vector = match iterator.size_hint() {
            (_, Some(upper)) => Vec::with_capacity(upper),
            _ => Vec::new(),
        };
        // must delegate to spec_extend() since extend() itself delegates
        // to spec_from for empty Vecs
        vector.spec_extend(iterator);
        vector
    }
}
<|endoftext|>


<commit_before>//! Representations of voice information.

use super::id::{ChannelId, UserId};

/// Information about an available voice region.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VoiceRegion {
    /// Whether it is a custom voice region, which is used for events.
    pub custom: bool,
    /// Whether it is a deprecated voice region, which you should avoid using.
    pub deprecated: bool,
    /// The internal Id of the voice region.
    pub id: String,
    /// A recognizable name of the location of the voice region.
    pub name: String,
    /// Whether the voice region is optimal for use by the current user.
    pub optional: bool,
    /// an example hostname.
    pub sample_hostname: String,
    /// An example port.
    pub sample_port: u64,
    /// Indicator of whether the voice region is only for VIP guilds.
    pub vip: bool,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

/// A user's state within a voice channel.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VoiceState {
    pub channel_id: Option<ChannelId>,
    pub deaf: bool,
    pub mute: bool,
    pub self_deaf: bool,
    pub self_mute: bool,
    pub session_id: String,
    pub suppress: bool,
    pub token: Option<String>,
    pub user_id: UserId,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}
<commit_msg>Add `self_stream` field to `VoiceState` (#895)<commit_after>//! Representations of voice information.

use super::id::{ChannelId, UserId};

/// Information about an available voice region.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VoiceRegion {
    /// Whether it is a custom voice region, which is used for events.
    pub custom: bool,
    /// Whether it is a deprecated voice region, which you should avoid using.
    pub deprecated: bool,
    /// The internal Id of the voice region.
    pub id: String,
    /// A recognizable name of the location of the voice region.
    pub name: String,
    /// Whether the voice region is optimal for use by the current user.
    pub optional: bool,
    /// an example hostname.
    pub sample_hostname: String,
    /// An example port.
    pub sample_port: u64,
    /// Indicator of whether the voice region is only for VIP guilds.
    pub vip: bool,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

/// A user's state within a voice channel.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VoiceState {
    pub channel_id: Option<ChannelId>,
    pub deaf: bool,
    pub mute: bool,
    pub self_deaf: bool,
    pub self_mute: bool,
    pub self_stream: Option<bool>,
    pub session_id: String,
    pub suppress: bool,
    pub token: Option<String>,
    pub user_id: UserId,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}
<|endoftext|>