<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.
//!
//! *[See also the array primitive type](../primitive.array.html).*

#![unstable(feature = "fixed_size_array",
            reason = "traits and impls are better expressed through generic \
                      integer constants",
            issue = "27778")]

use borrow::{Borrow, BorrowMut};
use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use convert::{AsRef, AsMut};
use default::Default;
use fmt;
use hash::{Hash, self};
use iter::IntoIterator;
use marker::{Sized, Unsize};
use option::Option;
use slice::{Iter, IterMut, SliceExt};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
///
/// The trait is marked unsafe in order to restrict implementors to fixed-size
/// arrays. User of this trait can assume that implementors have the exact
/// layout in memory of a fixed size array (for example, for unsafe
/// initialization).
///
/// Note that the traits AsRef and AsMut provide similar methods for types that
/// may not be fixed-size arrays. Implementors should prefer those traits
/// instead.
pub unsafe trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    fn as_mut_slice(&mut self) -> &mut [T];
}

unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
    #[inline]
    fn as_slice(&self) -> &[T] {
        self
    }
    #[inline]
    fn as_mut_slice(&mut self) -> &mut [T] {
        self
    }
}

// macro for implementing n-ary tuple functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            impl<T> AsMut<[T]> for [T; $N] {
                #[inline]
                fn as_mut(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> Borrow<[T]> for [T; $N] {
                fn borrow(&self) -> &[T] {
                    self
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> BorrowMut<[T]> for [T; $N] {
                fn borrow_mut(&mut self) -> &mut [T] {
                    self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

// The Default impls cannot be generated using the array_impls! macro because
// they require array literals.

macro_rules! array_impl_default {
    {$n:expr, $t:ident $($ts:ident)*} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] where T: Default {
            fn default() -> [T; $n] {
                [$t::default(), $($ts::default()),*]
            }
        }
        array_impl_default!{($n - 1), $($ts)*}
    };
    {$n:expr,} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] {
            fn default() -> [T; $n] { [] }
        }
    };
}

array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}

macro_rules! array_impl_clone {
    {$n:expr, $i:expr, $($idx:expr,)*} => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<T: Clone> Clone for [T; $n] {
            fn clone(&self) -> [T; $n] {
                let temp = [&self[$i], $(&self[$idx]),*];
                [temp[$i].clone(), $(temp[$idx].clone()),*]
            }
        }
        array_impl_clone!{$i, $($idx,)*}
    };
    {$n:expr,} => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<T: Clone> Clone for [T; 0] {
            fn clone(&self) -> [T; 0] {
                []
            }
        }
    };
}

array_impl_clone! {
                                32, 31, 30,
    29, 28, 27, 26, 25, 24, 23, 22, 21, 20,
    19, 18, 17, 16, 15, 14, 13, 12, 11, 10,
     9,  8,  7,  6,  5,  4,  3,  2,  1,  0,
}
<commit_msg>Don't use an explicit temporary for cloning an array<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.
//!
//! *[See also the array primitive type](../primitive.array.html).*

#![unstable(feature = "fixed_size_array",
            reason = "traits and impls are better expressed through generic \
                      integer constants",
            issue = "27778")]

use borrow::{Borrow, BorrowMut};
use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use convert::{AsRef, AsMut};
use default::Default;
use fmt;
use hash::{Hash, self};
use iter::IntoIterator;
use marker::{Sized, Unsize};
use option::Option;
use slice::{Iter, IterMut, SliceExt};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
///
/// The trait is marked unsafe in order to restrict implementors to fixed-size
/// arrays. User of this trait can assume that implementors have the exact
/// layout in memory of a fixed size array (for example, for unsafe
/// initialization).
///
/// Note that the traits AsRef and AsMut provide similar methods for types that
/// may not be fixed-size arrays. Implementors should prefer those traits
/// instead.
pub unsafe trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    fn as_mut_slice(&mut self) -> &mut [T];
}

unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
    #[inline]
    fn as_slice(&self) -> &[T] {
        self
    }
    #[inline]
    fn as_mut_slice(&mut self) -> &mut [T] {
        self
    }
}

// macro for implementing n-ary tuple functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            impl<T> AsMut<[T]> for [T; $N] {
                #[inline]
                fn as_mut(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> Borrow<[T]> for [T; $N] {
                fn borrow(&self) -> &[T] {
                    self
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> BorrowMut<[T]> for [T; $N] {
                fn borrow_mut(&mut self) -> &mut [T] {
                    self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

// The Default impls cannot be generated using the array_impls! macro because
// they require array literals.

macro_rules! array_impl_default {
    {$n:expr, $t:ident $($ts:ident)*} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] where T: Default {
            fn default() -> [T; $n] {
                [$t::default(), $($ts::default()),*]
            }
        }
        array_impl_default!{($n - 1), $($ts)*}
    };
    {$n:expr,} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] {
            fn default() -> [T; $n] { [] }
        }
    };
}

array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}

macro_rules! array_impl_clone {
    {$n:expr, $i:expr, $($idx:expr,)*} => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<T: Clone> Clone for [T; $n] {
            fn clone(&self) -> [T; $n] {
                [self[$i-$i].clone(), $(self[$i-$idx].clone()),*]
            }
        }
        array_impl_clone!{$i, $($idx,)*}
    };
    {$n:expr,} => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<T: Clone> Clone for [T; 0] {
            fn clone(&self) -> [T; 0] {
                []
            }
        }
    };
}

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


<commit_before>// Type inference

use core::{Match, Src, Scope, Session};
use nameres::resolve_path_with_str;
use core::Namespace::TypeNamespace;
use core;
use ast;
use scopes;
use matchers;
use core::SearchType::ExactMatch;
use util::txt_matches;

fn find_start_of_function_body(src: &str) -> usize {
    // TODO: this should ignore anything inside parens so as to skip the arg list
    src.find('{').unwrap()
}

// Removes the body of the statement (anything in the braces {...}), leaving just
// the header
// TODO: this should skip parens (e.g. function arguments)
pub fn generate_skeleton_for_parsing(src: &str) -> String {
    let mut s = String::new();
    let n = src.find('{').unwrap();
    s.push_str(&src[..n+1]);
    s.push_str("};");
    s
}

pub fn first_param_is_self(blob: &str) -> bool {
    // skip generic arg
    // consider 'pub fn map<U, F: FnOnce(T) -> U>(self, f: F)'
    // we have to match the '>'
    match blob.find('(') {
        None => false,
        Some(probable_param_start) => {
            let skip_generic = match blob.find('<') {
                None => 0,
                Some(generic_start) if generic_start < probable_param_start => {
                    let mut level = 0;
                    let mut prev = ' ';
                    let mut skip_generic = 0;
                    for (i, c) in blob.char_indices() {
                        match c {
                            '<' => level += 1,
                            '>' if prev == '-' => (),
                            '>' => level -= 1,
                            _ => (),
                        }
                        prev = c;
                        if level == 0 {
                            skip_generic = i;
                        }
                    }
                    skip_generic
                },
                Some(..) => 0,
            };
            while let Some(start) = blob[skip_generic..].find('(') {
                let end = scopes::find_closing_paren(blob, start + 1);
                let is_self = txt_matches(ExactMatch, "self", &blob[(start + 1)..end]);
                debug!("searching fn args: |{}| {}",
                       &blob[(start + 1)..end],
                       is_self);
                return is_self;
            }
            false
        }
    }
}

#[test]
fn generates_skeleton_for_mod() {
    let src = "mod foo { blah };";
    let out = generate_skeleton_for_parsing(src);
    assert_eq!("mod foo {};", out);
}

fn get_type_of_self_arg(m: &Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    debug!("get_type_of_self_arg {:?}", m);
    scopes::find_impl_start(msrc, m.point, 0).and_then(|start| {
        let decl = generate_skeleton_for_parsing(&msrc.from(start));
        debug!("get_type_of_self_arg impl skeleton |{}|", decl);

        if decl.starts_with("impl") {
            let implres = ast::parse_impl(decl);
            debug!("get_type_of_self_arg implres |{:?}|", implres);
            resolve_path_with_str(&implres.name_path.expect("failed parsing impl name"),
                                  &m.filepath, start,
                                  ExactMatch, TypeNamespace,
                                  session).nth(0).map(core::Ty::Match)
        } else {
            // // must be a trait
            ast::parse_trait(decl).name.and_then(|name| {
                Some(core::Ty::Match(Match {
                           matchstr: name,
                           filepath: m.filepath.clone(),
                           point: start,
                           local: m.local,
                           mtype: core::MatchType::Trait,
                           contextstr: matchers::first_line(&msrc[start..]),
                           generic_args: Vec::new(),
                           generic_types: Vec::new(),
                           docs: String::new(),
                }))
            })
        }
    })
}

fn get_type_of_fnarg(m: &Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    if m.matchstr == "self" {
        return get_type_of_self_arg(m, msrc, session);
    }

    let stmtstart = scopes::find_stmt_start(msrc, m.point).unwrap();
    let block = msrc.from(stmtstart);
    if let Some((start, end)) = block.iter_stmts().next() {
        let blob = &msrc[(stmtstart+start)..(stmtstart+end)];
        // wrap in "impl blah { }" so that methods get parsed correctly too
        let mut s = String::new();
        s.push_str("impl blah {");
        let impl_header_len = s.len();
        s.push_str(&blob[..(find_start_of_function_body(blob)+1)]);
        s.push_str("}}");
        let argpos = m.point - (stmtstart+start) + impl_header_len;
        return ast::parse_fn_arg_type(s, argpos, Scope::from_match(m), session);
    }
    None
}

fn get_type_of_let_expr(m: &Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    // ASSUMPTION: this is being called on a let decl
    let point = scopes::find_stmt_start(msrc, m.point).unwrap();
    let src = msrc.from(point);

    if let Some((start, end)) = src.iter_stmts().next() {
        let blob = &src[start..end];
        debug!("get_type_of_let_expr calling parse_let |{}|", blob);

        let pos = m.point - point - start;
        let scope = Scope{ filepath: m.filepath.clone(), point: m.point };
        ast::get_let_type(blob.to_owned(), pos, scope, session)
    } else {
        None
    }
}

fn get_type_of_let_block_expr(m: &Match, msrc: Src, session: &Session, prefix: &str) -> Option<core::Ty> {
    // ASSUMPTION: this is being called on an if let or while let decl
    let stmtstart = scopes::find_stmt_start(msrc, m.point).unwrap();
    let stmt = msrc.from(stmtstart);
    let point = stmt.find(prefix).unwrap();
    let src = core::new_source(generate_skeleton_for_parsing(&stmt[point..]));

    if let Some((start, end)) = src.as_src().iter_stmts().next() {
        let blob = &src[start..end];
        debug!("get_type_of_let_block_expr calling get_let_type |{}|", blob);

        let pos = m.point - stmtstart - point - start;
        let scope = Scope{ filepath: m.filepath.clone(), point: m.point };
        ast::get_let_type(blob.to_owned(), pos, scope, session)
    } else {
        None
    }
}

fn get_type_of_for_expr(m: &Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    let stmtstart = scopes::find_stmt_start(msrc, m.point).unwrap();
    let stmt = msrc.from(stmtstart);
    let forpos = stmt.find("for ").unwrap();
    let inpos = stmt.find(" in ").unwrap();
    // XXX: this need not be the correct brace, see generate_skeleton_for_parsing
    let bracepos = stmt.find('{').unwrap();
    let mut src = stmt[..forpos].to_owned();
    src.push_str("if let Some(");
    src.push_str(&stmt[forpos+4..inpos]);
    src.push_str(") = ");
    src.push_str(&stmt[inpos+4..bracepos]);
    src.push_str(".into_iter().next() { }}");
    let src = core::new_source(src);

    if let Some((start, end)) = src.as_src().iter_stmts().next() {
        let blob = &src[start..end];
        debug!("get_type_of_for_expr: |{}| {} {} {} {}", blob, m.point, stmtstart, forpos, start);

        let pos = m.point - stmtstart - forpos - start;
        let scope = Scope{ filepath: m.filepath.clone(), point: m.point };

        ast::get_let_type(blob.to_owned(), pos, scope, session)
    } else {
        None
    }
}

pub fn get_struct_field_type(fieldname: &str, structmatch: &Match, session: &Session) -> Option<core::Ty> {
    assert!(structmatch.mtype == core::MatchType::Struct);

    let src = session.load_file(&structmatch.filepath);

    let opoint = scopes::find_stmt_start(src.as_src(), structmatch.point);
    let structsrc = scopes::end_of_next_scope(&src[opoint.unwrap()..]);

    let fields = ast::parse_struct_fields(structsrc.to_owned(), Scope::from_match(structmatch));
    for (field, _, ty) in fields.into_iter() {
        if fieldname == field {
            return ty;
        }
    }
    None
}

pub fn get_tuplestruct_field_type(fieldnum: usize, structmatch: &Match, session: &Session) -> Option<core::Ty> {
    let src = session.load_file(&structmatch.filepath);

    let structsrc = if let core::MatchType::EnumVariant = structmatch.mtype {
        // decorate the enum variant src to make it look like a tuple struct
        let to = (&src[structmatch.point..]).find('(')
            .map(|n| scopes::find_closing_paren(&src, structmatch.point + n+1))
            .unwrap();
        "struct ".to_owned() + &src[structmatch.point..(to+1)] + ";"
    } else {
        assert!(structmatch.mtype == core::MatchType::Struct);
        let opoint = scopes::find_stmt_start(src.as_src(), structmatch.point);
        (*get_first_stmt(src.as_src().from(opoint.unwrap()))).to_owned()
    };

    debug!("get_tuplestruct_field_type structsrc=|{}|", structsrc);

    let fields = ast::parse_struct_fields(structsrc, Scope::from_match(structmatch));

    for (i, (_, _, ty)) in fields.into_iter().enumerate() {
        if i == fieldnum {
            return ty;
        }
    }
    None
}

pub fn get_first_stmt(src: Src) -> Src {
    match src.iter_stmts().next() {
        Some((from, to)) => src.from_to(from, to),
        None => src
    }
}

pub fn get_type_of_match(m: Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    debug!("get_type_of match {:?} ", m);

    match m.mtype {
        core::MatchType::Let => get_type_of_let_expr(&m, msrc, session),
        core::MatchType::IfLet => get_type_of_let_block_expr(&m, msrc, session, "if let"),
        core::MatchType::WhileLet => get_type_of_let_block_expr(&m, msrc, session, "while let"),
        core::MatchType::For => get_type_of_for_expr(&m, msrc, session),
        core::MatchType::FnArg => get_type_of_fnarg(&m, msrc, session),
        core::MatchType::MatchArm => get_type_from_match_arm(&m, msrc, session),
        core::MatchType::Struct |
        core::MatchType::Enum |
        core::MatchType::Function |
        core::MatchType::Module => Some(core::Ty::Match(m)),
        _ => { debug!("!!! WARNING !!! Can't get type of {:?}", m.mtype); None }
    }
}

macro_rules! otry {
    ($e:expr) => (match $e { Some(e) => e, None => return None })
}

pub fn get_type_from_match_arm(m: &Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    // We construct a faux match stmt and then parse it. This is because the
    // match stmt may be incomplete (half written) in the real code

    // skip to end of match arm pattern so we can search backwards
    let arm = otry!((&msrc[m.point..]).find("=>")) + m.point;
    let scopestart = scopes::scope_start(msrc, arm);

    let stmtstart = otry!(scopes::find_stmt_start(msrc, scopestart-1));
    debug!("PHIL preblock is {} {}", stmtstart, scopestart);
    let preblock = &msrc[stmtstart..scopestart];
    let matchstart = otry!(preblock.rfind("match ")) + stmtstart;

    let lhs_start = scopes::get_start_of_pattern(&msrc, arm);
    let lhs = &msrc[lhs_start..arm];
    // construct faux match statement and recreate point
    let mut fauxmatchstmt = (&msrc[matchstart..scopestart]).to_owned();
    let faux_prefix_size = fauxmatchstmt.len();
    fauxmatchstmt = fauxmatchstmt + lhs + " => () };";
    let faux_point = faux_prefix_size + (m.point - lhs_start);

    debug!("fauxmatchstmt for parsing is pt:{} src:|{}|", faux_point, fauxmatchstmt);

    ast::get_match_arm_type(fauxmatchstmt, faux_point,
                            // scope is used to locate expression, so send
                            // it the start of the match expr
                            Scope {
                                filepath: m.filepath.clone(),
                                point: matchstart,
                            }, session)
}

pub fn get_function_declaration(fnmatch: &Match, session: &Session) -> String {
    let src = session.load_file(&fnmatch.filepath);
    let start = scopes::find_stmt_start(src.as_src(), fnmatch.point).unwrap();
    let end = (&src[start..]).find('{').unwrap();
    (&src[start..end+start]).to_owned()
}

pub fn get_return_type_of_function(fnmatch: &Match, session: &Session) -> Option<core::Ty> {
    let src = session.load_file(&fnmatch.filepath);
    let point = scopes::find_stmt_start(src.as_src(), fnmatch.point).unwrap();
    (&src[point..]).find("{").and_then(|n| {
        // wrap in "impl blah { }" so that methods get parsed correctly too
        let mut decl = String::new();
        decl.push_str("impl blah {");
        decl.push_str(&src[point..(point+n+1)]);
        decl.push_str("}}");
        debug!("get_return_type_of_function: passing in |{}|", decl);
        ast::parse_fn_output(decl, Scope::from_match(fnmatch))
    })
}
<commit_msg>[master] Early return on first generic close.<commit_after>// Type inference

use core::{Match, Src, Scope, Session};
use nameres::resolve_path_with_str;
use core::Namespace::TypeNamespace;
use core;
use ast;
use scopes;
use matchers;
use core::SearchType::ExactMatch;
use util::txt_matches;

fn find_start_of_function_body(src: &str) -> usize {
    // TODO: this should ignore anything inside parens so as to skip the arg list
    src.find('{').unwrap()
}

// Removes the body of the statement (anything in the braces {...}), leaving just
// the header
// TODO: this should skip parens (e.g. function arguments)
pub fn generate_skeleton_for_parsing(src: &str) -> String {
    let mut s = String::new();
    let n = src.find('{').unwrap();
    s.push_str(&src[..n+1]);
    s.push_str("};");
    s
}

pub fn first_param_is_self(blob: &str) -> bool {
    // skip generic arg
    // consider 'pub fn map<U, F: FnOnce(T) -> U>(self, f: F)'
    // we have to match the '>'
    match blob.find('(') {
        None => false,
        Some(probable_param_start) => {
            let skip_generic = match blob.find('<') {
                None => 0,
                Some(generic_start) if generic_start < probable_param_start => {
                    let mut level = 0;
                    let mut prev = ' ';
                    let mut skip_generic = 0;
                    for (i, c) in blob[generic_start..].char_indices() {
                        match c {
                            '<' => level += 1,
                            '>' if prev == '-' => (),
                            '>' => level -= 1,
                            _ => (),
                        }
                        prev = c;
                        if level == 0 {
                            skip_generic = i;
                            break;
                        }
                    }
                    skip_generic
                },
                Some(..) => 0,
            };
            while let Some(start) = blob[skip_generic..].find('(') {
                let end = scopes::find_closing_paren(blob, start + 1);
                let is_self = txt_matches(ExactMatch, "self", &blob[(start + 1)..end]);
                debug!("searching fn args: |{}| {}",
                       &blob[(start + 1)..end],
                       is_self);
                return is_self;
            }
            false
        }
    }
}

#[test]
fn generates_skeleton_for_mod() {
    let src = "mod foo { blah };";
    let out = generate_skeleton_for_parsing(src);
    assert_eq!("mod foo {};", out);
}

fn get_type_of_self_arg(m: &Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    debug!("get_type_of_self_arg {:?}", m);
    scopes::find_impl_start(msrc, m.point, 0).and_then(|start| {
        let decl = generate_skeleton_for_parsing(&msrc.from(start));
        debug!("get_type_of_self_arg impl skeleton |{}|", decl);

        if decl.starts_with("impl") {
            let implres = ast::parse_impl(decl);
            debug!("get_type_of_self_arg implres |{:?}|", implres);
            resolve_path_with_str(&implres.name_path.expect("failed parsing impl name"),
                                  &m.filepath, start,
                                  ExactMatch, TypeNamespace,
                                  session).nth(0).map(core::Ty::Match)
        } else {
            // // must be a trait
            ast::parse_trait(decl).name.and_then(|name| {
                Some(core::Ty::Match(Match {
                           matchstr: name,
                           filepath: m.filepath.clone(),
                           point: start,
                           local: m.local,
                           mtype: core::MatchType::Trait,
                           contextstr: matchers::first_line(&msrc[start..]),
                           generic_args: Vec::new(),
                           generic_types: Vec::new(),
                           docs: String::new(),
                }))
            })
        }
    })
}

fn get_type_of_fnarg(m: &Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    if m.matchstr == "self" {
        return get_type_of_self_arg(m, msrc, session);
    }

    let stmtstart = scopes::find_stmt_start(msrc, m.point).unwrap();
    let block = msrc.from(stmtstart);
    if let Some((start, end)) = block.iter_stmts().next() {
        let blob = &msrc[(stmtstart+start)..(stmtstart+end)];
        // wrap in "impl blah { }" so that methods get parsed correctly too
        let mut s = String::new();
        s.push_str("impl blah {");
        let impl_header_len = s.len();
        s.push_str(&blob[..(find_start_of_function_body(blob)+1)]);
        s.push_str("}}");
        let argpos = m.point - (stmtstart+start) + impl_header_len;
        return ast::parse_fn_arg_type(s, argpos, Scope::from_match(m), session);
    }
    None
}

fn get_type_of_let_expr(m: &Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    // ASSUMPTION: this is being called on a let decl
    let point = scopes::find_stmt_start(msrc, m.point).unwrap();
    let src = msrc.from(point);

    if let Some((start, end)) = src.iter_stmts().next() {
        let blob = &src[start..end];
        debug!("get_type_of_let_expr calling parse_let |{}|", blob);

        let pos = m.point - point - start;
        let scope = Scope{ filepath: m.filepath.clone(), point: m.point };
        ast::get_let_type(blob.to_owned(), pos, scope, session)
    } else {
        None
    }
}

fn get_type_of_let_block_expr(m: &Match, msrc: Src, session: &Session, prefix: &str) -> Option<core::Ty> {
    // ASSUMPTION: this is being called on an if let or while let decl
    let stmtstart = scopes::find_stmt_start(msrc, m.point).unwrap();
    let stmt = msrc.from(stmtstart);
    let point = stmt.find(prefix).unwrap();
    let src = core::new_source(generate_skeleton_for_parsing(&stmt[point..]));

    if let Some((start, end)) = src.as_src().iter_stmts().next() {
        let blob = &src[start..end];
        debug!("get_type_of_let_block_expr calling get_let_type |{}|", blob);

        let pos = m.point - stmtstart - point - start;
        let scope = Scope{ filepath: m.filepath.clone(), point: m.point };
        ast::get_let_type(blob.to_owned(), pos, scope, session)
    } else {
        None
    }
}

fn get_type_of_for_expr(m: &Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    let stmtstart = scopes::find_stmt_start(msrc, m.point).unwrap();
    let stmt = msrc.from(stmtstart);
    let forpos = stmt.find("for ").unwrap();
    let inpos = stmt.find(" in ").unwrap();
    // XXX: this need not be the correct brace, see generate_skeleton_for_parsing
    let bracepos = stmt.find('{').unwrap();
    let mut src = stmt[..forpos].to_owned();
    src.push_str("if let Some(");
    src.push_str(&stmt[forpos+4..inpos]);
    src.push_str(") = ");
    src.push_str(&stmt[inpos+4..bracepos]);
    src.push_str(".into_iter().next() { }}");
    let src = core::new_source(src);

    if let Some((start, end)) = src.as_src().iter_stmts().next() {
        let blob = &src[start..end];
        debug!("get_type_of_for_expr: |{}| {} {} {} {}", blob, m.point, stmtstart, forpos, start);

        let pos = m.point - stmtstart - forpos - start;
        let scope = Scope{ filepath: m.filepath.clone(), point: m.point };

        ast::get_let_type(blob.to_owned(), pos, scope, session)
    } else {
        None
    }
}

pub fn get_struct_field_type(fieldname: &str, structmatch: &Match, session: &Session) -> Option<core::Ty> {
    assert!(structmatch.mtype == core::MatchType::Struct);

    let src = session.load_file(&structmatch.filepath);

    let opoint = scopes::find_stmt_start(src.as_src(), structmatch.point);
    let structsrc = scopes::end_of_next_scope(&src[opoint.unwrap()..]);

    let fields = ast::parse_struct_fields(structsrc.to_owned(), Scope::from_match(structmatch));
    for (field, _, ty) in fields.into_iter() {
        if fieldname == field {
            return ty;
        }
    }
    None
}

pub fn get_tuplestruct_field_type(fieldnum: usize, structmatch: &Match, session: &Session) -> Option<core::Ty> {
    let src = session.load_file(&structmatch.filepath);

    let structsrc = if let core::MatchType::EnumVariant = structmatch.mtype {
        // decorate the enum variant src to make it look like a tuple struct
        let to = (&src[structmatch.point..]).find('(')
            .map(|n| scopes::find_closing_paren(&src, structmatch.point + n+1))
            .unwrap();
        "struct ".to_owned() + &src[structmatch.point..(to+1)] + ";"
    } else {
        assert!(structmatch.mtype == core::MatchType::Struct);
        let opoint = scopes::find_stmt_start(src.as_src(), structmatch.point);
        (*get_first_stmt(src.as_src().from(opoint.unwrap()))).to_owned()
    };

    debug!("get_tuplestruct_field_type structsrc=|{}|", structsrc);

    let fields = ast::parse_struct_fields(structsrc, Scope::from_match(structmatch));

    for (i, (_, _, ty)) in fields.into_iter().enumerate() {
        if i == fieldnum {
            return ty;
        }
    }
    None
}

pub fn get_first_stmt(src: Src) -> Src {
    match src.iter_stmts().next() {
        Some((from, to)) => src.from_to(from, to),
        None => src
    }
}

pub fn get_type_of_match(m: Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    debug!("get_type_of match {:?} ", m);

    match m.mtype {
        core::MatchType::Let => get_type_of_let_expr(&m, msrc, session),
        core::MatchType::IfLet => get_type_of_let_block_expr(&m, msrc, session, "if let"),
        core::MatchType::WhileLet => get_type_of_let_block_expr(&m, msrc, session, "while let"),
        core::MatchType::For => get_type_of_for_expr(&m, msrc, session),
        core::MatchType::FnArg => get_type_of_fnarg(&m, msrc, session),
        core::MatchType::MatchArm => get_type_from_match_arm(&m, msrc, session),
        core::MatchType::Struct |
        core::MatchType::Enum |
        core::MatchType::Function |
        core::MatchType::Module => Some(core::Ty::Match(m)),
        _ => { debug!("!!! WARNING !!! Can't get type of {:?}", m.mtype); None }
    }
}

macro_rules! otry {
    ($e:expr) => (match $e { Some(e) => e, None => return None })
}

pub fn get_type_from_match_arm(m: &Match, msrc: Src, session: &Session) -> Option<core::Ty> {
    // We construct a faux match stmt and then parse it. This is because the
    // match stmt may be incomplete (half written) in the real code

    // skip to end of match arm pattern so we can search backwards
    let arm = otry!((&msrc[m.point..]).find("=>")) + m.point;
    let scopestart = scopes::scope_start(msrc, arm);

    let stmtstart = otry!(scopes::find_stmt_start(msrc, scopestart-1));
    debug!("PHIL preblock is {} {}", stmtstart, scopestart);
    let preblock = &msrc[stmtstart..scopestart];
    let matchstart = otry!(preblock.rfind("match ")) + stmtstart;

    let lhs_start = scopes::get_start_of_pattern(&msrc, arm);
    let lhs = &msrc[lhs_start..arm];
    // construct faux match statement and recreate point
    let mut fauxmatchstmt = (&msrc[matchstart..scopestart]).to_owned();
    let faux_prefix_size = fauxmatchstmt.len();
    fauxmatchstmt = fauxmatchstmt + lhs + " => () };";
    let faux_point = faux_prefix_size + (m.point - lhs_start);

    debug!("fauxmatchstmt for parsing is pt:{} src:|{}|", faux_point, fauxmatchstmt);

    ast::get_match_arm_type(fauxmatchstmt, faux_point,
                            // scope is used to locate expression, so send
                            // it the start of the match expr
                            Scope {
                                filepath: m.filepath.clone(),
                                point: matchstart,
                            }, session)
}

pub fn get_function_declaration(fnmatch: &Match, session: &Session) -> String {
    let src = session.load_file(&fnmatch.filepath);
    let start = scopes::find_stmt_start(src.as_src(), fnmatch.point).unwrap();
    let end = (&src[start..]).find('{').unwrap();
    (&src[start..end+start]).to_owned()
}

pub fn get_return_type_of_function(fnmatch: &Match, session: &Session) -> Option<core::Ty> {
    let src = session.load_file(&fnmatch.filepath);
    let point = scopes::find_stmt_start(src.as_src(), fnmatch.point).unwrap();
    (&src[point..]).find("{").and_then(|n| {
        // wrap in "impl blah { }" so that methods get parsed correctly too
        let mut decl = String::new();
        decl.push_str("impl blah {");
        decl.push_str(&src[point..(point+n+1)]);
        decl.push_str("}}");
        debug!("get_return_type_of_function: passing in |{}|", decl);
        ast::parse_fn_output(decl, Scope::from_match(fnmatch))
    })
}
<|endoftext|>


<commit_before><commit_msg>Add decode tests for coprocessor transfer operations<commit_after><|endoftext|>


<commit_before><commit_msg>Fix AST module<commit_after><|endoftext|>


<commit_before><commit_msg>json related changes<commit_after><|endoftext|>


<commit_before><commit_msg>`IXAudio2SubmixVoice`, `IXAudio2MasteringVoice`, `IXAudio2EngineCallback`, `IXAudio2VoiceCallback`<commit_after><|endoftext|>


<commit_before><commit_msg>Fix warnings<commit_after><|endoftext|>


<commit_before>use js;
use js::rust::Compartment;
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL,
            JS_THIS_OBJECT, JS_SET_RVAL};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSNative,
                JSFunctionSpec, JSPropertySpec, JSVal};
use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError,
                            JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN,
                            JS_DefineFunctions, JS_DefineProperty, JS_GetContextPrivate,
                            JS_GetClass, JS_GetPrototype};
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB,
                  RESOLVE_STUB};
use js::glue::bindgen::*;
use core::ptr::null;
use core::cast;
use content::content_task::{Content, task_from_context};

pub enum DOMString {
    str(~str),
    null_string
}

pub struct rust_box<T> {
    rc: uint,
    td: *sys::TypeDesc,
    next: *(),
    prev: *(),
    payload: T
}

pub unsafe fn unwrap<T>(obj: *JSObject) -> T {
    let val = JS_GetReservedSlot(obj, 0);
    cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val))
}

pub unsafe fn squirrel_away<T>(x: @T) -> *rust_box<T> {
    let y: *rust_box<T> = cast::reinterpret_cast(&x);
    cast::forget(x);
    y
}

pub unsafe fn squirrel_away_unique<T>(x: ~T) -> *rust_box<T> {
    let y: *rust_box<T> = cast::reinterpret_cast(&x);
    cast::forget(x);
    y
}

//XXX very incomplete
pub fn jsval_to_str(cx: *JSContext, v: JSVal) -> Result<~str, ()> {
    let jsstr;
    if RUST_JSVAL_IS_STRING(v) == 1 {
        jsstr = RUST_JSVAL_TO_STRING(v)
    } else {
        jsstr = JS_ValueToString(cx, v);
        if jsstr.is_null() {
            return Err(());
        }
    }

    let len = 0;
    let chars = JS_GetStringCharsZAndLength(cx, jsstr, ptr::to_unsafe_ptr(&len));
    return if chars.is_null() {
        Err(())
    } else {
        unsafe {
            let buf = vec::raw::from_buf_raw(chars as *u8, len as uint);
            Ok(str::from_bytes(buf))
        }
    }
}

pub unsafe fn domstring_to_jsval(cx: *JSContext, string: &DOMString) -> JSVal {
    match string {
      &null_string => {
        JSVAL_NULL
      }
      &str(ref s) => {
        str::as_buf(*s, |buf, len| {
            let cbuf = cast::reinterpret_cast(&buf);
            RUST_STRING_TO_JSVAL(JS_NewStringCopyN(cx, cbuf, len as libc::size_t))
        })
      }
    }
}

pub fn get_compartment(cx: *JSContext) -> @mut Compartment {
    unsafe {
        let content = task_from_context(cx);
        let compartment = option::expect((*content).compartment,
                                         ~"Should always have compartment when \
                                           executing JS code");
        fail_unless!(cx == compartment.cx.ptr);
        compartment
    }
}

extern fn has_instance(_cx: *JSContext, obj: **JSObject, v: *JSVal, bp: *mut JSBool) -> JSBool {
    //XXXjdm this is totally broken for non-object values
    let mut o = RUST_JSVAL_TO_OBJECT(unsafe {*v});
    let obj = unsafe {*obj};
    unsafe { *bp = 0; }
    while o.is_not_null() {
        if o == obj {
            unsafe { *bp = 1; }
            break;
        }
        o = JS_GetPrototype(o);
    }
    return 1;
}

pub fn prototype_jsclass(name: ~str) -> @fn(compartment: @mut Compartment) -> JSClass {
    let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment| {
        JSClass {
            name: compartment.add_name(copy name),
            flags: 0,
            addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            getProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            setProperty: GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
            enumerate: GetJSClassHookStubPointer(ENUMERATE_STUB) as *u8,
            resolve: GetJSClassHookStubPointer(RESOLVE_STUB) as *u8,
            convert: GetJSClassHookStubPointer(CONVERT_STUB) as *u8,
            finalize: null(),
            checkAccess: null(),
            call: null(),
            hasInstance: has_instance,
            construct: null(),
            trace: null(),
            reserved: (null(), null(), null(), null(), null(),  // 05
                       null(), null(), null(), null(), null(),  // 10
                       null(), null(), null(), null(), null(),  // 15
                       null(), null(), null(), null(), null(),  // 20
                       null(), null(), null(), null(), null(),  // 25
                       null(), null(), null(), null(), null(),  // 30
                       null(), null(), null(), null(), null(),  // 35
                       null(), null(), null(), null(), null())  // 40
        }
    };
    return f;
}

pub fn instance_jsclass(name: ~str, finalize: *u8)
                     -> @fn(compartment: @mut Compartment) -> JSClass {
    let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment| {
        JSClass {
            name: compartment.add_name(copy name),
            flags: JSCLASS_HAS_RESERVED_SLOTS(1),
            addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            getProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            setProperty: GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
            enumerate: GetJSClassHookStubPointer(ENUMERATE_STUB) as *u8,
            resolve: GetJSClassHookStubPointer(RESOLVE_STUB) as *u8,
            convert: GetJSClassHookStubPointer(CONVERT_STUB) as *u8,
            finalize: finalize,
            checkAccess: null(),
            call: null(),
            hasInstance: has_instance,
            construct: null(),
            trace: null(),
            reserved: (null(), null(), null(), null(), null(),  // 05
                       null(), null(), null(), null(), null(),  // 10
                       null(), null(), null(), null(), null(),  // 15
                       null(), null(), null(), null(), null(),  // 20
                       null(), null(), null(), null(), null(),  // 25
                       null(), null(), null(), null(), null(),  // 30
                       null(), null(), null(), null(), null(),  // 35
                       null(), null(), null(), null(), null())  // 40
        }
    };
    return f;
}

// FIXME: A lot of string copies here
pub fn define_empty_prototype(name: ~str, proto: Option<~str>, compartment: @mut Compartment)
    -> js::rust::jsobj {
    compartment.register_class(prototype_jsclass(copy name));

    //TODO error checking
    let obj = result::unwrap(
        match proto {
            Some(s) => compartment.new_object_with_proto(copy name,
                                                         s,
                                                         compartment.global_obj.ptr),
            None => compartment.new_object(copy name, null(), compartment.global_obj.ptr)
        });

    compartment.define_property(copy name, RUST_OBJECT_TO_JSVAL(obj.ptr),
                                GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
                                GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
                                JSPROP_ENUMERATE);
    compartment.stash_global_proto(name, obj);
    return obj;
}

// We use slot 0 for holding the raw object.  This is safe for both
// globals and non-globals.
const DOM_OBJECT_SLOT: uint = 0;

// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
// LSetDOMProperty. Those constants need to be changed accordingly if this value
// changes.
const DOM_PROTO_INSTANCE_CLASS_SLOT: u32 = 0;

// All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. We have to
// start at 1 past JSCLASS_GLOBAL_SLOT_COUNT because XPConnect uses
// that one.
const DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT + 1;

// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
// LSetDOMProperty. Those constants need to be changed accordingly if this value
// changes.
const JSCLASS_DOM_GLOBAL: u32 = js::JSCLASS_USERBIT1;

pub struct NativeProperties {
    staticMethods: *JSFunctionSpec,
    staticMethodIds: *jsid,
    staticMethodsSpecs: *JSFunctionSpec,
    staticAttributes: *JSPropertySpec,
    staticAttributeIds: *jsid,
    staticAttributeSpecs: *JSPropertySpec,
    methods: *JSFunctionSpec,
    methodIds: *jsid,
    methodsSpecs: *JSFunctionSpec,
    attributes: *JSPropertySpec,
    attributeIds: *jsid,
    attributeSpecs: *JSPropertySpec,
    unforgeableAttributes: *JSPropertySpec,
    unforgeableAttributeIds: *jsid,
    unforgeableAttributeSpecs: *JSPropertySpec,
    constants: *ConstantSpec,
    constantIds: *jsid,
    constantSpecs: *ConstantSpec
}

pub struct NativePropertyHooks {
    resolve_own_property: *u8,
    resolve_property: *u8,
    enumerate_own_properties: *u8,
    enumerate_properties: *u8,
    proto_hooks: *NativePropertyHooks
}

pub struct JSNativeHolder {
    native: js::jsapi::JSNative,
    propertyHooks: *NativePropertyHooks
}

pub struct ConstantSpec {
    name: &str,
    value: JSVal
}

pub struct DOMClass {
    // A list of interfaces that this object implements, in order of decreasing
    // derivedness.
    interface_chain: [prototypes::id::Prototype * 1 /*prototypes::id::_ID_Count*/],

    unused: bool, // DOMObjectIsISupports (always false)
    native_hooks: *NativePropertyHooks
}

pub struct DOMJSClass {
    base: JSClass,
    dom_class: DOMClass
}

fn GetProtoOrIfaceArray(global: *JSObject) -> **JSObject {
    unsafe {
        assert ((*JS_GetClass(global)).flags & JSCLASS_DOM_GLOBAL) != 0;
        cast::reinterpret_cast(&JS_GetReservedSlot(global, DOM_PROTOTYPE_SLOT))
    }
}

mod prototypes {
    mod id {
        pub enum Prototype {
            ClientRect,
            _ID_Count
        }
    }
}

pub fn CreateInterfaceObjects2(cx: *JSContext, global: *JSObject, receiver: *JSObject,
                               protoProto: *JSObject, protoClass: *JSClass,
                               constructorClass: *JSClass, constructor: JSNative,
                               ctorNargs: uint,
                               domClass: *DOMClass,
                               methods: *JSFunctionSpec,
                               properties: *JSPropertySpec,
                               constants: *ConstantSpec,
                               staticMethods: *JSFunctionSpec,
                               name: &str) -> *JSObject {
    unsafe {
        let mut proto = ptr::null();
        if protoClass.is_not_null() {
            proto = /*CreateInterfacePrototypeObject(cx, global, protoProto,
                                                   protoClass,
                                                   regularProperties,
                                                   chromeOnlyProperties);*/ptr::null();
            if proto.is_null() {
                return ptr::null();
            }

            JS_SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
                               RUST_PRIVATE_TO_JSVAL(domClass as *libc::c_void));
        }

        let mut interface = ptr::null();
        if constructorClass.is_not_null() || constructor.is_not_null() {
            interface = do str::as_c_str(name) |s| {
                /*CreateInterfaceObject(cx, global, constructorClass, constructor,
                                              ctorNargs, proto, properties,
                                              chromeOnlyProperties, s)*/ptr::null()
            };
            if interface.is_null() {
                return ptr::null();
            }
        }

        if protoClass.is_not_null() {
            proto
        } else {
            interface
        }
    }
}

pub extern fn ThrowingConstructor(cx: *JSContext, argc: uint, vp: *JSVal) -> JSBool {
    //XXX should trigger exception here
    return 0;
}<commit_msg>Hook up interface and prototype object creation.<commit_after>use js;
use js::rust::Compartment;
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL,
         JS_THIS_OBJECT, JS_SET_RVAL, JSFUN_CONSTRUCTOR, JS_CALLEE};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSNative,
                JSFunctionSpec, JSPropertySpec, JSVal, JSString};
use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError,
                         JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN,
                         JS_DefineFunctions, JS_DefineProperty, JS_GetContextPrivate,
                         JS_GetClass, JS_GetPrototype, JS_LinkConstructorAndPrototype,
                         JS_AlreadyHasOwnProperty, JS_NewObject, JS_NewFunction,
                         JS_GetFunctionPrototype, JS_InternString, JS_GetFunctionObject,
                         JS_GetInternedStringCharsAndLength};
use js::jsfriendapi::bindgen::{DefineFunctionWithReserved, GetObjectJSClass,
                               JS_NewObjectWithUniqueType};
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB,
                  RESOLVE_STUB};
use js::glue::bindgen::*;
use core::ptr::null;
use core::cast;
use content::content_task::{Content, task_from_context};

const TOSTRING_CLASS_RESERVED_SLOT: u64 = 0;
const TOSTRING_NAME_RESERVED_SLOT: u64 = 1;

extern fn InterfaceObjectToString(cx: *JSContext, argc: uint, vp: *mut JSVal) -> JSBool {
  unsafe {
    let callee = RUST_JSVAL_TO_OBJECT(*JS_CALLEE(cx, cast::transmute(&vp)));
    let obj = JS_THIS_OBJECT(cx, cast::transmute(&vp));
    if obj.is_null() {
        //XXXjdm figure out JSMSG madness
        /*JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO,
                             "null", "object");*/
        return 0;
    }

    let v = GetFunctionNativeReserved(callee, TOSTRING_CLASS_RESERVED_SLOT);
    let clasp: *JSClass = cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(*v));

    let v = GetFunctionNativeReserved(callee, TOSTRING_NAME_RESERVED_SLOT);
    let jsname: *JSString = RUST_JSVAL_TO_STRING(*v);
    let length = 0;
    let name = JS_GetInternedStringCharsAndLength(jsname, &length);

    if GetObjectJSClass(obj) != clasp {
        //XXXjdm figure out JSMSG madness
        /*JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
                             NS_ConvertUTF16toUTF8(name).get(), "toString",
                             "object");*/
        return 0;
    }

    let name = jsval_to_str(cx, *v).get();
    let retval = str(~"function " + name + ~"() {\n    [native code]\n}");
    *vp = domstring_to_jsval(cx, &retval);
    return 1;
  }
}

pub enum DOMString {
    str(~str),
    null_string
}

pub struct rust_box<T> {
    rc: uint,
    td: *sys::TypeDesc,
    next: *(),
    prev: *(),
    payload: T
}

pub unsafe fn unwrap<T>(obj: *JSObject) -> T {
    let val = JS_GetReservedSlot(obj, 0);
    cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val))
}

pub unsafe fn squirrel_away<T>(x: @T) -> *rust_box<T> {
    let y: *rust_box<T> = cast::reinterpret_cast(&x);
    cast::forget(x);
    y
}

pub unsafe fn squirrel_away_unique<T>(x: ~T) -> *rust_box<T> {
    let y: *rust_box<T> = cast::reinterpret_cast(&x);
    cast::forget(x);
    y
}

//XXX very incomplete
pub fn jsval_to_str(cx: *JSContext, v: JSVal) -> Result<~str, ()> {
    let jsstr;
    if RUST_JSVAL_IS_STRING(v) == 1 {
        jsstr = RUST_JSVAL_TO_STRING(v)
    } else {
        jsstr = JS_ValueToString(cx, v);
        if jsstr.is_null() {
            return Err(());
        }
    }

    let len = 0;
    let chars = JS_GetStringCharsZAndLength(cx, jsstr, ptr::to_unsafe_ptr(&len));
    return if chars.is_null() {
        Err(())
    } else {
        unsafe {
            let buf = vec::raw::from_buf_raw(chars as *u8, len as uint);
            Ok(str::from_bytes(buf))
        }
    }
}

pub unsafe fn domstring_to_jsval(cx: *JSContext, string: &DOMString) -> JSVal {
    match string {
      &null_string => {
        JSVAL_NULL
      }
      &str(ref s) => {
        str::as_buf(*s, |buf, len| {
            let cbuf = cast::reinterpret_cast(&buf);
            RUST_STRING_TO_JSVAL(JS_NewStringCopyN(cx, cbuf, len as libc::size_t))
        })
      }
    }
}

pub fn get_compartment(cx: *JSContext) -> @mut Compartment {
    unsafe {
        let content = task_from_context(cx);
        let compartment = option::expect((*content).compartment,
                                         ~"Should always have compartment when \
                                           executing JS code");
        fail_unless!(cx == compartment.cx.ptr);
        compartment
    }
}

extern fn has_instance(_cx: *JSContext, obj: **JSObject, v: *JSVal, bp: *mut JSBool) -> JSBool {
    //XXXjdm this is totally broken for non-object values
    let mut o = RUST_JSVAL_TO_OBJECT(unsafe {*v});
    let obj = unsafe {*obj};
    unsafe { *bp = 0; }
    while o.is_not_null() {
        if o == obj {
            unsafe { *bp = 1; }
            break;
        }
        o = JS_GetPrototype(o);
    }
    return 1;
}

pub fn prototype_jsclass(name: ~str) -> @fn(compartment: @mut Compartment) -> JSClass {
    let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment| {
        JSClass {
            name: compartment.add_name(copy name),
            flags: 0,
            addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            getProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            setProperty: GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
            enumerate: GetJSClassHookStubPointer(ENUMERATE_STUB) as *u8,
            resolve: GetJSClassHookStubPointer(RESOLVE_STUB) as *u8,
            convert: GetJSClassHookStubPointer(CONVERT_STUB) as *u8,
            finalize: null(),
            checkAccess: null(),
            call: null(),
            hasInstance: has_instance,
            construct: null(),
            trace: null(),
            reserved: (null(), null(), null(), null(), null(),  // 05
                       null(), null(), null(), null(), null(),  // 10
                       null(), null(), null(), null(), null(),  // 15
                       null(), null(), null(), null(), null(),  // 20
                       null(), null(), null(), null(), null(),  // 25
                       null(), null(), null(), null(), null(),  // 30
                       null(), null(), null(), null(), null(),  // 35
                       null(), null(), null(), null(), null())  // 40
        }
    };
    return f;
}

pub fn instance_jsclass(name: ~str, finalize: *u8)
                     -> @fn(compartment: @mut Compartment) -> JSClass {
    let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment| {
        JSClass {
            name: compartment.add_name(copy name),
            flags: JSCLASS_HAS_RESERVED_SLOTS(1),
            addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            getProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
            setProperty: GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
            enumerate: GetJSClassHookStubPointer(ENUMERATE_STUB) as *u8,
            resolve: GetJSClassHookStubPointer(RESOLVE_STUB) as *u8,
            convert: GetJSClassHookStubPointer(CONVERT_STUB) as *u8,
            finalize: finalize,
            checkAccess: null(),
            call: null(),
            hasInstance: has_instance,
            construct: null(),
            trace: null(),
            reserved: (null(), null(), null(), null(), null(),  // 05
                       null(), null(), null(), null(), null(),  // 10
                       null(), null(), null(), null(), null(),  // 15
                       null(), null(), null(), null(), null(),  // 20
                       null(), null(), null(), null(), null(),  // 25
                       null(), null(), null(), null(), null(),  // 30
                       null(), null(), null(), null(), null(),  // 35
                       null(), null(), null(), null(), null())  // 40
        }
    };
    return f;
}

// FIXME: A lot of string copies here
pub fn define_empty_prototype(name: ~str, proto: Option<~str>, compartment: @mut Compartment)
    -> js::rust::jsobj {
    compartment.register_class(prototype_jsclass(copy name));

    //TODO error checking
    let obj = result::unwrap(
        match proto {
            Some(s) => compartment.new_object_with_proto(copy name,
                                                         s,
                                                         compartment.global_obj.ptr),
            None => compartment.new_object(copy name, null(), compartment.global_obj.ptr)
        });

    compartment.define_property(copy name, RUST_OBJECT_TO_JSVAL(obj.ptr),
                                GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
                                GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
                                JSPROP_ENUMERATE);
    compartment.stash_global_proto(name, obj);
    return obj;
}

// We use slot 0 for holding the raw object.  This is safe for both
// globals and non-globals.
const DOM_OBJECT_SLOT: uint = 0;

// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
// LSetDOMProperty. Those constants need to be changed accordingly if this value
// changes.
const DOM_PROTO_INSTANCE_CLASS_SLOT: u32 = 0;

// All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. We have to
// start at 1 past JSCLASS_GLOBAL_SLOT_COUNT because XPConnect uses
// that one.
const DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT + 1;

// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
// LSetDOMProperty. Those constants need to be changed accordingly if this value
// changes.
const JSCLASS_DOM_GLOBAL: u32 = js::JSCLASS_USERBIT1;

pub struct NativeProperties {
    staticMethods: *JSFunctionSpec,
    staticMethodIds: *jsid,
    staticMethodsSpecs: *JSFunctionSpec,
    staticAttributes: *JSPropertySpec,
    staticAttributeIds: *jsid,
    staticAttributeSpecs: *JSPropertySpec,
    methods: *JSFunctionSpec,
    methodIds: *jsid,
    methodsSpecs: *JSFunctionSpec,
    attributes: *JSPropertySpec,
    attributeIds: *jsid,
    attributeSpecs: *JSPropertySpec,
    unforgeableAttributes: *JSPropertySpec,
    unforgeableAttributeIds: *jsid,
    unforgeableAttributeSpecs: *JSPropertySpec,
    constants: *ConstantSpec,
    constantIds: *jsid,
    constantSpecs: *ConstantSpec
}

pub struct NativePropertyHooks {
    resolve_own_property: *u8,
    resolve_property: *u8,
    enumerate_own_properties: *u8,
    enumerate_properties: *u8,
    proto_hooks: *NativePropertyHooks
}

pub struct JSNativeHolder {
    native: js::jsapi::JSNative,
    propertyHooks: *NativePropertyHooks
}

pub struct ConstantSpec {
    name: &str,
    value: JSVal
}

pub struct DOMClass {
    // A list of interfaces that this object implements, in order of decreasing
    // derivedness.
    interface_chain: [prototypes::id::Prototype * 1 /*prototypes::id::_ID_Count*/],

    unused: bool, // DOMObjectIsISupports (always false)
    native_hooks: *NativePropertyHooks
}

pub struct DOMJSClass {
    base: JSClass,
    dom_class: DOMClass
}

fn GetProtoOrIfaceArray(global: *JSObject) -> **JSObject {
    unsafe {
        assert ((*JS_GetClass(global)).flags & JSCLASS_DOM_GLOBAL) != 0;
        cast::reinterpret_cast(&JS_GetReservedSlot(global, DOM_PROTOTYPE_SLOT))
    }
}

mod prototypes {
    mod id {
        pub enum Prototype {
            ClientRect,
            _ID_Count
        }
    }
}

pub fn CreateInterfaceObjects2(cx: *JSContext, global: *JSObject, receiver: *JSObject,
                               protoProto: *JSObject, protoClass: *JSClass,
                               constructorClass: *JSClass, constructor: JSNative,
                               ctorNargs: u32,
                               domClass: *DOMClass,
                               methods: *JSFunctionSpec,
                               properties: *JSPropertySpec,
                               constants: *ConstantSpec,
                               staticMethods: *JSFunctionSpec,
                               name: &str) -> *JSObject {
    unsafe {
        let mut proto = ptr::null();
        if protoClass.is_not_null() {
            proto = CreateInterfacePrototypeObject(cx, global, protoProto,
                                                   protoClass, methods,
                                                   properties, constants);
            if proto.is_null() {
                return ptr::null();
            }

            JS_SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
                               RUST_PRIVATE_TO_JSVAL(domClass as *libc::c_void));
        }

        let mut interface = ptr::null();
        if constructorClass.is_not_null() || constructor.is_not_null() {
            interface = do str::as_c_str(name) |s| {
                CreateInterfaceObject(cx, global, receiver, constructorClass,
                                      constructor, ctorNargs, proto,
                                      staticMethods, constants, s)
            };
            if interface.is_null() {
                return ptr::null();
            }
        }

        if protoClass.is_not_null() {
            proto
        } else {
            interface
        }
    }
}

fn CreateInterfaceObject(cx: *JSContext, global: *JSObject, receiver: *JSObject,
                         constructorClass: *JSClass, constructorNative: JSNative,
                         ctorNargs: u32, proto: *JSObject,
                         staticMethods: *JSFunctionSpec,
                         constants: *ConstantSpec,
                         name: *libc::c_char) -> *JSObject {
  unsafe {
    let constructor = if constructorClass.is_not_null() {
        let functionProto = JS_GetFunctionPrototype(cx, global);
        if functionProto.is_null() {
            ptr::null()
        } else {
            JS_NewObject(cx, constructorClass, functionProto, global)
        }
    } else {
        assert constructorNative.is_not_null();
        let fun = JS_NewFunction(cx, constructorNative, ctorNargs,
                                 JSFUN_CONSTRUCTOR, global, name);
        if fun.is_null() {
            ptr::null()
        } else {
            JS_GetFunctionObject(fun)
        }
    };

    if constructor.is_null() {
        return ptr::null();
    }

    if staticMethods.is_not_null() /*&&
       !DefinePrefable(cx, constructor, staticMethods)*/ {
        return ptr::null();
    }

    if constructorClass.is_not_null() {
        let toString = do str::as_c_str("toString") |s| {
            DefineFunctionWithReserved(cx, constructor, s,
                                       InterfaceObjectToString,
                                       0, 0)
        };
        if toString.is_null() {
            return ptr::null();
        }

        let toStringObj = JS_GetFunctionObject(toString);
        SetFunctionNativeReserved(toStringObj, TOSTRING_CLASS_RESERVED_SLOT,
                                  &RUST_PRIVATE_TO_JSVAL(constructorClass as *libc::c_void));
        let s = JS_InternString(cx, name);
        if s.is_null() {
            return ptr::null();
        }
        SetFunctionNativeReserved(toStringObj, TOSTRING_NAME_RESERVED_SLOT,
                                  &RUST_STRING_TO_JSVAL(s));
    }

    if constants.is_not_null() /*&&
       !DefinePrefable(cx, constructor, constants)*/ {
        return ptr::null();
    }

    if proto.is_not_null() && JS_LinkConstructorAndPrototype(cx, constructor, proto) == 0 {
        return ptr::null();
    }

    let alreadyDefined = 0;
    if JS_AlreadyHasOwnProperty(cx, receiver, name, &alreadyDefined) == 0 {
        return ptr::null();
    }

    if alreadyDefined == 0 &&
       JS_DefineProperty(cx, receiver, name, RUST_OBJECT_TO_JSVAL(constructor),
                         ptr::null(), ptr::null(), 0) == 0 {
        return ptr::null();
    }

    return constructor;
  }
}

fn CreateInterfacePrototypeObject(cx: *JSContext, global: *JSObject,
                                  parentProto: *JSObject, protoClass: *JSClass,
                                  methods: *JSFunctionSpec,
                                  properties: *JSPropertySpec,
                                  constants: *ConstantSpec) -> *JSObject {
    let ourProto = JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global);
    if ourProto.is_null() {
        return ptr::null();
    }

    if methods.is_not_null() /*&& !DefinePrefable(cx, ourProto, methods)*/ {
        return ptr::null();
    }

    if properties.is_not_null() /*&& !DefinePrefable(cx, ourProto, properties)*/ {
        return ptr::null();
    }

    if constants.is_not_null() /*&& !DefinePrefable(cx, ourProto, constants)*/ {
        return ptr::null();
    }

    return ourProto;
}

pub extern fn ThrowingConstructor(cx: *JSContext, argc: uint, vp: *JSVal) -> JSBool {
    //XXX should trigger exception here
    return 0;
}<|endoftext|>


<commit_before><commit_msg>add more tests for whitespace control<commit_after>extern crate liquid;

use liquid::LiquidOptions;
use liquid::Renderable;
use liquid::Context;
use liquid::parse;
use std::default::Default;

macro_rules! compare {
    ($input:expr, $output:expr) => {
        let input = $input.replace("…", " ");
        let expected = $output.replace("…", " ");
        let options: LiquidOptions = Default::default();
        let template = parse(&input, options).unwrap();

        let mut data = Context::new();
        let output = template.render(&mut data);
        assert_eq!(output.unwrap(), Some(expected));
    }
}

#[test]
pub fn no_whitespace_control() {
    compare!("
topic1
……{% assign foo = \"bar\" %}
……{% if foo %}
…………-……{{ foo }}
……{% endif %}
",
             "
topic1
……
……
…………-……bar
……
");
}

#[test]
pub fn simple_whitespace_control() {
    compare!("
topic1
……{% assign foo = \"bar\" -%}
……{% if foo -%}
…………-……{{- foo }}
……{%- endif %}
",
             "
topic1
……-bar
");
}

#[test]
pub fn double_sided_whitespace_control() {
    compare!("
topic1
……{%- assign foo = \"bar\" -%}
……-……{{- foo -}}……

",
             "
topic1-bar\
");
}
<|endoftext|>


<commit_before><commit_msg>Adding a test case for #2548<commit_after>// A test case for #2548.

// xfail-test

struct foo {
    x: @mut int;

    new(x: @mut int) { self.x = x; }

    drop {
        io::println("Goodbye, World!");
        *self.x += 1;
    }
}

fn main() {
    let x = @mut 0;

    {
        let mut res = foo(x);

        let mut v = ~[mut];
        v <- ~[mut res] + v;
    }

    assert *x == 1;
}
<|endoftext|>


<commit_before><commit_msg>test: Add a test case for vec growth<commit_after>// xfail-stage0

fn main() {
    auto v = vec(1);
    v += vec(2);
    v += vec(3);
    v += vec(4);
    v += vec(5);
    check (v.(0) == 1);
    check (v.(1) == 2);
    check (v.(2) == 3);
    check (v.(3) == 4);
    check (v.(4) == 5);
}

<|endoftext|>


<commit_before><commit_msg>We should expect a subscription to finish.<commit_after><|endoftext|>


<commit_before><commit_msg>some improvements<commit_after><|endoftext|>


<commit_before>use clap::{Arg, ArgMatches, App, SubCommand};

use tag::Tag;

/// Generates a `clap::SubCommand` to be integrated in the commandline-ui builder for building a
/// "tags --add foo --remove bar" subcommand to do tagging action.
pub fn tag_subcommand<'a, 'b>() -> App<'a, 'b> {
    SubCommand::with_name(tag_subcommand_name())
        .author("Matthias Beyer <mail@beyermatthias.de>")
        .version("0.1")
        .about("Add or remove tags")
        .arg(tag_add_arg())
        .arg(tag_remove_arg())
}

pub fn tag_add_arg<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name(tag_subcommand_add_arg_name())
        .short("a")
        .long("add")
        .takes_value(true)
        .multiple(true)
        .help("Add tags, seperated by comma or by specifying multiple times")
}

pub fn tag_remove_arg<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name(tag_subcommand_remove_arg_name())
        .short("r")
        .long("remove")
        .takes_value(true)
        .multiple(true)
        .help("Remove tags, seperated by comma or by specifying multiple times")
}

pub fn tag_subcommand_name() -> &'static str {
    "tags"
}

pub fn tag_subcommand_add_arg_name() -> &'static str {
    "add-tags"
}

pub fn tag_subcommand_remove_arg_name() -> &'static str {
    "remove-tags"
}

pub fn tag_subcommand_names() -> Vec<&'static str> {
    vec![tag_subcommand_add_arg_name(), tag_subcommand_remove_arg_name()]
}

/// Generates a `clap::Arg` which can be integrated into the commandline-ui builder for building a
/// "-t" or "--tags" argument which takes values for tagging actions (add, remove)
pub fn tag_argument<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name(tag_argument_name())
        .short("t")
        .long("tags")
        .takes_value(true)
        .multiple(true)
        .help("Add or remove tags, prefixed by '+' (for adding) or '-' (for removing)")
}

pub fn tag_argument_name() -> &'static str {
    "specify-tags"
}

/// Get the tags which should be added from the commandline
///
/// Returns none if the argument was not specified
pub fn get_add_tags(matches: &ArgMatches) -> Option<Vec<Tag>> {
    if let Some(v) = extract_tags(matches, tag_subcommand_add_arg_name(), '+') {
        return Some(v);
    } else {
        matches
            .values_of(tag_subcommand_add_arg_name())
            .map(|values| values.map(String::from).collect())
    }
}

/// Get the tags which should be removed from the commandline
///
/// Returns none if the argument was not specified
pub fn get_remove_tags(matches: &ArgMatches) -> Option<Vec<Tag>> {
    if let Some(v) = extract_tags(matches, tag_subcommand_remove_arg_name(), '-') {
        return Some(v);
    } else {
        matches
            .values_of(tag_subcommand_remove_arg_name())
            .map(|values| values.map(String::from).collect())
    }
}

fn extract_tags(matches: &ArgMatches, specifier: &str, specchar: char) -> Option<Vec<Tag>> {
    if let Some(submatch) = matches.subcommand_matches("tags") {
        submatch.values_of(specifier)
            .map(|values| values.map(String::from).collect())
    } else {
        matches.values_of("specify-tags")
            .map(|argmatches| {
                argmatches
                    .map(String::from)
                    .filter(|s| s.starts_with(specchar))
                    .map(|s| {
                        String::from(s.split_at(1).1)
                    })
                    .collect()
            })
    }
}

<commit_msg>Shorten code in get_add_tags()<commit_after>use clap::{Arg, ArgMatches, App, SubCommand};

use tag::Tag;

/// Generates a `clap::SubCommand` to be integrated in the commandline-ui builder for building a
/// "tags --add foo --remove bar" subcommand to do tagging action.
pub fn tag_subcommand<'a, 'b>() -> App<'a, 'b> {
    SubCommand::with_name(tag_subcommand_name())
        .author("Matthias Beyer <mail@beyermatthias.de>")
        .version("0.1")
        .about("Add or remove tags")
        .arg(tag_add_arg())
        .arg(tag_remove_arg())
}

pub fn tag_add_arg<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name(tag_subcommand_add_arg_name())
        .short("a")
        .long("add")
        .takes_value(true)
        .multiple(true)
        .help("Add tags, seperated by comma or by specifying multiple times")
}

pub fn tag_remove_arg<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name(tag_subcommand_remove_arg_name())
        .short("r")
        .long("remove")
        .takes_value(true)
        .multiple(true)
        .help("Remove tags, seperated by comma or by specifying multiple times")
}

pub fn tag_subcommand_name() -> &'static str {
    "tags"
}

pub fn tag_subcommand_add_arg_name() -> &'static str {
    "add-tags"
}

pub fn tag_subcommand_remove_arg_name() -> &'static str {
    "remove-tags"
}

pub fn tag_subcommand_names() -> Vec<&'static str> {
    vec![tag_subcommand_add_arg_name(), tag_subcommand_remove_arg_name()]
}

/// Generates a `clap::Arg` which can be integrated into the commandline-ui builder for building a
/// "-t" or "--tags" argument which takes values for tagging actions (add, remove)
pub fn tag_argument<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name(tag_argument_name())
        .short("t")
        .long("tags")
        .takes_value(true)
        .multiple(true)
        .help("Add or remove tags, prefixed by '+' (for adding) or '-' (for removing)")
}

pub fn tag_argument_name() -> &'static str {
    "specify-tags"
}

/// Get the tags which should be added from the commandline
///
/// Returns none if the argument was not specified
pub fn get_add_tags(matches: &ArgMatches) -> Option<Vec<Tag>> {
    let add = tag_subcommand_add_arg_name();
    extract_tags(matches, add, '+')
        .or_else(|| matches.values_of(add).map(|values| values.map(String::from).collect()))
}

/// Get the tags which should be removed from the commandline
///
/// Returns none if the argument was not specified
pub fn get_remove_tags(matches: &ArgMatches) -> Option<Vec<Tag>> {
    if let Some(v) = extract_tags(matches, tag_subcommand_remove_arg_name(), '-') {
        return Some(v);
    } else {
        matches
            .values_of(tag_subcommand_remove_arg_name())
            .map(|values| values.map(String::from).collect())
    }
}

fn extract_tags(matches: &ArgMatches, specifier: &str, specchar: char) -> Option<Vec<Tag>> {
    if let Some(submatch) = matches.subcommand_matches("tags") {
        submatch.values_of(specifier)
            .map(|values| values.map(String::from).collect())
    } else {
        matches.values_of("specify-tags")
            .map(|argmatches| {
                argmatches
                    .map(String::from)
                    .filter(|s| s.starts_with(specchar))
                    .map(|s| {
                        String::from(s.split_at(1).1)
                    })
                    .collect()
            })
    }
}

<|endoftext|>


<commit_before><commit_msg>Remove main.rs from top-level directory of /rs/trpl<commit_after><|endoftext|>


<commit_before><commit_msg>insertionsort1<commit_after><|endoftext|>


<commit_before><commit_msg>Auto merge of #10372 - weihanglo:issue-9325, r=ehuss<commit_after><|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use io;
use libc::{self, c_int, size_t, c_void};
use mem;
use sys::cvt;
use sys_common::AsInner;

pub struct FileDesc {
    fd: c_int,
}

impl FileDesc {
    pub fn new(fd: c_int) -> FileDesc {
        FileDesc { fd: fd }
    }

    pub fn raw(&self) -> c_int { self.fd }

    /// Extracts the actual filedescriptor without closing it.
    pub fn into_raw(self) -> c_int {
        let fd = self.fd;
        mem::forget(self);
        fd
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = try!(cvt(unsafe {
            libc::read(self.fd,
                       buf.as_mut_ptr() as *mut c_void,
                       buf.len() as size_t)
        }));
        Ok(ret as usize)
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        let ret = try!(cvt(unsafe {
            libc::write(self.fd,
                        buf.as_ptr() as *const c_void,
                        buf.len() as size_t)
        }));
        Ok(ret as usize)
    }

    #[cfg(not(target_env = "newlib"))]
    pub fn set_cloexec(&self) {
        unsafe {
            let ret = libc::ioctl(self.fd, libc::FIOCLEX);
            debug_assert_eq!(ret, 0);
        }
    }
    #[cfg(target_env = "newlib")]
    pub fn set_cloexec(&self) {
        unsafe {
            let previous = libc::fnctl(self.fd, libc::F_GETFD);
            let ret = libc::fnctl(self.fd, libc::F_SETFD, previous | libc::FD_CLOEXEC);
            debug_assert_eq!(ret, 0);
        }
    }
}

impl AsInner<c_int> for FileDesc {
    fn as_inner(&self) -> &c_int { &self.fd }
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        // Note that errors are ignored when closing a file descriptor. The
        // reason for this is that if an error occurs we don't actually know if
        // the file descriptor was closed or not, and if we retried (for
        // something like EINTR), we might close another valid file descriptor
        // (opened after we closed ours.
        let _ = unsafe { libc::close(self.fd) };
    }
}
<commit_msg>Fix a typo in `fd.rs`. Fixes #30231.<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use io;
use libc::{self, c_int, size_t, c_void};
use mem;
use sys::cvt;
use sys_common::AsInner;

pub struct FileDesc {
    fd: c_int,
}

impl FileDesc {
    pub fn new(fd: c_int) -> FileDesc {
        FileDesc { fd: fd }
    }

    pub fn raw(&self) -> c_int { self.fd }

    /// Extracts the actual filedescriptor without closing it.
    pub fn into_raw(self) -> c_int {
        let fd = self.fd;
        mem::forget(self);
        fd
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = try!(cvt(unsafe {
            libc::read(self.fd,
                       buf.as_mut_ptr() as *mut c_void,
                       buf.len() as size_t)
        }));
        Ok(ret as usize)
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        let ret = try!(cvt(unsafe {
            libc::write(self.fd,
                        buf.as_ptr() as *const c_void,
                        buf.len() as size_t)
        }));
        Ok(ret as usize)
    }

    #[cfg(not(target_env = "newlib"))]
    pub fn set_cloexec(&self) {
        unsafe {
            let ret = libc::ioctl(self.fd, libc::FIOCLEX);
            debug_assert_eq!(ret, 0);
        }
    }
    #[cfg(target_env = "newlib")]
    pub fn set_cloexec(&self) {
        unsafe {
            let previous = libc::fcntl(self.fd, libc::F_GETFD);
            let ret = libc::fcntl(self.fd, libc::F_SETFD, previous | libc::FD_CLOEXEC);
            debug_assert_eq!(ret, 0);
        }
    }
}

impl AsInner<c_int> for FileDesc {
    fn as_inner(&self) -> &c_int { &self.fd }
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        // Note that errors are ignored when closing a file descriptor. The
        // reason for this is that if an error occurs we don't actually know if
        // the file descriptor was closed or not, and if we retried (for
        // something like EINTR), we might close another valid file descriptor
        // (opened after we closed ours.
        let _ = unsafe { libc::close(self.fd) };
    }
}
<|endoftext|>


<commit_before><commit_msg>tidy: Use an inclusive range rather than a +1 bound<commit_after><|endoftext|>


<commit_before><commit_msg>just use full-normalization when for the impl trait ref<commit_after><|endoftext|>


<commit_before><commit_msg>feat: allows waiting for user input on error<commit_after><|endoftext|>


<commit_before><commit_msg>tests(fmt): removes fmt tests from Windows builds<commit_after><|endoftext|>


<commit_before><commit_msg>Fix some incorrect indentation in tests::archive_from_bytes_zero_length_memmap<commit_after><|endoftext|>


<commit_before><commit_msg>lib: update builder functions, add temp split<commit_after><|endoftext|>


<commit_before><commit_msg>Add push_back<commit_after><|endoftext|>