<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](../../std/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 cmp::Ordering;
use fmt;
use hash::{Hash, self};
use marker::Unsize;
use slice::{Iter, IterMut};

/// 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_rules! __impl_slice_eq1 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
            #[inline]
            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
        }
    }
}

macro_rules! __impl_slice_eq2 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq2! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        __impl_slice_eq1!($Lhs, $Rhs, $Bound);

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
            #[inline]
            fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
        }
    }
}

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

            #[stable(feature = "rust1", since = "1.0.0")]
            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:Copy> Clone for [T; $N] {
                fn clone(&self) -> [T; $N] {
                    *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}
<commit_msg>Auto merge of #43996 - shanavas786:fix-typo, r=frewsxcv<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](../../std/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 cmp::Ordering;
use fmt;
use hash::{Hash, self};
use marker::Unsize;
use slice::{Iter, IterMut};

/// 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_rules! __impl_slice_eq1 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
            #[inline]
            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
        }
    }
}

macro_rules! __impl_slice_eq2 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq2! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        __impl_slice_eq1!($Lhs, $Rhs, $Bound);

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
            #[inline]
            fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
        }
    }
}

// macro for implementing n-element array functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            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:Copy> Clone for [T; $N] {
                fn clone(&self) -> [T; $N] {
                    *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}
<|endoftext|>


<commit_before>/// Disk
pub mod disk;
/// MMIO
pub mod mmio;
/// PCI
pub mod pci;
/// PCI configuration
pub mod pciconfig;
/// PIO
pub mod pio;
/// PS2
pub mod ps2;
/// RTC
pub mod rtc;
/// Serial
pub mod serial;
<commit_msg>Add as module the Layouts package<commit_after>/// Disk
pub mod disk;
/// MMIO
pub mod mmio;
/// PCI
pub mod pci;
/// PCI configuration
pub mod pciconfig;
/// PIO
pub mod pio;
/// PS2
pub mod ps2;
/// RTC
pub mod rtc;
/// Serial
pub mod serial;
/// Layouts
pub mod kb_layouts;
<|endoftext|>


<commit_before>// extern crate bindgen;
#[cfg(target_env = "msvc")]
extern crate cc;
extern crate pkg_config;
extern crate num_cpus;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;

// Automatically write bindings to libsass
//#[allow(dead_code)]
//fn write_bindings() {
//    let bindings = bindgen::Builder::default()
//        .header("libsass/include/sass.h")
//        .clang_arg("-Ilibsass/include")
//        // To avoid a test failing
//        .blacklist_type("max_align_t")
//        // we do static linking so it should be fine
//        // https://github.com/rust-lang/rust/issues/36927
//        .rustified_enum(".*")
//        .generate()
//        .expect("Unable to generate bindings");
//
//    // Write the bindings to the $OUT_DIR/bindings.rs file.
//    let out_path = PathBuf::from("src");
//    bindings
//        .write_to_file(out_path.join("bindings.rs"))
//        .expect("Couldn't write bindings!");
//}

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => panic!("\n{} failed with {}\n", stringify!($e), e),
    })
}

fn cp_r(dir: &Path, dest: &Path) {
    for entry in t!(fs::read_dir(dir)) {
        let entry = t!(entry);
        let path = entry.path();
        let dst = dest.join(path.file_name().unwrap());
        if t!(fs::metadata(&path)).is_file() {
            t!(fs::copy(path, dst));
        } else {
            t!(fs::create_dir_all(&dst));
            cp_r(&path, &dst);
        }
    }
}

fn get_libsass_folder() -> PathBuf {
    env::current_dir().unwrap().join("libsass")
}

// linux/unix
#[cfg(not(target_env = "msvc"))]
fn compile() {
    let target = env::var("TARGET").expect("TARGET not found");
    let src = get_libsass_folder();
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);
    let is_bsd = target.contains("dragonfly")
        || target.contains("freebsd")
        || target.contains("netbsd")
        || target.contains("openbsd");

    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or(num_cpus::get().to_string());
    let r = Command::new(if is_bsd { "gmake" } else { "make" })
        .current_dir(&build)
        .args(&["--jobs", &jobs])
        .output()
        .expect("error running make");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("lib").display()
    );
    println!("cargo:rustc-link-lib=static=sass");
    println!(
        "cargo:rustc-link-lib=dylib={}",
        if target.contains("darwin") || is_bsd {
            "c++"
        } else {
            "stdc++"
        }
    );
}

// windows
#[cfg(target_env = "msvc")]
fn compile() {
    let src = get_libsass_folder();
    let target = env::var("TARGET").expect("TARGET not found in environment");
    let msvc_platform = if target.contains("x86_64") {
        "Win64"
    } else {
        "Win32"
    };
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);

    // Find an instance of devenv.exe from Visual Studio IDE in order to upgrade
    // libsass.sln to the current available IDE. Do nothing if no devenv.exe found
    let d = cc::windows_registry::find(target.as_str(), "devenv.exe");
    if let Some(mut d) = d {
        let d = d
            .args(&["/upgrade", "win\\libsass.sln"])
            .current_dir(&build)
            .output()
            .expect("error running devenv");
        if !d.status.success() {
            let err = String::from_utf8_lossy(&d.stderr);
            let out = String::from_utf8_lossy(&d.stdout);
            println!("Upgrade error:\nSTDERR:{}\nSTDOUT:{}", err, out);
        }
    }

    let r = cc::windows_registry::find(target.as_str(), "msbuild.exe")
        .expect("could not find msbuild")
        .args(&[
            "win\\libsass.sln",
            "/p:LIBSASS_STATIC_LIB=1",
            "/p:Configuration=Release",
            "/p:WholeProgramOptimization=false",
            format!("/p:Platform={}", msvc_platform).as_str(),
        ])
        .current_dir(&build)
        .output()
        .expect("error running msbuild");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("win").join("bin").display()
    );
    println!("cargo:rustc-link-lib=static=libsass");
}

fn main() {
    // Uncomment the line below to generate bindings. Doesn't work on CI as it
    // requires additional tooling
    // write_bindings();

    // Is it already built?
    if let Ok(_) = pkg_config::find_library("sass") {
        return;
    }

    compile();
}
<commit_msg>build: upstream name for pkg-config is libsass<commit_after>// extern crate bindgen;
#[cfg(target_env = "msvc")]
extern crate cc;
extern crate pkg_config;
extern crate num_cpus;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;

// Automatically write bindings to libsass
//#[allow(dead_code)]
//fn write_bindings() {
//    let bindings = bindgen::Builder::default()
//        .header("libsass/include/sass.h")
//        .clang_arg("-Ilibsass/include")
//        // To avoid a test failing
//        .blacklist_type("max_align_t")
//        // we do static linking so it should be fine
//        // https://github.com/rust-lang/rust/issues/36927
//        .rustified_enum(".*")
//        .generate()
//        .expect("Unable to generate bindings");
//
//    // Write the bindings to the $OUT_DIR/bindings.rs file.
//    let out_path = PathBuf::from("src");
//    bindings
//        .write_to_file(out_path.join("bindings.rs"))
//        .expect("Couldn't write bindings!");
//}

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => panic!("\n{} failed with {}\n", stringify!($e), e),
    })
}

fn cp_r(dir: &Path, dest: &Path) {
    for entry in t!(fs::read_dir(dir)) {
        let entry = t!(entry);
        let path = entry.path();
        let dst = dest.join(path.file_name().unwrap());
        if t!(fs::metadata(&path)).is_file() {
            t!(fs::copy(path, dst));
        } else {
            t!(fs::create_dir_all(&dst));
            cp_r(&path, &dst);
        }
    }
}

fn get_libsass_folder() -> PathBuf {
    env::current_dir().unwrap().join("libsass")
}

// linux/unix
#[cfg(not(target_env = "msvc"))]
fn compile() {
    let target = env::var("TARGET").expect("TARGET not found");
    let src = get_libsass_folder();
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);
    let is_bsd = target.contains("dragonfly")
        || target.contains("freebsd")
        || target.contains("netbsd")
        || target.contains("openbsd");

    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or(num_cpus::get().to_string());
    let r = Command::new(if is_bsd { "gmake" } else { "make" })
        .current_dir(&build)
        .args(&["--jobs", &jobs])
        .output()
        .expect("error running make");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("lib").display()
    );
    println!("cargo:rustc-link-lib=static=sass");
    println!(
        "cargo:rustc-link-lib=dylib={}",
        if target.contains("darwin") || is_bsd {
            "c++"
        } else {
            "stdc++"
        }
    );
}

// windows
#[cfg(target_env = "msvc")]
fn compile() {
    let src = get_libsass_folder();
    let target = env::var("TARGET").expect("TARGET not found in environment");
    let msvc_platform = if target.contains("x86_64") {
        "Win64"
    } else {
        "Win32"
    };
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);

    // Find an instance of devenv.exe from Visual Studio IDE in order to upgrade
    // libsass.sln to the current available IDE. Do nothing if no devenv.exe found
    let d = cc::windows_registry::find(target.as_str(), "devenv.exe");
    if let Some(mut d) = d {
        let d = d
            .args(&["/upgrade", "win\\libsass.sln"])
            .current_dir(&build)
            .output()
            .expect("error running devenv");
        if !d.status.success() {
            let err = String::from_utf8_lossy(&d.stderr);
            let out = String::from_utf8_lossy(&d.stdout);
            println!("Upgrade error:\nSTDERR:{}\nSTDOUT:{}", err, out);
        }
    }

    let r = cc::windows_registry::find(target.as_str(), "msbuild.exe")
        .expect("could not find msbuild")
        .args(&[
            "win\\libsass.sln",
            "/p:LIBSASS_STATIC_LIB=1",
            "/p:Configuration=Release",
            "/p:WholeProgramOptimization=false",
            format!("/p:Platform={}", msvc_platform).as_str(),
        ])
        .current_dir(&build)
        .output()
        .expect("error running msbuild");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("win").join("bin").display()
    );
    println!("cargo:rustc-link-lib=static=libsass");
}

fn main() {
    // Uncomment the line below to generate bindings. Doesn't work on CI as it
    // requires additional tooling
    // write_bindings();

    // Is it already built?
    if let Ok(_) = pkg_config::find_library("libsass") {
        return;
    }

    compile();
}
<|endoftext|>


<commit_before>#[link(name="rmdir", vers="1.0.0", author="Arcterus")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern mod extra;

use std::os;
use std::io::{stderr, io_error, fs};
use extra::getopts::groups;

fn main() {
    let args = os::args();
    let program = args[0].clone();

    let opts = ~[
        groups::optflag("", "ignore-fail-on-non-empty", "ignore each failure that is solely because a directory is non-empty"),
        groups::optflag("p", "parents", "remove DIRECTORY and its ancestors; e.g., 'rmdir -p a/b/c' is similar to rmdir a/b/c a/b a"),
        groups::optflag("v", "verbose", "output a diagnostic for every directory processed"),
        groups::optflag("", "help", "print this help and exit"),
        groups::optflag("", "version", "output version information and exit")
    ];
    let matches = match groups::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut stderr() as &mut Writer, "{}", f.to_err_msg());
            os::set_exit_status(1);
            return
        }
    };

    if matches.opt_present("help") {
        println("rmdir 1.0.0");
        println("");
        println("Usage:");
        println!("  {0:s} [OPTION]... DIRECTORY...", program);
        println("");
        print(groups::usage("Remove the DIRECTORY(ies), if they are empty.", opts));
    } else if matches.opt_present("version") {
        println("rmdir 1.0.0");
    } else if matches.free.is_empty() {
        writeln!(&mut stderr() as &mut Writer, "Missing an argument");
        writeln!(&mut stderr() as &mut Writer,
                 "For help, try '{0:s} --help'", program);
        os::set_exit_status(1);
    } else {
        let ignore = matches.opt_present("ignore-fail-on-non-empty");
        let parents = matches.opt_present("parents");
        let verbose = matches.opt_present("verbose");
        remove(matches.free, ignore, parents, verbose);
    }
}

fn remove(dirs: &[~str], ignore: bool, parents: bool, verbose: bool) {
    for dir in dirs.iter() {
        let path = Path::new(dir.to_owned());
        if path.exists() {
            if path.is_dir() {
                remove_dir(&path, dir, ignore, parents, verbose);
            } else {
                writeln!(&mut stderr() as &mut Writer,
                         "Failed to remove '{}' (file)", *dir);
                os::set_exit_status(1);
            }
        } else {
            writeln!(&mut stderr() as &mut Writer,
                     "No such file or directory '{}'", *dir);
            os::set_exit_status(1);
        }
    }
}

fn remove_dir(path: &Path, dir: &~str, ignore: bool, parents: bool, verbose: bool) {
    if fs::walk_dir(path).next() == None {
        io_error::cond.trap(|_| {
            writeln!(&mut stderr() as &mut Writer,
                     "Failed to remove directory '{}'", *dir);
            os::set_exit_status(1);
        }).inside(|| {
            fs::rmdir(path);
            if verbose {
                println!("Removed directory '{}'", *dir);
            }
            if parents {
                let dirname = path.dirname_str().unwrap();
                if dirname != "." {
                    remove_dir(&Path::new(dirname), &dirname.to_owned(), ignore, parents, verbose);
                }
            }
        });
    } else if !ignore {
        writeln!(&mut stderr() as &mut Writer,
                 "Failed to remove directory '{}' (non-empty)", *dir);
        os::set_exit_status(1);
    }
}

<commit_msg>Added the aliases -h and -V for --help and --version to rmdir<commit_after>#[link(name="rmdir", vers="1.0.0", author="Arcterus")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern mod extra;

use std::os;
use std::io::{stderr, io_error, fs};
use extra::getopts::groups;

fn main() {
    let args = os::args();
    let program = args[0].clone();

    let opts = ~[
        groups::optflag("", "ignore-fail-on-non-empty", "ignore each failure that is solely because a directory is non-empty"),
        groups::optflag("p", "parents", "remove DIRECTORY and its ancestors; e.g., 'rmdir -p a/b/c' is similar to rmdir a/b/c a/b a"),
        groups::optflag("v", "verbose", "output a diagnostic for every directory processed"),
        groups::optflag("h", "help", "print this help and exit"),
        groups::optflag("V", "version", "output version information and exit")
    ];
    let matches = match groups::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut stderr() as &mut Writer, "{}", f.to_err_msg());
            os::set_exit_status(1);
            return
        }
    };

    if matches.opt_present("help") {
        println("rmdir 1.0.0");
        println("");
        println("Usage:");
        println!("  {0:s} [OPTION]... DIRECTORY...", program);
        println("");
        print(groups::usage("Remove the DIRECTORY(ies), if they are empty.", opts));
    } else if matches.opt_present("version") {
        println("rmdir 1.0.0");
    } else if matches.free.is_empty() {
        writeln!(&mut stderr() as &mut Writer, "Missing an argument");
        writeln!(&mut stderr() as &mut Writer,
                 "For help, try '{0:s} --help'", program);
        os::set_exit_status(1);
    } else {
        let ignore = matches.opt_present("ignore-fail-on-non-empty");
        let parents = matches.opt_present("parents");
        let verbose = matches.opt_present("verbose");
        remove(matches.free, ignore, parents, verbose);
    }
}

fn remove(dirs: &[~str], ignore: bool, parents: bool, verbose: bool) {
    for dir in dirs.iter() {
        let path = Path::new(dir.to_owned());
        if path.exists() {
            if path.is_dir() {
                remove_dir(&path, dir, ignore, parents, verbose);
            } else {
                writeln!(&mut stderr() as &mut Writer,
                         "Failed to remove '{}' (file)", *dir);
                os::set_exit_status(1);
            }
        } else {
            writeln!(&mut stderr() as &mut Writer,
                     "No such file or directory '{}'", *dir);
            os::set_exit_status(1);
        }
    }
}

fn remove_dir(path: &Path, dir: &~str, ignore: bool, parents: bool, verbose: bool) {
    if fs::walk_dir(path).next() == None {
        io_error::cond.trap(|_| {
            writeln!(&mut stderr() as &mut Writer,
                     "Failed to remove directory '{}'", *dir);
            os::set_exit_status(1);
        }).inside(|| {
            fs::rmdir(path);
            if verbose {
                println!("Removed directory '{}'", *dir);
            }
            if parents {
                let dirname = path.dirname_str().unwrap();
                if dirname != "." {
                    remove_dir(&Path::new(dirname), &dirname.to_owned(), ignore, parents, verbose);
                }
            }
        });
    } else if !ignore {
        writeln!(&mut stderr() as &mut Writer,
                 "Failed to remove directory '{}' (non-empty)", *dir);
        os::set_exit_status(1);
    }
}

<|endoftext|>


<commit_before>use autocxx_macro::include_cxx;

// The following syntax is very interim as I haven't figured out
// how to parse a string inside a procedural macro yet(!)
include_cxx!(
    <input>,
    <DoMath>
);

fn main() {
    println!("Hello, world! - C++ math should say 12={}", ffi::DoMath(4));
}
<commit_msg>Another note.<commit_after>use autocxx_macro::include_cxx;

// The following syntax is very interim as I haven't figured out
// how to parse a string inside a procedural macro yet(!)
// Also, 'input' is supposed to refer to input.h, but currently
// that name is totally hardcoded in our hacky fork of bindgen, so don't
// attempt to change it!
include_cxx!(
    <input>,
    <DoMath>
);

fn main() {
    println!("Hello, world! - C++ math should say 12={}", ffi::DoMath(4));
}
<|endoftext|>


<commit_before>use std::ops::{Index, IndexMut};

#[derive(Debug)]
pub struct SquareMatrix<T> {
    n: usize,
    data: Box<[T]>,
}

impl<T> Index<(usize, usize)> for SquareMatrix<T> {
    type Output = T;

    /// (row, col)
    #[inline(always)]
    fn index<'a>(&'a self, pos: (usize, usize)) -> &'a T {
        match pos {
            (row, col) => {
                let idx = row * self.n + col;
                &self.data[idx]
            }
        }
    }
}

impl<T> IndexMut<(usize, usize)> for SquareMatrix<T> {
    /// (row, col)
    #[inline(always)]
    fn index_mut<'a>(&'a mut self, pos: (usize, usize)) -> &'a mut T {
        match pos {
            (row, col) => {
                let idx = row * self.n + col;
                &mut self.data[idx]
            }
        }
    }
}

impl<T: Copy> SquareMatrix<T> {
    pub fn from_fn<F: Fn((usize, usize)) -> T>(n: usize, f: F) -> SquareMatrix<T> {
        let data = (0..n * n).map(|i| f((i / n, i % n))).collect();
        SquareMatrix::from_row_vec(n, data)
    }

    pub fn from_row_vec(n: usize, data: Vec<T>) -> SquareMatrix<T> {
        assert!(n > 0);
        assert!(data.len() == n * n);
        SquareMatrix {
            n: n,
            data: data.into_boxed_slice(),
        }
    }
    #[inline(always)]
    pub fn n(&self) -> usize {
        self.n
    }

    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        &self.data[..]
    }

    #[inline]
    pub fn row_slice(&self, row: usize) -> &[T] {
        &self.data[row * self.n..(row + 1) * self.n]
    }

    #[inline]
    pub fn row_slice_mut(&mut self, row: usize) -> &mut [T] {
        &mut self.data[row * self.n..(row + 1) * self.n]
    }

    #[inline]
    pub fn map_row<F: Fn(T) -> T>(&mut self, row: usize, f: F) {
        let n = self.n;
        assert!(row < n);

        let mut row_slice = self.row_slice_mut(row);
        debug_assert!(row_slice.len() == n);

        for elm in row_slice.iter_mut() {
            *elm = f(*elm);
        }
    }

    #[inline]
    pub fn map_col<F: Fn(T) -> T>(&mut self, col: usize, f: F) {
        for row in 0..self.n {
            let n = f(self[(row, col)]);
            self[(row, col)] = n;
        }
    }

}
<commit_msg>Add test cases for SquareMatrix<commit_after>use std::ops::{Index, IndexMut};

#[derive(Debug)]
pub struct SquareMatrix<T> {
    n: usize,
    data: Box<[T]>,
}

impl<T> Index<(usize, usize)> for SquareMatrix<T> {
    type Output = T;

    /// (row, col)
    #[inline(always)]
    fn index<'a>(&'a self, pos: (usize, usize)) -> &'a T {
        let (row, col) = pos;
        let idx = row * self.n + col;
        &self.data[idx]
    }
}

impl<T> IndexMut<(usize, usize)> for SquareMatrix<T> {
    /// (row, col)
    #[inline(always)]
    fn index_mut<'a>(&'a mut self, pos: (usize, usize)) -> &'a mut T {
        let (row, col) = pos;
        let idx = row * self.n + col;
        &mut self.data[idx]
    }
}

impl<T: Copy> SquareMatrix<T> {
    pub fn from_fn<F: Fn((usize, usize)) -> T>(n: usize, f: F) -> SquareMatrix<T> {
        let data = (0..n * n).map(|i| f((i / n, i % n))).collect();
        SquareMatrix::from_row_vec(n, data)
    }

    pub fn from_row_vec(n: usize, data: Vec<T>) -> SquareMatrix<T> {
        assert!(n > 0);
        assert!(data.len() == n * n);
        SquareMatrix {
            n: n,
            data: data.into_boxed_slice(),
        }
    }

    #[inline(always)]
    pub fn n(&self) -> usize {
        self.n
    }

    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        &self.data[..]
    }

    #[inline]
    pub fn row_slice(&self, row: usize) -> &[T] {
        assert!(row < self.n);
        &self.data[row * self.n..(row + 1) * self.n]
    }

    #[inline]
    pub fn row_slice_mut(&mut self, row: usize) -> &mut [T] {
        assert!(row < self.n);
        &mut self.data[row * self.n..(row + 1) * self.n]
    }

    #[inline]
    pub fn map_row<F: Fn(T) -> T>(&mut self, row: usize, f: F) {
        let n = self.n;
        assert!(row < n);

        let mut row_slice = self.row_slice_mut(row);
        debug_assert!(row_slice.len() == n);

        for elm in row_slice.iter_mut() {
            *elm = f(*elm);
        }
    }

    #[inline]
    pub fn map_col<F: Fn(T) -> T>(&mut self, col: usize, f: F) {
        for row in 0..self.n {
            let mut elm = &mut self[(row, col)];
            *elm = f(*elm);
        }
    }

}

#[test]
fn test_square_matrix() {
    let mat = SquareMatrix::from_row_vec(2, vec![1, 2, 3, 4]);
    assert_eq!(2, mat.n());

    assert_eq!(1, mat[(0,0)]);
    assert_eq!(2, mat[(0,1)]);
    assert_eq!(3, mat[(1,0)]);
    assert_eq!(4, mat[(1,1)]);

    assert_eq!(&[1,2,3,4], mat.as_slice());
    assert_eq!(&[1,2], mat.row_slice(0));
    assert_eq!(&[3,4], mat.row_slice(1));

    let mut mat = mat;

    mat.map_row(0, |i| i + 5);
    assert_eq!(&[6,7,3,4], mat.as_slice());

    mat.map_col(1, |i| i + 2);
    assert_eq!(&[6,9,3,6], mat.as_slice());
    mat.map_col(0, |i| i + 3);
    assert_eq!(&[9,9,6,6], mat.as_slice());

    let mat = SquareMatrix::from_fn(3, |(row, _col)| row);
    assert_eq!(&[0,0,0,1,1,1,2,2,2], mat.as_slice());

    let mat = SquareMatrix::from_fn(3, |(_row, col)| col);
    assert_eq!(&[0,1,2,0,1,2,0,1,2], mat.as_slice());

    let mat = SquareMatrix::from_fn(3, |(row, col)| row + col);
    assert_eq!(&[0,1,2,1,2,3,2,3,4], mat.as_slice());
}
<|endoftext|>


<commit_before>use std::io::{IoError, TcpListener, Listener, Acceptor, TcpStream, IoResult};

use knuckle::{cryptobox, sign};
use knuckle::util::random_bytes;
use knuckle::cryptobox::{CryptoBox, Keypair};

use mittens::socks;
use mittens::config::RelayConfig;

struct ServerConnection {
    verify_key: sign::PublicKey,
    cbox: cryptobox::CryptoBox,
    control: TcpStream
}

impl ServerConnection {
    fn new(conf: &RelayConfig) -> IoResult<ServerConnection> {
        let control = try!(TcpStream::connect_timeout(conf.server_addr, 5000));

        // TODO: REMOVE ME
        let key = Keypair::new();

        Ok(ServerConnection {
            verify_key: conf.verify_key,
            cbox: CryptoBox::from_key_pair(key.sk, key.pk),
            control: control
        })
    }

    /// Challenge the server with a random nonce, ensure that they can
    /// produce a valid signature.
    fn verify_stream(&mut self) -> IoResult<()> {
        let nonce = random_bytes(128);
        let resp = try!(self.send(nonce.as_slice()));

        let smsg = sign::SignedMsg {
            pk: self.verify_key,
            signed: resp
        };

        match smsg.verify() {
            Some(ref msg) if *msg == nonce => Ok(()),
            _ => Err(IoError::last_error())
        }
    }

    fn establish_connection(&mut self) -> IoResult<()> {
        try!(self.verify_stream());

        Ok(())
    }

    fn send(&mut self, msg: &[u8]) -> IoResult<Vec<u8>> {
        let ciphertext = self.cbox.encrypt(msg).as_bytes();

        try!(self.control.write_be_uint(ciphertext.len()));
        try!(self.control.write(ciphertext.as_slice()));

        let len = try!(self.control.read_be_uint());
        self.control.read_exact(len)
    }
}

pub fn start_relay(conf: RelayConfig) {
    let server_conn = match ServerConnection::new(&conf)
        .and_then(|mut c| c.verify_stream()) {
            Ok(conn) => conn,
            Err(x) => fail!("Failed to establish secure connection: {}", x)
        };

    let listener = TcpListener::bind(conf.relay_host.as_slice(),
                                     conf.relay_port);
    let mut acceptor = listener.listen().unwrap();

    for stream in acceptor.incoming() {
        match stream {
            Err(_) => { /* TODO: handle errors */ }
            Ok(mut stream) => socks::handle_stream(&mut stream)
        }
    }

    drop(acceptor);
}
<commit_msg>Add send_raw<commit_after>use std::io::{IoError, TcpListener, Listener, Acceptor, TcpStream, IoResult};

use knuckle::{cryptobox, sign};
use knuckle::util::random_bytes;
use knuckle::cryptobox::{CryptoBox, Keypair};

use mittens::socks;
use mittens::config::RelayConfig;

struct ServerConnection {
    verify_key: sign::PublicKey,
    cbox: cryptobox::CryptoBox,
    control: TcpStream
}

impl ServerConnection {
    fn new(conf: &RelayConfig) -> IoResult<ServerConnection> {
        let control = try!(TcpStream::connect_timeout(conf.server_addr, 5000));

        // TODO: REMOVE ME
        let key = Keypair::new();

        Ok(ServerConnection {
            verify_key: conf.verify_key,
            cbox: CryptoBox::from_key_pair(key.sk, key.pk),
            control: control
        })
    }

    /// Challenge the server with a random nonce, ensure that they can
    /// produce a valid signature.
    fn verify_stream(&mut self) -> IoResult<()> {
        let nonce = random_bytes(128);
        let resp = try!(self.send(nonce.as_slice()));

        let smsg = sign::SignedMsg {
            pk: self.verify_key,
            signed: resp
        };

        match smsg.verify() {
            Some(ref msg) if *msg == nonce => Ok(()),
            _ => Err(IoError::last_error())
        }
    }

    fn establish_connection(&mut self) -> IoResult<()> {
        try!(self.verify_stream());

        Ok(())
    }

    fn send(&mut self, msg: &[u8]) -> IoResult<Vec<u8>> {
        let ciphertext = self.cbox.encrypt(msg).as_bytes();

        self.send_raw(ciphertext.as_slice())
    }

    fn send_raw(&mut self, msg: &[u8]) -> IoResult<Vec<u8>> {
        try!(self.control.write_be_uint(msg.len()));
        try!(self.control.write(msg.as_slice()));

        let len = try!(self.control.read_be_uint());
        self.control.read_exact(len)
    }
}

pub fn start_relay(conf: RelayConfig) {
    let server_conn = match ServerConnection::new(&conf)
        .and_then(|mut c| c.verify_stream()) {
            Ok(conn) => conn,
            Err(x) => fail!("Failed to establish secure connection: {}", x)
        };

    let listener = TcpListener::bind(conf.relay_host.as_slice(),
                                     conf.relay_port);
    let mut acceptor = listener.listen().unwrap();

    for stream in acceptor.incoming() {
        match stream {
            Err(_) => { /* TODO: handle errors */ }
            Ok(mut stream) => socks::handle_stream(&mut stream)
        }
    }

    drop(acceptor);
}
<|endoftext|>


<commit_before>#![allow(unused_imports)]
#![allow(dead_code)]

use nom::{IResult};
use nom::IResult::*;
use nom::Err::*;

use nom::{digit,is_alphanumeric};

use std::str;

// Primitives
fn is_token_char(i: u8) -> bool {
  is_alphanumeric(i) ||
  b"!#$%&'*+-.^_`|~".contains(&i)
}
named!(pub token, take_while!(is_token_char));

fn is_ws(i: u8) -> bool {
  i == ' ' as u8 && i == '\t' as u8
}
named!(pub repeated_ws, take_while!(is_ws));
named!(pub obsolete_ws, chain!(repeated_ws?, || { &b" "[..] }));

named!(pub sp, tag!(" "));
named!(pub crlf, tag!("\r\n"));

fn is_vchar(i: u8) -> bool {
  i > 32 && i <= 126
}
fn is_vchar_or_ws(i: u8) -> bool {
  is_vchar(i) || is_ws(i)
}

named!(pub vchar_1, take_while!(is_vchar));
named!(pub vchar_ws_1, take_while!(is_vchar_or_ws));

#[derive(PartialEq,Debug)]
pub struct RequestLine<'a> {
    pub method: &'a [u8],
    pub uri: &'a [u8],
    pub version: [&'a [u8];2]
}

#[derive(PartialEq,Debug,Clone)]
pub struct RRequestLine {
    pub method: String,
    pub uri: String,
    pub version: String
}

impl RRequestLine {
  pub fn fromRequestLine(r: RequestLine) -> Option<RRequestLine> {
    if let Ok(method) = str::from_utf8(r.method) {
      if let Ok(uri) = str::from_utf8(r.uri) {
        if let Ok(version1) = str::from_utf8(r.version[0]) {
          if let Ok(version2) = str::from_utf8(r.version[1]) {
            Some(RRequestLine {
              method:  String::from(method),
              uri:     String::from(uri),
              version: String::from(version1) + version2
            })
          } else {
            None
          }
        } else {
          None
        }
      } else {
        None
      }
    } else {
      None
    }
  }
}

named!(pub http_version<[&[u8];2]>,
       chain!(
        tag!("HTTP/") ~
        major: digit ~
        tag!(".") ~
        minor: digit, || {
            [minor, major] // ToDo do we need it?
        }
       )
);

named!(pub request_line<RequestLine>,
       chain!(
        method: token ~
        sp ~
        uri: vchar_1 ~ // ToDo proper URI parsing?
        sp ~
        version: http_version ~
        crlf, || {
            RequestLine {
              method: method,
              uri: uri,
              version: version
            }
        }
       )
);

#[derive(PartialEq,Debug)]
pub struct RequestHeader<'a> {
    pub name: &'a [u8],
    pub value: &'a [u8]
}

named!(pub message_header<RequestHeader>,
       chain!(
         name: token ~
         tag!(":") ~
         sp ~ // ToDo make it optional
         value: vchar_1 ~ // ToDo handle folding?
         crlf, || {
           RequestHeader {
            name: name,
            value: value
           }
         }
       )
);

named!(pub headers< Vec<RequestHeader> >, many0!(message_header));

#[derive(PartialEq,Debug)]
pub struct RequestHead<'a> {
    pub request_line: RequestLine<'a>,
    pub headers: Vec<RequestHeader<'a>>
}

named!(pub request_head<RequestHead>,
       chain!(
        rl: request_line ~
        hs: many0!(message_header) ~
        crlf, || {
          RequestHead {
            request_line: rl,
            headers: hs
          }
        }
       )
);

#[cfg(test)]
mod tests {
  use super::*;
  use nom::*;
  use nom::IResult::*;

  #[test]
  fn request_line_test() {
      let input = b"GET /index.html HTTP/1.1\r\n";
      let result = request_line(input);
      let expected = RequestLine {
        method: b"GET",
        uri: b"/index.html",
        version: [b"1", b"1"]
      };

      assert_eq!(result, Done(&[][..], expected));
  }

  #[test]
  fn header_test() {
      let input = b"Accept: */*\r\n";
      let result = message_header(input);
      let expected = RequestHeader {
        name: b"Accept",
        value: b"*/*"
      };

      assert_eq!(result, Done(&b""[..], expected))
  }

  #[test]
  fn request_head_test() {
      let input =
          b"GET /index.html HTTP/1.1\r\n\
            Host: localhost:8888\r\n\
            User-Agent: curl/7.43.0\r\n\
            Accept: */*\r\n\
            \r\n";
      let result = request_head(input);
      let expected = RequestHead {
        request_line: RequestLine {
        method: b"GET",
        uri: b"/index.html",
        version: [b"1", b"1"]
      },
        headers: vec!(
          RequestHeader {
            name: b"Host",
            value: b"localhost:8888"
          },
          RequestHeader {
            name: b"User-Agent",
            value: b"curl/7.43.0"
          },
          RequestHeader {
            name: b"Accept",
            value: b"*/*"
          }
        )
      };

      assert_eq!(result, Done(&b""[..], expected))
  }
}
<commit_msg>we can use character parsers now<commit_after>#![allow(unused_imports)]
#![allow(dead_code)]

use nom::{IResult};
use nom::IResult::*;
use nom::Err::*;

use nom::{digit,is_alphanumeric};

use std::str;

// Primitives
fn is_token_char(i: u8) -> bool {
  is_alphanumeric(i) ||
  b"!#$%&'*+-.^_`|~".contains(&i)
}
named!(pub token, take_while!(is_token_char));

fn is_ws(i: u8) -> bool {
  i == ' ' as u8 && i == '\t' as u8
}
named!(pub repeated_ws, take_while!(is_ws));
named!(pub obsolete_ws, chain!(repeated_ws?, || { &b" "[..] }));

named!(pub sp<char>, char!(' '));
named!(pub crlf, tag!("\r\n"));

fn is_vchar(i: u8) -> bool {
  i > 32 && i <= 126
}
fn is_vchar_or_ws(i: u8) -> bool {
  is_vchar(i) || is_ws(i)
}

named!(pub vchar_1, take_while!(is_vchar));
named!(pub vchar_ws_1, take_while!(is_vchar_or_ws));

#[derive(PartialEq,Debug)]
pub struct RequestLine<'a> {
    pub method: &'a [u8],
    pub uri: &'a [u8],
    pub version: [&'a [u8];2]
}

#[derive(PartialEq,Debug,Clone)]
pub struct RRequestLine {
    pub method: String,
    pub uri: String,
    pub version: String
}

impl RRequestLine {
  pub fn fromRequestLine(r: RequestLine) -> Option<RRequestLine> {
    if let Ok(method) = str::from_utf8(r.method) {
      if let Ok(uri) = str::from_utf8(r.uri) {
        if let Ok(version1) = str::from_utf8(r.version[0]) {
          if let Ok(version2) = str::from_utf8(r.version[1]) {
            Some(RRequestLine {
              method:  String::from(method),
              uri:     String::from(uri),
              version: String::from(version1) + version2
            })
          } else {
            None
          }
        } else {
          None
        }
      } else {
        None
      }
    } else {
      None
    }
  }
}

named!(pub http_version<[&[u8];2]>,
       chain!(
        tag!("HTTP/") ~
        major: digit ~
        tag!(".") ~
        minor: digit, || {
            [minor, major] // ToDo do we need it?
        }
       )
);

named!(pub request_line<RequestLine>,
       chain!(
        method: token ~
        sp ~
        uri: vchar_1 ~ // ToDo proper URI parsing?
        sp ~
        version: http_version ~
        crlf, || {
            RequestLine {
              method: method,
              uri: uri,
              version: version
            }
        }
       )
);

#[derive(PartialEq,Debug)]
pub struct RequestHeader<'a> {
    pub name: &'a [u8],
    pub value: &'a [u8]
}

named!(pub message_header<RequestHeader>,
       chain!(
         name: token ~
         tag!(":") ~
         sp ~ // ToDo make it optional
         value: vchar_1 ~ // ToDo handle folding?
         crlf, || {
           RequestHeader {
            name: name,
            value: value
           }
         }
       )
);

named!(pub headers< Vec<RequestHeader> >, many0!(message_header));

#[derive(PartialEq,Debug)]
pub struct RequestHead<'a> {
    pub request_line: RequestLine<'a>,
    pub headers: Vec<RequestHeader<'a>>
}

named!(pub request_head<RequestHead>,
       chain!(
        rl: request_line ~
        hs: many0!(message_header) ~
        crlf, || {
          RequestHead {
            request_line: rl,
            headers: hs
          }
        }
       )
);

#[cfg(test)]
mod tests {
  use super::*;
  use nom::IResult::*;

  #[test]
  fn request_line_test() {
      let input = b"GET /index.html HTTP/1.1\r\n";
      let result = request_line(input);
      let expected = RequestLine {
        method: b"GET",
        uri: b"/index.html",
        version: [b"1", b"1"]
      };

      assert_eq!(result, Done(&[][..], expected));
  }

  #[test]
  fn header_test() {
      let input = b"Accept: */*\r\n";
      let result = message_header(input);
      let expected = RequestHeader {
        name: b"Accept",
        value: b"*/*"
      };

      assert_eq!(result, Done(&b""[..], expected))
  }

  #[test]
  fn request_head_test() {
      let input =
          b"GET /index.html HTTP/1.1\r\n\
            Host: localhost:8888\r\n\
            User-Agent: curl/7.43.0\r\n\
            Accept: */*\r\n\
            \r\n";
      let result = request_head(input);
      let expected = RequestHead {
        request_line: RequestLine {
        method: b"GET",
        uri: b"/index.html",
        version: [b"1", b"1"]
      },
        headers: vec!(
          RequestHeader {
            name: b"Host",
            value: b"localhost:8888"
          },
          RequestHeader {
            name: b"User-Agent",
            value: b"curl/7.43.0"
          },
          RequestHeader {
            name: b"Accept",
            value: b"*/*"
          }
        )
      };

      assert_eq!(result, Done(&b""[..], expected))
  }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

extern mod std;
extern mod extra;

use extra::test::{TestOpts, run_tests_console, TestDesc, TestDescAndFn, DynTestFn, DynTestName};
use extra::getopts::{getopts, reqopt};
use std::{os, str};
use std::cell::Cell;
use std::os::list_dir_path;
use std::rt::io::Reader;
use std::rt::io::process::{Process, ProcessConfig, Ignored, CreatePipe};

#[deriving(Clone)]
struct Config {
    source_dir: ~str,
    filter: Option<~str>
}

fn main() {
    let args = os::args();
    let config = parse_config(args);
    let opts = test_options(config.clone());
    let tests = find_tests(config);
    if !run_tests_console(&opts, tests) {
        os::set_exit_status(1);
    }
}

fn parse_config(args: ~[~str]) -> Config {
    let args = args.tail();
    let opts = ~[reqopt("source-dir")];
    let matches = match getopts(args, opts) {
      Ok(m) => m,
      Err(f) => fail!(f.to_err_msg())
    };

    Config {
        source_dir: matches.opt_str("source-dir").unwrap(),
        filter: if matches.free.is_empty() {
            None
        } else {
            Some((*matches.free.head()).clone())
        }
    }
}

fn test_options(config: Config) -> TestOpts {
    TestOpts {
        filter: config.filter,
        run_ignored: false,
        run_tests: true,
        run_benchmarks: false,
        ratchet_metrics: None,
        ratchet_noise_percent: None,
        save_metrics: None,
        test_shard: None,
        logfile: None
    }
}

fn find_tests(config: Config) -> ~[TestDescAndFn] {
    let mut files = list_dir_path(&Path::new(config.source_dir));
    // FIXME (#1094): not the right way to transform a path
    files.retain( |file| file.display().to_str().ends_with(".html") );
    return files.map(|file| make_test(file.display().to_str()) );
}

fn make_test(file: ~str) -> TestDescAndFn {
    let f = Cell::new(file.clone());
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(file),
            ignore: false,
            should_fail: false
        },
        testfn: DynTestFn(|| { run_test(f.take()) })
    }
}

fn run_test(file: ~str) {
    let path = os::make_absolute(&Path::new(file));
    // FIXME (#1094): not the right way to transform a path
    let infile = ~"file://" + path.display().to_str();
    let create_pipe = CreatePipe(true, false); // rustc #10228

    let config = ProcessConfig {
        program: "./servo",
        args: [~"-z", infile.clone()],
        env: None,
        cwd: None,
        io: [Ignored, create_pipe, Ignored]
    };

    let mut prc = Process::new(config).unwrap();
    let stdout = prc.io[1].get_mut_ref();
    let mut output = ~[];
    loop {
        let byte = stdout.read_byte();
        match byte {
            Some(byte) => {
                print!("{}", byte as char);
                output.push(byte);
            }
            None => break
        }
    }

    let out = str::from_utf8(output);
    let lines: ~[&str] = out.split_iter('\n').collect();
    for &line in lines.iter() {
        if line.contains("TEST-UNEXPECTED-FAIL") {
            fail!(line);
        }
    }
}
<commit_msg>Fix use of display().to_str in find_tests<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

extern mod std;
extern mod extra;

use extra::test::{TestOpts, run_tests_console, TestDesc, TestDescAndFn, DynTestFn, DynTestName};
use extra::getopts::{getopts, reqopt};
use std::{os, str};
use std::cell::Cell;
use std::os::list_dir_path;
use std::rt::io::Reader;
use std::rt::io::process::{Process, ProcessConfig, Ignored, CreatePipe};

#[deriving(Clone)]
struct Config {
    source_dir: ~str,
    filter: Option<~str>
}

fn main() {
    let args = os::args();
    let config = parse_config(args);
    let opts = test_options(config.clone());
    let tests = find_tests(config);
    if !run_tests_console(&opts, tests) {
        os::set_exit_status(1);
    }
}

fn parse_config(args: ~[~str]) -> Config {
    let args = args.tail();
    let opts = ~[reqopt("source-dir")];
    let matches = match getopts(args, opts) {
      Ok(m) => m,
      Err(f) => fail!(f.to_err_msg())
    };

    Config {
        source_dir: matches.opt_str("source-dir").unwrap(),
        filter: if matches.free.is_empty() {
            None
        } else {
            Some((*matches.free.head()).clone())
        }
    }
}

fn test_options(config: Config) -> TestOpts {
    TestOpts {
        filter: config.filter,
        run_ignored: false,
        run_tests: true,
        run_benchmarks: false,
        ratchet_metrics: None,
        ratchet_noise_percent: None,
        save_metrics: None,
        test_shard: None,
        logfile: None
    }
}

fn find_tests(config: Config) -> ~[TestDescAndFn] {
    let mut files = list_dir_path(&Path::new(config.source_dir));
    files.retain(|file| file.extension_str() == Some("html") );
    return files.map(|file| make_test(file.display().to_str()) );
}

fn make_test(file: ~str) -> TestDescAndFn {
    let f = Cell::new(file.clone());
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(file),
            ignore: false,
            should_fail: false
        },
        testfn: DynTestFn(|| { run_test(f.take()) })
    }
}

fn run_test(file: ~str) {
    let path = os::make_absolute(&Path::new(file));
    // FIXME (#1094): not the right way to transform a path
    let infile = ~"file://" + path.display().to_str();
    let create_pipe = CreatePipe(true, false); // rustc #10228

    let config = ProcessConfig {
        program: "./servo",
        args: [~"-z", infile.clone()],
        env: None,
        cwd: None,
        io: [Ignored, create_pipe, Ignored]
    };

    let mut prc = Process::new(config).unwrap();
    let stdout = prc.io[1].get_mut_ref();
    let mut output = ~[];
    loop {
        let byte = stdout.read_byte();
        match byte {
            Some(byte) => {
                print!("{}", byte as char);
                output.push(byte);
            }
            None => break
        }
    }

    let out = str::from_utf8(output);
    let lines: ~[&str] = out.split_iter('\n').collect();
    for &line in lines.iter() {
        if line.contains("TEST-UNEXPECTED-FAIL") {
            fail!(line);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>:pencil: disallow thread_local in stable<commit_after><|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Common handling of keyboard input and state management for text input controls

use clipboard_provider::ClipboardProvider;
use dom::bindings::js::JSRef;
use dom::keyboardevent::{KeyboardEvent, KeyboardEventHelpers, key_value};
use msg::constellation_msg::{SHIFT, CONTROL, ALT, SUPER};
use msg::constellation_msg::{Key, KeyModifiers};
use util::str::DOMString;

use std::borrow::ToOwned;
use std::cmp::{min, max};
use std::default::Default;

#[derive(Copy, Clone, PartialEq)]
pub enum Selection {
    Selected,
    NotSelected
}

#[jstraceable]
#[derive(Copy, Clone)]
pub struct TextPoint {
    /// 0-based line number
    pub line: usize,
    /// 0-based column number
    pub index: usize,
}

/// Encapsulated state for handling keyboard input in a single or multiline text input control.
#[jstraceable]
pub struct TextInput<T: ClipboardProvider> {
    /// Current text input content, split across lines without trailing '\n'
    lines: Vec<DOMString>,
    /// Current cursor input point
    pub edit_point: TextPoint,
    /// Beginning of selection range with edit_point as end that can span multiple lines.
    selection_begin: Option<TextPoint>,
    /// Is this a multiline input?
    multiline: bool,
    clipboard_provider: T,
}

/// Resulting action to be taken by the owner of a text input that is handling an event.
pub enum KeyReaction {
    TriggerDefaultAction,
    DispatchInput,
    Nothing,
}

impl Default for TextPoint {
    fn default() -> TextPoint {
        TextPoint {
            line: 0,
            index: 0,
        }
    }
}

/// Control whether this control should allow multiple lines.
#[derive(PartialEq)]
pub enum Lines {
    Single,
    Multiple,
}

/// The direction in which to delete a character.
#[derive(PartialEq)]
pub enum DeleteDir {
    Forward,
    Backward
}

/// Was the keyboard event accompanied by the standard control modifier,
/// i.e. cmd on Mac OS or ctrl on other platforms.
#[cfg(target_os="macos")]
fn is_control_key(mods: KeyModifiers) -> bool {
    mods.contains(SUPER) && !mods.contains(CONTROL | ALT)
}

#[cfg(not(target_os="macos"))]
fn is_control_key(mods: KeyModifiers) -> bool {
    mods.contains(CONTROL) && !mods.contains(SUPER | ALT)
}

fn is_printable_key(key: Key) -> bool {
    match key {
        Key::Space | Key::Apostrophe | Key::Comma | Key::Minus |
        Key::Period | Key::Slash | Key::GraveAccent | Key::Num0 |
        Key::Num1 | Key::Num2 | Key::Num3 | Key::Num4 | Key::Num5 |
        Key::Num6 | Key::Num7 | Key::Num8 | Key::Num9 | Key::Semicolon |
        Key::Equal | Key::A | Key::B | Key::C | Key::D | Key::E | Key::F |
        Key::G | Key::H | Key::I | Key::J | Key::K | Key::L | Key::M | Key::N |
        Key::O | Key::P | Key::Q | Key::R | Key::S | Key::T | Key::U | Key::V |
        Key::W | Key::X | Key::Y | Key::Z | Key::LeftBracket | Key::Backslash |
        Key::RightBracket | Key::Kp0 | Key::Kp1 | Key::Kp2 | Key::Kp3 |
        Key::Kp4 | Key::Kp5 | Key::Kp6 | Key::Kp7 | Key::Kp8 | Key::Kp9 |
        Key::KpDecimal | Key::KpDivide | Key::KpMultiply | Key::KpSubtract |
        Key::KpAdd | Key::KpEqual => true,
        _ => false,
    }
}

impl<T: ClipboardProvider> TextInput<T> {
    /// Instantiate a new text input control
    pub fn new(lines: Lines, initial: DOMString, clipboard_provider: T) -> TextInput<T> {
        let mut i = TextInput {
            lines: vec!(),
            edit_point: Default::default(),
            selection_begin: None,
            multiline: lines == Lines::Multiple,
            clipboard_provider: clipboard_provider
        };
        i.set_content(initial);
        i
    }

    /// Remove a character at the current editing point
    pub fn delete_char(&mut self, dir: DeleteDir) {
        if self.selection_begin.is_none() {
            self.adjust_horizontal(if dir == DeleteDir::Forward {
                1
            } else {
                -1
            }, Selection::Selected);
        }
        self.replace_selection("".to_owned());
    }

    /// Insert a character at the current editing point
    pub fn insert_char(&mut self, ch: char) {
        if self.selection_begin.is_none() {
            self.selection_begin = Some(self.edit_point);
        }
        self.replace_selection(ch.to_string());
    }

    /// Insert a string at the current editing point
    fn insert_string(&mut self, s: &str) {
        // it looks like this could be made performant by avoiding some redundant
        //  selection-related checks, but use the simple implementation for now
        for ch in s.chars() {
            self.insert_char(ch);
        }
    }

    pub fn get_sorted_selection(&self) -> (TextPoint, TextPoint) {
        let begin = self.selection_begin.unwrap();
        let end = self.edit_point;

        if begin.line < end.line || (begin.line == end.line && begin.index < end.index) {
            (begin, end)
        } else {
            (end, begin)
        }
    }

    pub fn replace_selection(&mut self, insert: String) {
        let (begin, end) = self.get_sorted_selection();
        self.clear_selection();

        let new_lines = {
            let prefix = self.lines[begin.line].slice_chars(0, begin.index);
            let suffix = self.lines[end.line].slice_chars(end.index, self.lines[end.line].chars().count());
            let lines_prefix = &self.lines[..begin.line];
            let lines_suffix = &self.lines[end.line + 1..];

            let mut insert_lines = if self.multiline {
                insert.split('\n').map(|s| s.to_owned()).collect()
            } else {
                vec!(insert)
            };

            let mut new_line = prefix.to_owned();
            new_line.push_str(&insert_lines[0]);
            insert_lines[0] = new_line;

            let last_insert_lines_index = insert_lines.len() - 1;
            self.edit_point.index = insert_lines[last_insert_lines_index].chars().count();
            self.edit_point.line = begin.line + last_insert_lines_index;

            insert_lines[last_insert_lines_index].push_str(suffix);

            let mut new_lines = vec!();
            new_lines.push_all(lines_prefix);
            new_lines.push_all(&insert_lines);
            new_lines.push_all(lines_suffix);
            new_lines
        };

        self.lines = new_lines;
    }

    /// Return the length of the current line under the editing point.
    pub fn current_line_length(&self) -> usize {
        self.lines[self.edit_point.line].chars().count()
    }

    /// Adjust the editing point position by a given of lines. The resulting column is
    /// as close to the original column position as possible.
    pub fn adjust_vertical(&mut self, adjust: isize, select: Selection) {
        if !self.multiline {
            return;
        }

        if select == Selection::Selected {
            if self.selection_begin.is_none() {
                self.selection_begin = Some(self.edit_point);
            }
        } else {
            self.clear_selection();
        }

        assert!(self.edit_point.line < self.lines.len());

        let target_line: isize = self.edit_point.line as isize + adjust;

        if target_line < 0 {
            self.edit_point.index = 0;
            self.edit_point.line = 0;
            return;
        } else if target_line as usize >= self.lines.len() {
            self.edit_point.line = self.lines.len() - 1;
            self.edit_point.index = self.current_line_length();
            return;
        }

        self.edit_point.line = target_line as usize;
        self.edit_point.index = min(self.current_line_length(), self.edit_point.index);
    }

    /// Adjust the editing point position by a given number of columns. If the adjustment
    /// requested is larger than is available in the current line, the editing point is
    /// adjusted vertically and the process repeats with the remaining adjustment requested.
    pub fn adjust_horizontal(&mut self, adjust: isize, select: Selection) {
        if select == Selection::Selected {
            if self.selection_begin.is_none() {
                self.selection_begin = Some(self.edit_point);
            }
        } else {
            if self.selection_begin.is_some() {
                let (begin, end) = self.get_sorted_selection();
                self.edit_point = if adjust < 0 {begin} else {end};
                self.clear_selection();
                return
            }
        }

        if adjust < 0 {
            let remaining = self.edit_point.index;
            if adjust.abs() as usize > remaining && self.edit_point.line > 0 {
                self.adjust_vertical(-1, select);
                self.edit_point.index = self.current_line_length();
                self.adjust_horizontal(adjust + remaining as isize + 1, select);
            } else {
                self.edit_point.index = max(0, self.edit_point.index as isize + adjust) as usize;
            }
        } else {
            let remaining = self.current_line_length() - self.edit_point.index;
            if adjust as usize > remaining && self.lines.len() > self.edit_point.line + 1 {
                self.adjust_vertical(1, select);
                self.edit_point.index = 0;
                // one shift is consumed by the change of line, hence the -1
                self.adjust_horizontal(adjust - remaining as isize - 1, select);
            } else {
                self.edit_point.index = min(self.current_line_length(),
                                            self.edit_point.index + adjust as usize);
            }
        }
    }

    /// Deal with a newline input.
    pub fn handle_return(&mut self) -> KeyReaction {
        if !self.multiline {
            return KeyReaction::TriggerDefaultAction;
        }
        self.insert_char('\n');
        return KeyReaction::DispatchInput;
    }

    /// Select all text in the input control.
    pub fn select_all(&mut self) {
        self.selection_begin = Some(TextPoint {
            line: 0,
            index: 0,
        });
        let last_line = self.lines.len() - 1;
        self.edit_point.line = last_line;
        self.edit_point.index = self.lines[last_line].chars().count();
    }

    /// Remove the current selection.
    pub fn clear_selection(&mut self) {
        self.selection_begin = None;
    }

    /// Process a given `KeyboardEvent` and return an action for the caller to execute.
    pub fn handle_keydown(&mut self, event: JSRef<KeyboardEvent>) -> KeyReaction {
        if let Some(key) = event.get_key() {
            self.handle_keydown_aux(key, event.get_key_modifiers())
        } else {
            KeyReaction::Nothing
        }
    }
    pub fn handle_keydown_aux(&mut self, key: Key, mods: KeyModifiers) -> KeyReaction {
        let maybe_select = if mods.contains(SHIFT) { Selection::Selected } else { Selection::NotSelected };
        match key {
           Key::A if is_control_key(mods) => {
                self.select_all();
                KeyReaction::Nothing
            },
           Key::V if is_control_key(mods) => {
                let contents = self.clipboard_provider.clipboard_contents();
                self.insert_string(&contents);
                KeyReaction::DispatchInput
            },
            _ if is_printable_key(key) => {
                self.insert_string(key_value(key, mods));
                KeyReaction::DispatchInput
            }
            Key::Space => {
                self.insert_char(' ');
                KeyReaction::DispatchInput
            }
            Key::Delete => {
                self.delete_char(DeleteDir::Forward);
                KeyReaction::DispatchInput
            }
            Key::Backspace => {
                self.delete_char(DeleteDir::Backward);
                KeyReaction::DispatchInput
            }
            Key::Left => {
                self.adjust_horizontal(-1, maybe_select);
                KeyReaction::Nothing
            }
            Key::Right => {
                self.adjust_horizontal(1, maybe_select);
                KeyReaction::Nothing
            }
            Key::Up => {
                self.adjust_vertical(-1, maybe_select);
                KeyReaction::Nothing
            }
            Key::Down => {
                self.adjust_vertical(1, maybe_select);
                KeyReaction::Nothing
            }
            Key::Enter | Key::KpEnter => self.handle_return(),
            Key::Home => {
                self.edit_point.index = 0;
                KeyReaction::Nothing
            }
            Key::End => {
                self.edit_point.index = self.current_line_length();
                KeyReaction::Nothing
            }
            Key::PageUp => {
                self.adjust_vertical(-28, maybe_select);
                KeyReaction::Nothing
            }
            Key::PageDown => {
                self.adjust_vertical(28, maybe_select);
                KeyReaction::Nothing
            }
            Key::Tab => KeyReaction::TriggerDefaultAction,
            _ => KeyReaction::Nothing,
        }
    }

    /// Get the current contents of the text input. Multiple lines are joined by \n.
    pub fn get_content(&self) -> DOMString {
        let mut content = "".to_owned();
        for (i, line) in self.lines.iter().enumerate() {
            content.push_str(&line);
            if i < self.lines.len() - 1 {
                content.push('\n');
            }
        }
        content
    }

    /// Set the current contents of the text input. If this is control supports multiple lines,
    /// any \n encountered will be stripped and force a new logical line.
    pub fn set_content(&mut self, content: DOMString) {
        self.lines = if self.multiline {
            content.split('\n').map(|s| s.to_owned()).collect()
        } else {
            vec!(content)
        };
        self.edit_point.line = min(self.edit_point.line, self.lines.len() - 1);
        self.edit_point.index = min(self.edit_point.index, self.current_line_length());
    }
}
<commit_msg>Remove some unnecessary allocations in text input handling.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Common handling of keyboard input and state management for text input controls

use clipboard_provider::ClipboardProvider;
use dom::bindings::js::JSRef;
use dom::keyboardevent::{KeyboardEvent, KeyboardEventHelpers, key_value};
use msg::constellation_msg::{SHIFT, CONTROL, ALT, SUPER};
use msg::constellation_msg::{Key, KeyModifiers};
use util::str::DOMString;

use std::borrow::ToOwned;
use std::cmp::{min, max};
use std::default::Default;

#[derive(Copy, Clone, PartialEq)]
pub enum Selection {
    Selected,
    NotSelected
}

#[jstraceable]
#[derive(Copy, Clone)]
pub struct TextPoint {
    /// 0-based line number
    pub line: usize,
    /// 0-based column number
    pub index: usize,
}

/// Encapsulated state for handling keyboard input in a single or multiline text input control.
#[jstraceable]
pub struct TextInput<T: ClipboardProvider> {
    /// Current text input content, split across lines without trailing '\n'
    lines: Vec<DOMString>,
    /// Current cursor input point
    pub edit_point: TextPoint,
    /// Beginning of selection range with edit_point as end that can span multiple lines.
    selection_begin: Option<TextPoint>,
    /// Is this a multiline input?
    multiline: bool,
    clipboard_provider: T,
}

/// Resulting action to be taken by the owner of a text input that is handling an event.
pub enum KeyReaction {
    TriggerDefaultAction,
    DispatchInput,
    Nothing,
}

impl Default for TextPoint {
    fn default() -> TextPoint {
        TextPoint {
            line: 0,
            index: 0,
        }
    }
}

/// Control whether this control should allow multiple lines.
#[derive(PartialEq)]
pub enum Lines {
    Single,
    Multiple,
}

/// The direction in which to delete a character.
#[derive(PartialEq)]
pub enum DeleteDir {
    Forward,
    Backward
}

/// Was the keyboard event accompanied by the standard control modifier,
/// i.e. cmd on Mac OS or ctrl on other platforms.
#[cfg(target_os="macos")]
fn is_control_key(mods: KeyModifiers) -> bool {
    mods.contains(SUPER) && !mods.contains(CONTROL | ALT)
}

#[cfg(not(target_os="macos"))]
fn is_control_key(mods: KeyModifiers) -> bool {
    mods.contains(CONTROL) && !mods.contains(SUPER | ALT)
}

fn is_printable_key(key: Key) -> bool {
    match key {
        Key::Space | Key::Apostrophe | Key::Comma | Key::Minus |
        Key::Period | Key::Slash | Key::GraveAccent | Key::Num0 |
        Key::Num1 | Key::Num2 | Key::Num3 | Key::Num4 | Key::Num5 |
        Key::Num6 | Key::Num7 | Key::Num8 | Key::Num9 | Key::Semicolon |
        Key::Equal | Key::A | Key::B | Key::C | Key::D | Key::E | Key::F |
        Key::G | Key::H | Key::I | Key::J | Key::K | Key::L | Key::M | Key::N |
        Key::O | Key::P | Key::Q | Key::R | Key::S | Key::T | Key::U | Key::V |
        Key::W | Key::X | Key::Y | Key::Z | Key::LeftBracket | Key::Backslash |
        Key::RightBracket | Key::Kp0 | Key::Kp1 | Key::Kp2 | Key::Kp3 |
        Key::Kp4 | Key::Kp5 | Key::Kp6 | Key::Kp7 | Key::Kp8 | Key::Kp9 |
        Key::KpDecimal | Key::KpDivide | Key::KpMultiply | Key::KpSubtract |
        Key::KpAdd | Key::KpEqual => true,
        _ => false,
    }
}

impl<T: ClipboardProvider> TextInput<T> {
    /// Instantiate a new text input control
    pub fn new(lines: Lines, initial: DOMString, clipboard_provider: T) -> TextInput<T> {
        let mut i = TextInput {
            lines: vec!(),
            edit_point: Default::default(),
            selection_begin: None,
            multiline: lines == Lines::Multiple,
            clipboard_provider: clipboard_provider
        };
        i.set_content(initial);
        i
    }

    /// Remove a character at the current editing point
    pub fn delete_char(&mut self, dir: DeleteDir) {
        if self.selection_begin.is_none() {
            self.adjust_horizontal(if dir == DeleteDir::Forward {
                1
            } else {
                -1
            }, Selection::Selected);
        }
        self.replace_selection("".to_owned());
    }

    /// Insert a character at the current editing point
    pub fn insert_char(&mut self, ch: char) {
        self.insert_string(ch.to_string());
    }

    /// Insert a string at the current editing point
    fn insert_string<S: Into<String>>(&mut self, s: S) {
        if self.selection_begin.is_none() {
            self.selection_begin = Some(self.edit_point);
        }
        self.replace_selection(s.into());
    }

    pub fn get_sorted_selection(&self) -> (TextPoint, TextPoint) {
        let begin = self.selection_begin.unwrap();
        let end = self.edit_point;

        if begin.line < end.line || (begin.line == end.line && begin.index < end.index) {
            (begin, end)
        } else {
            (end, begin)
        }
    }

    pub fn replace_selection(&mut self, insert: String) {
        let (begin, end) = self.get_sorted_selection();
        self.clear_selection();

        let new_lines = {
            let prefix = self.lines[begin.line].slice_chars(0, begin.index);
            let suffix = self.lines[end.line].slice_chars(end.index, self.lines[end.line].chars().count());
            let lines_prefix = &self.lines[..begin.line];
            let lines_suffix = &self.lines[end.line + 1..];

            let mut insert_lines = if self.multiline {
                insert.split('\n').map(|s| s.to_owned()).collect()
            } else {
                vec!(insert)
            };

            let mut new_line = prefix.to_owned();
            new_line.push_str(&insert_lines[0]);
            insert_lines[0] = new_line;

            let last_insert_lines_index = insert_lines.len() - 1;
            self.edit_point.index = insert_lines[last_insert_lines_index].chars().count();
            self.edit_point.line = begin.line + last_insert_lines_index;

            insert_lines[last_insert_lines_index].push_str(suffix);

            let mut new_lines = vec!();
            new_lines.push_all(lines_prefix);
            new_lines.push_all(&insert_lines);
            new_lines.push_all(lines_suffix);
            new_lines
        };

        self.lines = new_lines;
    }

    /// Return the length of the current line under the editing point.
    pub fn current_line_length(&self) -> usize {
        self.lines[self.edit_point.line].chars().count()
    }

    /// Adjust the editing point position by a given of lines. The resulting column is
    /// as close to the original column position as possible.
    pub fn adjust_vertical(&mut self, adjust: isize, select: Selection) {
        if !self.multiline {
            return;
        }

        if select == Selection::Selected {
            if self.selection_begin.is_none() {
                self.selection_begin = Some(self.edit_point);
            }
        } else {
            self.clear_selection();
        }

        assert!(self.edit_point.line < self.lines.len());

        let target_line: isize = self.edit_point.line as isize + adjust;

        if target_line < 0 {
            self.edit_point.index = 0;
            self.edit_point.line = 0;
            return;
        } else if target_line as usize >= self.lines.len() {
            self.edit_point.line = self.lines.len() - 1;
            self.edit_point.index = self.current_line_length();
            return;
        }

        self.edit_point.line = target_line as usize;
        self.edit_point.index = min(self.current_line_length(), self.edit_point.index);
    }

    /// Adjust the editing point position by a given number of columns. If the adjustment
    /// requested is larger than is available in the current line, the editing point is
    /// adjusted vertically and the process repeats with the remaining adjustment requested.
    pub fn adjust_horizontal(&mut self, adjust: isize, select: Selection) {
        if select == Selection::Selected {
            if self.selection_begin.is_none() {
                self.selection_begin = Some(self.edit_point);
            }
        } else {
            if self.selection_begin.is_some() {
                let (begin, end) = self.get_sorted_selection();
                self.edit_point = if adjust < 0 {begin} else {end};
                self.clear_selection();
                return
            }
        }

        if adjust < 0 {
            let remaining = self.edit_point.index;
            if adjust.abs() as usize > remaining && self.edit_point.line > 0 {
                self.adjust_vertical(-1, select);
                self.edit_point.index = self.current_line_length();
                self.adjust_horizontal(adjust + remaining as isize + 1, select);
            } else {
                self.edit_point.index = max(0, self.edit_point.index as isize + adjust) as usize;
            }
        } else {
            let remaining = self.current_line_length() - self.edit_point.index;
            if adjust as usize > remaining && self.lines.len() > self.edit_point.line + 1 {
                self.adjust_vertical(1, select);
                self.edit_point.index = 0;
                // one shift is consumed by the change of line, hence the -1
                self.adjust_horizontal(adjust - remaining as isize - 1, select);
            } else {
                self.edit_point.index = min(self.current_line_length(),
                                            self.edit_point.index + adjust as usize);
            }
        }
    }

    /// Deal with a newline input.
    pub fn handle_return(&mut self) -> KeyReaction {
        if !self.multiline {
            return KeyReaction::TriggerDefaultAction;
        }
        self.insert_char('\n');
        return KeyReaction::DispatchInput;
    }

    /// Select all text in the input control.
    pub fn select_all(&mut self) {
        self.selection_begin = Some(TextPoint {
            line: 0,
            index: 0,
        });
        let last_line = self.lines.len() - 1;
        self.edit_point.line = last_line;
        self.edit_point.index = self.lines[last_line].chars().count();
    }

    /// Remove the current selection.
    pub fn clear_selection(&mut self) {
        self.selection_begin = None;
    }

    /// Process a given `KeyboardEvent` and return an action for the caller to execute.
    pub fn handle_keydown(&mut self, event: JSRef<KeyboardEvent>) -> KeyReaction {
        if let Some(key) = event.get_key() {
            self.handle_keydown_aux(key, event.get_key_modifiers())
        } else {
            KeyReaction::Nothing
        }
    }
    pub fn handle_keydown_aux(&mut self, key: Key, mods: KeyModifiers) -> KeyReaction {
        let maybe_select = if mods.contains(SHIFT) { Selection::Selected } else { Selection::NotSelected };
        match key {
           Key::A if is_control_key(mods) => {
                self.select_all();
                KeyReaction::Nothing
            },
           Key::V if is_control_key(mods) => {
                let contents = self.clipboard_provider.clipboard_contents();
                self.insert_string(contents);
                KeyReaction::DispatchInput
            },
            _ if is_printable_key(key) => {
                self.insert_string(key_value(key, mods));
                KeyReaction::DispatchInput
            }
            Key::Space => {
                self.insert_char(' ');
                KeyReaction::DispatchInput
            }
            Key::Delete => {
                self.delete_char(DeleteDir::Forward);
                KeyReaction::DispatchInput
            }
            Key::Backspace => {
                self.delete_char(DeleteDir::Backward);
                KeyReaction::DispatchInput
            }
            Key::Left => {
                self.adjust_horizontal(-1, maybe_select);
                KeyReaction::Nothing
            }
            Key::Right => {
                self.adjust_horizontal(1, maybe_select);
                KeyReaction::Nothing
            }
            Key::Up => {
                self.adjust_vertical(-1, maybe_select);
                KeyReaction::Nothing
            }
            Key::Down => {
                self.adjust_vertical(1, maybe_select);
                KeyReaction::Nothing
            }
            Key::Enter | Key::KpEnter => self.handle_return(),
            Key::Home => {
                self.edit_point.index = 0;
                KeyReaction::Nothing
            }
            Key::End => {
                self.edit_point.index = self.current_line_length();
                KeyReaction::Nothing
            }
            Key::PageUp => {
                self.adjust_vertical(-28, maybe_select);
                KeyReaction::Nothing
            }
            Key::PageDown => {
                self.adjust_vertical(28, maybe_select);
                KeyReaction::Nothing
            }
            Key::Tab => KeyReaction::TriggerDefaultAction,
            _ => KeyReaction::Nothing,
        }
    }

    /// Get the current contents of the text input. Multiple lines are joined by \n.
    pub fn get_content(&self) -> DOMString {
        let mut content = "".to_owned();
        for (i, line) in self.lines.iter().enumerate() {
            content.push_str(&line);
            if i < self.lines.len() - 1 {
                content.push('\n');
            }
        }
        content
    }

    /// Set the current contents of the text input. If this is control supports multiple lines,
    /// any \n encountered will be stripped and force a new logical line.
    pub fn set_content(&mut self, content: DOMString) {
        self.lines = if self.multiline {
            content.split('\n').map(|s| s.to_owned()).collect()
        } else {
            vec!(content)
        };
        self.edit_point.line = min(self.edit_point.line, self.lines.len() - 1);
        self.edit_point.index = min(self.edit_point.index, self.current_line_length());
    }
}
<|endoftext|>