<commit_before><commit_msg>Add build.rs<commit_after>#[cfg(target_os="linux")]
fn main(){
    println!("cargo:rustc-link-lib=dl");
}

#[cfg(any(target_os="freebsd",
          target_os="dragonfly"))]
fn main(){
    println!("cargo:rustc-link-lib=c");
}

#[cfg(any(target_os="openbsd",
          target_os="bitrig",
          target_os="netbsd",
          target_os="macos"))]
fn main(){
    // netbsd claims dl* will be available to any dynamically linked binary, but I haven’t found
    // any libraries that have to be linked to on other platforms.
}

#[cfg(target_os="windows")]
fn main(){}
<|endoftext|>


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


<commit_before>// High-level bindings to Cairo.

import cairo::{CAIRO_STATUS_SUCCESS, cairo_format_t, cairo_status_t, cairo_surface_t, cairo_t};
import cairo::bindgen::{cairo_create, cairo_fill, cairo_image_surface_create};
import cairo::bindgen::{cairo_image_surface_get_data, cairo_image_surface_get_format};
import cairo::bindgen::{cairo_image_surface_get_height, cairo_image_surface_get_stride};
import cairo::bindgen::{cairo_image_surface_get_width, cairo_rectangle, cairo_set_line_width};
import cairo::bindgen::{cairo_set_source_rgb, cairo_stroke, cairo_surface_destroy};
import cairo::bindgen::{cairo_surface_reference, cairo_surface_write_to_png_stream};
import io::{MemBuffer, Writer};
import ptr::addr_of;
import result::{err, ok, result};
import unsafe::reinterpret_cast;
import vec::unsafe::{form_slice, from_buf};

// FIXME: We should have a hierarchy of surfaces, but this needs to wait on case classes.
struct ImageSurface {
    let cairo_surface: *cairo_surface_t;

    fn width()  -> c_int    { cairo_image_surface_get_width(self.cairo_surface)  }
    fn height() -> c_int    { cairo_image_surface_get_height(self.cairo_surface) }
    fn stride() -> c_int    { cairo_image_surface_get_stride(self.cairo_surface) }
    fn format() -> c_int    { cairo_image_surface_get_format(self.cairo_surface) }

    // FIXME: This should not copy!
    pure fn data() -> ~[u8] unsafe {
        let buffer = cairo_image_surface_get_data(self.cairo_surface);
        return from_buf(buffer, (self.stride() * self.height()) as uint);
    }

    drop {
        cairo_surface_destroy(self.cairo_surface);
    }
}

// Should be private.
fn image_surface_from_cairo_surface(cairo_surface: *cairo_surface_t) -> ImageSurface {
    assert !cairo_surface.is_null();
    ImageSurface { cairo_surface: cairo_surface }
}

fn ImageSurface(format: cairo_format_t, width: c_int, height: c_int) -> ImageSurface {
    let cairo_surface = cairo_image_surface_create(format, width, height);
    if cairo_surface.is_null() {
        fail ~"couldn't create Cairo image surface";
    }
    return image_surface_from_cairo_surface(move cairo_surface);
}

impl ImageSurface {
    fn write_to_png_stream(buffer: &io::MemBuffer) -> result<(),cairo_status_t> unsafe {
        extern fn write_fn(closure: *c_void, data: *c_uchar, len: c_uint)
                        -> cairo_status_t unsafe {
            let writer: *MemBuffer = reinterpret_cast(closure);
            do form_slice(data, len as uint) |bytes| {
                (*writer).write(bytes);
            }
            return CAIRO_STATUS_SUCCESS;
        }

        let buffer_ptr = reinterpret_cast(buffer);
        let status = cairo_surface_write_to_png_stream(self.cairo_surface, write_fn, buffer_ptr);
        if status != CAIRO_STATUS_SUCCESS {
            return err(status);
        }

        return ok(());
    }

    fn clone() -> ImageSurface {
        cairo_surface_reference(self.cairo_surface);
        return image_surface_from_cairo_surface(self.cairo_surface);
    }
}

struct Context {
    let cairo_context: *cairo_t;

    new(&&surface: ImageSurface) {
        self.cairo_context = cairo_create(surface.cairo_surface);
    }

    fn set_line_width(width: c_double) {
        cairo_set_line_width(self.cairo_context, width);
    }

    fn set_source_rgb(r: c_double, g: c_double, b: c_double) {
        cairo_set_source_rgb(self.cairo_context, r, g, b);
    }

    fn rectangle(x: c_double, y: c_double, width: c_double, height: c_double) {
        cairo_rectangle(self.cairo_context, x, y, width, height);
    }

    fn stroke() {
        cairo_stroke(self.cairo_context);
    }

    fn fill() {
        cairo_fill(self.cairo_context);
    }
}

<commit_msg>Update for language changes<commit_after>// High-level bindings to Cairo.

import cairo::{CAIRO_STATUS_SUCCESS, cairo_format_t, cairo_status_t, cairo_surface_t, cairo_t};
import cairo::bindgen::{cairo_create, cairo_fill, cairo_image_surface_create};
import cairo::bindgen::{cairo_image_surface_get_data, cairo_image_surface_get_format};
import cairo::bindgen::{cairo_image_surface_get_height, cairo_image_surface_get_stride};
import cairo::bindgen::{cairo_image_surface_get_width, cairo_rectangle, cairo_set_line_width};
import cairo::bindgen::{cairo_set_source_rgb, cairo_stroke, cairo_surface_destroy};
import cairo::bindgen::{cairo_surface_reference, cairo_surface_write_to_png_stream};
import io::{MemBuffer, Writer};
import ptr::addr_of;
import result::{Err, Ok, Result};
import unsafe::reinterpret_cast;
import vec::unsafe::{form_slice, from_buf};

// FIXME: We should have a hierarchy of surfaces, but this needs to wait on case classes.
struct ImageSurface {
    let cairo_surface: *cairo_surface_t;

    fn width()  -> c_int    { cairo_image_surface_get_width(self.cairo_surface)  }
    fn height() -> c_int    { cairo_image_surface_get_height(self.cairo_surface) }
    fn stride() -> c_int    { cairo_image_surface_get_stride(self.cairo_surface) }
    fn format() -> c_int    { cairo_image_surface_get_format(self.cairo_surface) }

    // FIXME: This should not copy!
    pure fn data() -> ~[u8] unsafe {
        let buffer = cairo_image_surface_get_data(self.cairo_surface);
        return from_buf(buffer, (self.stride() * self.height()) as uint);
    }

    drop {
        cairo_surface_destroy(self.cairo_surface);
    }
}

// Should be private.
fn image_surface_from_cairo_surface(cairo_surface: *cairo_surface_t) -> ImageSurface {
    assert !cairo_surface.is_null();
    ImageSurface { cairo_surface: cairo_surface }
}

fn ImageSurface(format: cairo_format_t, width: c_int, height: c_int) -> ImageSurface {
    let cairo_surface = cairo_image_surface_create(format, width, height);
    if cairo_surface.is_null() {
        fail ~"couldn't create Cairo image surface";
    }
    return image_surface_from_cairo_surface(move cairo_surface);
}

impl ImageSurface {
    fn write_to_png_stream(buffer: &io::MemBuffer) -> Result<(),cairo_status_t> unsafe {
        extern fn write_fn(closure: *c_void, data: *c_uchar, len: c_uint)
                        -> cairo_status_t unsafe {
            let writer: *MemBuffer = reinterpret_cast(closure);
            do form_slice(data, len as uint) |bytes| {
                (*writer).write(bytes);
            }
            return CAIRO_STATUS_SUCCESS;
        }

        let buffer_ptr = reinterpret_cast(buffer);
        let status = cairo_surface_write_to_png_stream(self.cairo_surface, write_fn, buffer_ptr);
        if status != CAIRO_STATUS_SUCCESS {
            return Err(status);
        }

        return Ok(());
    }

    fn clone() -> ImageSurface {
        cairo_surface_reference(self.cairo_surface);
        return image_surface_from_cairo_surface(self.cairo_surface);
    }
}

struct Context {
    let cairo_context: *cairo_t;

    new(&&surface: ImageSurface) {
        self.cairo_context = cairo_create(surface.cairo_surface);
    }

    fn set_line_width(width: c_double) {
        cairo_set_line_width(self.cairo_context, width);
    }

    fn set_source_rgb(r: c_double, g: c_double, b: c_double) {
        cairo_set_source_rgb(self.cairo_context, r, g, b);
    }

    fn rectangle(x: c_double, y: c_double, width: c_double, height: c_double) {
        cairo_rectangle(self.cairo_context, x, y, width, height);
    }

    fn stroke() {
        cairo_stroke(self.cairo_context);
    }

    fn fill() {
        cairo_fill(self.cairo_context);
    }
}

<|endoftext|>


<commit_before><commit_msg>Added merge_segments benchmark<commit_after>#![feature(test)]

#[macro_use]
extern crate maplit;
extern crate test;
extern crate kite;
extern crate kite_rocksdb;

use test::Bencher;
use std::fs::remove_dir_all;

use kite::term::Term;
use kite::token::Token;
use kite::schema::{FieldType, FIELD_INDEXED, FIELD_STORED};
use kite::document::{Document, FieldValue};

use kite_rocksdb::RocksDBIndexStore;

#[bench]
fn bench_merge_segments(b: &mut Bencher) {
    remove_dir_all("test_indices/bench_merge_segments");

    let mut store = RocksDBIndexStore::create("test_indices/bench_merge_segments").unwrap();
    store.add_field("title".to_string(), FieldType::Text, FIELD_INDEXED).unwrap();
    store.add_field("body".to_string(), FieldType::Text, FIELD_INDEXED).unwrap();
    store.add_field("id".to_string(), FieldType::I64, FIELD_STORED).unwrap();

    let mut tokens = Vec::new();
    for t in 0..500 {
        tokens.push(Token {
            term: Term::String(t.to_string()),
            position: t
        });
    }

    // Make 1000 single-document segments
    for i in 0..1000 {
        store.insert_or_update_document(Document {
            key: i.to_string(),
            indexed_fields: hashmap! {
                "body".to_string() => tokens.clone(),
                "title".to_string() => vec![Token { term: Term::String(i.to_string()), position: 1}],
            },
            stored_fields: hashmap! {
                "id".to_string() => FieldValue::Integer(i),
            },
        });
    }

    // Merge them together in groups of 100
    // This is only run about 5 times so only half of the documents will be merged
    let mut i = 0;
    b.iter(|| {
        let start = i * 100;
        let stop = start + 100;
        let segments = (start..stop).collect::<Vec<u32>>();

        store.merge_segments(&segments);
        store.purge_segments(&segments);

        i += 1;
    });
}
<|endoftext|>


<commit_before>#![feature(default_type_params)]
extern crate curl;
extern crate hyper;

extern crate test;

use std::fmt::{self, Show};
use std::str::from_str;
use std::io::{IoResult, MemReader};
use std::io::net::ip::SocketAddr;
use std::os;
use std::path::BytesContainer;

use hyper::net;

static README: &'static [u8] = include_bin!("../README.md");

struct MockStream {
    read: MemReader,
}

impl Clone for MockStream {
    fn clone(&self) -> MockStream {
        MockStream::new()
    }
}

impl MockStream {
    fn new() -> MockStream {
        let head = b"HTTP/1.1 200 OK\r\nServer: Mock\r\n\r\n";
        let mut res = head.to_vec();
        res.push_all(README);
        MockStream {
            read: MemReader::new(res),
        }
    }
}

impl Reader for MockStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.read.read(buf)
    }
}

impl Writer for MockStream {
    fn write(&mut self, _msg: &[u8]) -> IoResult<()> {
        // we're mocking, what do we care.
        Ok(())
    }
}

#[bench]
fn bench_mock_curl(b: &mut test::Bencher) {
    let mut cwd = os::getcwd().unwrap();
    cwd.push("README.md");
    let s = format!("file://{}", cwd.container_as_str().unwrap());
    let url = s.as_slice();
    b.iter(|| {
        curl::http::handle()
            .get(url)
            .header("X-Foo", "Bar")
            .exec()
            .unwrap()
    });
}

#[derive(Clone)]
struct Foo;

impl hyper::header::Header for Foo {
    fn header_name(_: Option<Foo>) -> &'static str {
        "x-foo"
    }
    fn parse_header(_: &[Vec<u8>]) -> Option<Foo> {
        None
    }
}

impl hyper::header::HeaderFormat for Foo {
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        "Bar".fmt(fmt)
    }
}

impl net::NetworkStream for MockStream {
    fn peer_name(&mut self) -> IoResult<SocketAddr> {
        Ok(from_str("127.0.0.1:1337").unwrap())
    }
}

struct MockConnector;

impl net::NetworkConnector<MockStream> for MockConnector {
    fn connect(&mut self, _: &str, _: u16, _: &str) -> IoResult<MockStream> {
        Ok(MockStream::new())
    }

}

#[bench]
fn bench_mock_hyper(b: &mut test::Bencher) {
    let url = "http://127.0.0.1:1337/";
    b.iter(|| {
        let mut req = hyper::client::Request::with_connector(
            hyper::Get, hyper::Url::parse(url).unwrap(), &mut MockConnector
        ).unwrap();
        req.headers_mut().set(Foo);

        req
            .start().unwrap()
            .send().unwrap()
            .read_to_string().unwrap()
    });
}

<commit_msg>Fix the benches for latest rust changes.<commit_after>#![feature(default_type_params)]
extern crate curl;
extern crate hyper;

extern crate test;

use std::fmt::{self, Show};
use std::io::{IoResult, MemReader};
use std::io::net::ip::SocketAddr;
use std::os;
use std::path::BytesContainer;

use hyper::net;

static README: &'static [u8] = include_bin!("../README.md");

struct MockStream {
    read: MemReader,
}

impl Clone for MockStream {
    fn clone(&self) -> MockStream {
        MockStream::new()
    }
}

impl MockStream {
    fn new() -> MockStream {
        let head = b"HTTP/1.1 200 OK\r\nServer: Mock\r\n\r\n";
        let mut res = head.to_vec();
        res.push_all(README);
        MockStream {
            read: MemReader::new(res),
        }
    }
}

impl Reader for MockStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.read.read(buf)
    }
}

impl Writer for MockStream {
    fn write(&mut self, _msg: &[u8]) -> IoResult<()> {
        // we're mocking, what do we care.
        Ok(())
    }
}

#[bench]
fn bench_mock_curl(b: &mut test::Bencher) {
    let mut cwd = os::getcwd().unwrap();
    cwd.push("README.md");
    let s = format!("file://{}", cwd.container_as_str().unwrap());
    let url = s.as_slice();
    b.iter(|| {
        curl::http::handle()
            .get(url)
            .header("X-Foo", "Bar")
            .exec()
            .unwrap()
    });
}

#[derive(Clone)]
struct Foo;

impl hyper::header::Header for Foo {
    fn header_name(_: Option<Foo>) -> &'static str {
        "x-foo"
    }
    fn parse_header(_: &[Vec<u8>]) -> Option<Foo> {
        None
    }
}

impl hyper::header::HeaderFormat for Foo {
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        "Bar".fmt(fmt)
    }
}

impl net::NetworkStream for MockStream {
    fn peer_name(&mut self) -> IoResult<SocketAddr> {
        Ok("127.0.0.1:1337".parse().unwrap())
    }
}

struct MockConnector;

impl net::NetworkConnector<MockStream> for MockConnector {
    fn connect(&mut self, _: &str, _: u16, _: &str) -> IoResult<MockStream> {
        Ok(MockStream::new())
    }

}

#[bench]
fn bench_mock_hyper(b: &mut test::Bencher) {
    let url = "http://127.0.0.1:1337/";
    b.iter(|| {
        let mut req = hyper::client::Request::with_connector(
            hyper::Get, hyper::Url::parse(url).unwrap(), &mut MockConnector
        ).unwrap();
        req.headers_mut().set(Foo);

        req
            .start().unwrap()
            .send().unwrap()
            .read_to_string().unwrap()
    });
}

<|endoftext|>


<commit_before>#![feature(alloc)]
#![feature(asm)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core_simd)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(convert)]
#![feature(fnbox)]
#![feature(fundamental)]
#![feature(lang_items)]
#![feature(no_std)]
#![feature(rc_unique)]
#![feature(unboxed_closures)]
#![feature(unsafe_no_drop_flag)]
#![feature(vec_from_raw_buf)]
#![feature(vec_push_all)]
#![no_std]

extern crate alloc;

extern crate collections;

#[macro_use]
extern crate mopa;

use core::fmt;
use core::mem::size_of;

use alloc::rc::*;

use common::debug::*;
use common::pio::*;
use common::memory::*;
use common::string::*;
use common::url::*;

use drivers::keyboard::*;
use drivers::mouse::*;
use drivers::pci::*;
use drivers::ps2::*;
use drivers::serial::*;

use graphics::bmp::*;

use programs::filemanager::*;
use programs::session::*;

use schemes::file::*;
use schemes::http::*;
use schemes::memory::*;
use schemes::pci::*;
use schemes::random::*;

mod common {
    pub mod debug;
    pub mod elf;
    pub mod memory;
    pub mod pci;
    pub mod pio;
    pub mod random;
    pub mod string;
    pub mod url;
}

mod drivers {
    pub mod disk;
    pub mod keyboard;
    pub mod mouse;
    pub mod pci;
    pub mod ps2;
    pub mod serial;
}

mod filesystems {
    pub mod unfs;
}

mod graphics {
    pub mod bmp;
    pub mod color;
    pub mod display;
    pub mod point;
    pub mod size;
    pub mod window;
}

mod network {
    pub mod arp;
    pub mod common;
    pub mod ethernet;
    pub mod icmp;
    pub mod intel8254x;
    pub mod ipv4;
    pub mod rtl8139;
    pub mod tcp;
    pub mod udp;
}

mod programs {
    pub mod editor;
    pub mod executor;
    pub mod filemanager;
    pub mod session;
    pub mod viewer;
}

mod schemes {
    pub mod file;
    pub mod http;
    pub mod ide;
    pub mod memory;
    pub mod pci;
    pub mod random;
}

mod usb {
    pub mod xhci;
}

static mut session_ptr: *mut Session = 0 as *mut Session;

unsafe fn init(){
    serial_init();

    dd(size_of::<usize>() * 8);
    d(" bits");
    dl();

    page_init();
    cluster_init();

    session_ptr = alloc(size_of::<Session>()) as *mut Session;
    *session_ptr = Session::new();
    let session = &mut *session_ptr;

    session.items.insert(0, Rc::new(FileManager::new()));

    keyboard_init();
    mouse_init();

    session.modules.push(Rc::new(PS2));
    session.modules.push(Rc::new(Serial::new(0x3F8, 0x4)));

    pci_init(session);

    session.modules.push(Rc::new(FileScheme));
    session.modules.push(Rc::new(HTTPScheme));
    session.modules.push(Rc::new(MemoryScheme));
    session.modules.push(Rc::new(PCIScheme));
    session.modules.push(Rc::new(RandomScheme));

    session.on_url_wrapped(&URL::from_string("file:///background.bmp".to_string()), box |response: String|{
        if response.data as usize > 0 {
            (*session_ptr).display.background = BMP::from_data(response.data as usize);
        }
    });
}

#[no_mangle]
pub unsafe fn kernel(interrupt: u32) {
    match interrupt {
        0x20 => (), //timer
        0x21 => (*session_ptr).on_irq(0x1), //keyboard
        0x23 => (*session_ptr).on_irq(0x3), // serial 2 and 4
        0x24 => (*session_ptr).on_irq(0x4), // serial 1 and 3
        0x29 => (*session_ptr).on_irq(0x9), //pci
        0x2A => (*session_ptr).on_irq(0xA), //pci
        0x2B => (*session_ptr).on_irq(0xB), //pci
        0x2C => (*session_ptr).on_irq(0xC), //mouse
        0x2E => (*session_ptr).on_irq(0xE), //disk
        0x2F => (*session_ptr).on_irq(0xF), //disk
        0xFF => { // main loop
            init();

            loop {
                (*session_ptr).on_poll();
                (*session_ptr).redraw();
                asm!("sti");
                asm!("hlt");
                asm!("cli"); // TODO: Allow preempting
            }
        },
        0x0 => {
            d("Divide by zero exception\n");
        },
        0x1 => {
            d("Debug exception\n");
        },
        0x2 => {
            d("Non-maskable interrupt\n");
        },
        0x3 => {
            d("Breakpoint exception\n");
        },
        0x4 => {
            d("Overflow exception\n");
        },
        0x5 => {
            d("Bound range exceeded exception\n");
        },
        0x6 => {
            d("Invalid opcode exception\n");
        },
        0x7 => {
            d("Device not available exception\n");
        },
        0x8 => {
            d("Double fault\n");
        },
        0xA => {
            d("Invalid TSS exception\n");
        },
        0xB => {
            d("Segment not present exception\n");
        },
        0xC => {
            d("Stack-segment fault\n");
        },
        0xD => {
            d("General protection fault\n");
        },
        0xE => {
            d("Page fault\n");
        },
        0x10 => {
            d("x87 floating-point exception\n");
        },
        0x11 => {
            d("Alignment check exception\n");
        },
        0x12 => {
            d("Machine check exception\n");
        },
        0x13 => {
            d("SIMD floating-point exception\n");
        },
        0x14 => {
            d("Virtualization exception\n");
        },
        0x1E => {
            d("Security exception\n");
        },
        _ => {
            d("I: ");
            dh(interrupt as usize);
            dl();
        }
    }

    if interrupt >= 0x20 && interrupt < 0x30 {
        if interrupt >= 0x28 {
            outb(0xA0, 0x20);
        }

        outb(0x20, 0x20);
    }
}

#[lang = "panic_fmt"]
pub fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32) -> !{
    d("PANIC: ");
    d(file);
    d(": ");
    dh(line as usize);
    dl();
    unsafe{
        asm!("cli");
        asm!("hlt");
    }
    loop{}
}

#[no_mangle]
pub extern "C" fn memcmp(a: *mut u8, b: *const u8, len: isize) -> isize {
    unsafe {
        let mut i = 0;
        while i < len {
            let c_a = *a.offset(i);
            let c_b = *b.offset(i);
            if c_a != c_b{
                return c_a as isize - c_b as isize;
            }
            i += 1;
        }
        return 0;
    }
}

#[no_mangle]
pub extern "C" fn memmove(dst: *mut u8, src: *const u8, len: isize){
    unsafe {
        if src < dst {
            let mut i = len;
            while i > 0 {
                i -= 1;
                *dst.offset(i) = *src.offset(i);
            }
        }else{
            let mut i = 0;
            while i < len {
                *dst.offset(i) = *src.offset(i);
                i += 1;
            }
        }
    }
}

#[no_mangle]
pub extern "C" fn memcpy(dst: *mut u8, src: *const u8, len: isize){
    unsafe {
        let mut i = 0;
        while i < len {
            *dst.offset(i) = *src.offset(i);
            i += 1;
        }
    }
}

#[no_mangle]
pub extern "C" fn memset(src: *mut u8, c: i32, len: isize) {
    unsafe {
        let mut i = 0;
        while i < len {
            *src.offset(i) = c as u8;
            i += 1;
        }
    }
}
<commit_msg>Still having trouble with panic<commit_after>#![feature(alloc)]
#![feature(asm)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core_simd)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(convert)]
#![feature(fnbox)]
#![feature(fundamental)]
#![feature(lang_items)]
#![feature(no_std)]
#![feature(rc_unique)]
#![feature(unboxed_closures)]
#![feature(unsafe_no_drop_flag)]
#![feature(vec_from_raw_buf)]
#![feature(vec_push_all)]
#![no_std]

extern crate alloc;

extern crate collections;

#[macro_use]
extern crate mopa;

use core::fmt;
use core::mem::size_of;

use alloc::rc::*;

use common::debug::*;
use common::pio::*;
use common::memory::*;
use common::string::*;
use common::url::*;

use drivers::keyboard::*;
use drivers::mouse::*;
use drivers::pci::*;
use drivers::ps2::*;
use drivers::serial::*;

use graphics::bmp::*;

use programs::filemanager::*;
use programs::session::*;

use schemes::file::*;
use schemes::http::*;
use schemes::memory::*;
use schemes::pci::*;
use schemes::random::*;

mod common {
    pub mod debug;
    pub mod elf;
    pub mod memory;
    pub mod pci;
    pub mod pio;
    pub mod random;
    pub mod string;
    pub mod url;
}

mod drivers {
    pub mod disk;
    pub mod keyboard;
    pub mod mouse;
    pub mod pci;
    pub mod ps2;
    pub mod serial;
}

mod filesystems {
    pub mod unfs;
}

mod graphics {
    pub mod bmp;
    pub mod color;
    pub mod display;
    pub mod point;
    pub mod size;
    pub mod window;
}

mod network {
    pub mod arp;
    pub mod common;
    pub mod ethernet;
    pub mod icmp;
    pub mod intel8254x;
    pub mod ipv4;
    pub mod rtl8139;
    pub mod tcp;
    pub mod udp;
}

mod programs {
    pub mod editor;
    pub mod executor;
    pub mod filemanager;
    pub mod session;
    pub mod viewer;
}

mod schemes {
    pub mod file;
    pub mod http;
    pub mod ide;
    pub mod memory;
    pub mod pci;
    pub mod random;
}

mod usb {
    pub mod xhci;
}

static mut session_ptr: *mut Session = 0 as *mut Session;

unsafe fn init(){
    serial_init();

    dd(size_of::<usize>() * 8);
    d(" bits");
    dl();

    page_init();
    cluster_init();

    session_ptr = alloc(size_of::<Session>()) as *mut Session;
    *session_ptr = Session::new();
    let session = &mut *session_ptr;

    session.items.insert(0, Rc::new(FileManager::new()));

    keyboard_init();
    mouse_init();

    session.modules.push(Rc::new(PS2));
    session.modules.push(Rc::new(Serial::new(0x3F8, 0x4)));

    pci_init(session);

    session.modules.push(Rc::new(FileScheme));
    session.modules.push(Rc::new(HTTPScheme));
    session.modules.push(Rc::new(MemoryScheme));
    session.modules.push(Rc::new(PCIScheme));
    session.modules.push(Rc::new(RandomScheme));

    session.on_url_wrapped(&URL::from_string("file:///background.bmp".to_string()), box |response: String|{
        if response.data as usize > 0 {
            (*session_ptr).display.background = BMP::from_data(response.data as usize);
        }
    });
}

#[no_mangle]
pub unsafe fn kernel(interrupt: u32) {
    match interrupt {
        0x20 => (), //timer
        0x21 => (*session_ptr).on_irq(0x1), //keyboard
        0x23 => (*session_ptr).on_irq(0x3), // serial 2 and 4
        0x24 => (*session_ptr).on_irq(0x4), // serial 1 and 3
        0x29 => (*session_ptr).on_irq(0x9), //pci
        0x2A => (*session_ptr).on_irq(0xA), //pci
        0x2B => (*session_ptr).on_irq(0xB), //pci
        0x2C => (*session_ptr).on_irq(0xC), //mouse
        0x2E => (*session_ptr).on_irq(0xE), //disk
        0x2F => (*session_ptr).on_irq(0xF), //disk
        0xFF => { // main loop
            init();

            loop {
                (*session_ptr).on_poll();
                (*session_ptr).redraw();
                asm!("sti");
                asm!("hlt");
                asm!("cli"); // TODO: Allow preempting
            }
        },
        0x0 => {
            d("Divide by zero exception\n");
        },
        0x1 => {
            d("Debug exception\n");
        },
        0x2 => {
            d("Non-maskable interrupt\n");
        },
        0x3 => {
            d("Breakpoint exception\n");
        },
        0x4 => {
            d("Overflow exception\n");
        },
        0x5 => {
            d("Bound range exceeded exception\n");
        },
        0x6 => {
            d("Invalid opcode exception\n");
        },
        0x7 => {
            d("Device not available exception\n");
        },
        0x8 => {
            d("Double fault\n");
        },
        0xA => {
            d("Invalid TSS exception\n");
        },
        0xB => {
            d("Segment not present exception\n");
        },
        0xC => {
            d("Stack-segment fault\n");
        },
        0xD => {
            d("General protection fault\n");
        },
        0xE => {
            d("Page fault\n");
        },
        0x10 => {
            d("x87 floating-point exception\n");
        },
        0x11 => {
            d("Alignment check exception\n");
        },
        0x12 => {
            d("Machine check exception\n");
        },
        0x13 => {
            d("SIMD floating-point exception\n");
        },
        0x14 => {
            d("Virtualization exception\n");
        },
        0x1E => {
            d("Security exception\n");
        },
        _ => {
            d("I: ");
            dh(interrupt as usize);
            dl();
        }
    }

    if interrupt >= 0x20 && interrupt < 0x30 {
        if interrupt >= 0x28 {
            outb(0xA0, 0x20);
        }

        outb(0x20, 0x20);
    }
}

#[lang = "panic_fmt"]
pub extern fn panic_fmt(fmt: fmt::Arguments, file: &'static str, line: u32) -> ! {
    d("PANIC: ");
    d(file);
    d(": ");
    dh(line as usize);
    dl();
    unsafe{
        asm!("cli");
        asm!("hlt");
    }
    loop{}
}

#[no_mangle]
pub extern "C" fn memcmp(a: *mut u8, b: *const u8, len: isize) -> isize {
    unsafe {
        let mut i = 0;
        while i < len {
            let c_a = *a.offset(i);
            let c_b = *b.offset(i);
            if c_a != c_b{
                return c_a as isize - c_b as isize;
            }
            i += 1;
        }
        return 0;
    }
}

#[no_mangle]
pub extern "C" fn memmove(dst: *mut u8, src: *const u8, len: isize){
    unsafe {
        if src < dst {
            let mut i = len;
            while i > 0 {
                i -= 1;
                *dst.offset(i) = *src.offset(i);
            }
        }else{
            let mut i = 0;
            while i < len {
                *dst.offset(i) = *src.offset(i);
                i += 1;
            }
        }
    }
}

#[no_mangle]
pub extern "C" fn memcpy(dst: *mut u8, src: *const u8, len: isize){
    unsafe {
        let mut i = 0;
        while i < len {
            *dst.offset(i) = *src.offset(i);
            i += 1;
        }
    }
}

#[no_mangle]
pub extern "C" fn memset(src: *mut u8, c: i32, len: isize) {
    unsafe {
        let mut i = 0;
        while i < len {
            *src.offset(i) = c as u8;
            i += 1;
        }
    }
}
<|endoftext|>


<commit_before>///! Basic CSS block layout.

use style::{StyledNode, Display};
use css::Value::{Keyword, Length};
use css::Unit::Px;
use std::default::Default;
use std::iter::AdditiveIterator; // for `sum`

pub use self::BoxType::{AnonymousBlock, InlineNode, BlockNode};

// CSS box model. All sizes are in px.

#[derive(Default, Show)]
pub struct Rect {
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
}

#[derive(Default, Show)]
pub struct Dimensions {
    /// Position of the content area relative to the document origin:
    pub content: Rect,
    // Surrounding edges:
    pub padding: EdgeSizes,
    pub border: EdgeSizes,
    pub margin: EdgeSizes,
}

#[derive(Default, Show)]
pub struct EdgeSizes {
    pub left: f32,
    pub right: f32,
    pub top: f32,
    pub bottom: f32,
}

impl Copy for Rect {}
impl Copy for Dimensions {}
impl Copy for EdgeSizes {}

/// A node in the layout tree.
pub struct LayoutBox<'a> {
    pub dimensions: Dimensions,
    pub box_type: BoxType<'a>,
    pub children: Vec<LayoutBox<'a>>,
}

pub enum BoxType<'a> {
    BlockNode(&'a StyledNode<'a>),
    InlineNode(&'a StyledNode<'a>),
    AnonymousBlock,
}

impl<'a> LayoutBox<'a> {
    fn new(box_type: BoxType) -> LayoutBox {
        LayoutBox {
            box_type: box_type,
            dimensions: Default::default(),
            children: Vec::new(),
        }
    }

    fn get_style_node(&self) -> &'a StyledNode<'a> {
        match self.box_type {
            BlockNode(node) => node,
            InlineNode(node) => node,
            AnonymousBlock => panic!("Anonymous block box has no style node")
        }
    }
}

/// Transform a style tree into a layout tree.
pub fn layout_tree<'a>(node: &'a StyledNode<'a>, mut containing_block: Dimensions) -> LayoutBox<'a> {
    // The layout algorithm expects the container height to start at 0.
    // TODO: Save the initial containing block height, for calculating percent heights.
    containing_block.content.height = 0.0;

    let mut root_box = build_layout_tree(node);
    root_box.layout(containing_block);
    return root_box;
}

/// Build the tree of LayoutBoxes, but don't perform any layout calculations yet.
fn build_layout_tree<'a>(style_node: &'a StyledNode<'a>) -> LayoutBox<'a> {
    // Create the root box.
    let mut root = LayoutBox::new(match style_node.display() {
        Display::Block => BlockNode(style_node),
        Display::Inline => InlineNode(style_node),
        Display::None => panic!("Root node has display: none.")
    });

    // Create the descendant boxes.
    for child in style_node.children.iter() {
        match child.display() {
            Display::Block => root.children.push(build_layout_tree(child)),
            Display::Inline => root.get_inline_container().children.push(build_layout_tree(child)),
            Display::None => {} // Don't lay out nodes with `display: none;`
        }
    }
    return root;
}

impl<'a> LayoutBox<'a> {
    /// Lay out a box and its descendants.
    fn layout(&mut self, containing_block: Dimensions) {
        match self.box_type {
            BlockNode(_) => self.layout_block(containing_block),
            InlineNode(_) => {} // TODO
            AnonymousBlock => {} // TODO
        }
    }

    /// Lay out a block-level element and its descendants.
    fn layout_block(&mut self, containing_block: Dimensions) {
        // Child width can depend on parent width, so we need to calculate this box's width before
        // laying out its children.
        self.calculate_block_width(containing_block);

        // Determine where the box is located within its container.
        self.calculate_block_position(containing_block);

        // Recursively lay out the children of this box.
        self.layout_block_children();

        // Parent height can depend on child height, so `calculate_height` must be called after the
        // children are laid out.
        self.calculate_block_height();
    }

    #[allow(unstable)]
    /// Calculate the width of a block-level non-replaced element in normal flow.
    ///
    /// http://www.w3.org/TR/CSS2/visudet.html#blockwidth
    ///
    /// Sets the horizontal margin/padding/border dimensions, and the `width`.
    fn calculate_block_width(&mut self, containing_block: Dimensions) {
        let style = self.get_style_node();

        // `width` has initial value `auto`.
        let auto = Keyword("auto".to_string());
        let mut width = style.value("width").unwrap_or(auto.clone());

        // margin, border, and padding have initial value 0.
        let zero = Length(0.0, Px);

        let mut margin_left = style.lookup("margin-left", "margin", &zero);
        let mut margin_right = style.lookup("margin-right", "margin", &zero);

        let border_left = style.lookup("border-left-width", "border-width", &zero);
        let border_right = style.lookup("border-right-width", "border-width", &zero);

        let padding_left = style.lookup("padding-left", "padding", &zero);
        let padding_right = style.lookup("padding-right", "padding", &zero);

        let total = [&margin_left, &margin_right, &border_left, &border_right,
                     &padding_left, &padding_right, &width].iter().map(|v| v.to_px()).sum();

        // If width is not auto and the total is wider than the container, treat auto margins as 0.
        if width != auto && total > containing_block.content.width {
            if margin_left == auto {
                margin_left = Length(0.0, Px);
            }
            if margin_right == auto {
                margin_right = Length(0.0, Px);
            }
        }

        // Adjust used values so that the above sum equals `containing_block.width`.
        // Each arm of the `match` should increase the total width by exactly `underflow`,
        // and afterward all values should be absolute lengths in px.
        let underflow = containing_block.content.width - total;

        match (width == auto, margin_left == auto, margin_right == auto) {
            // If the values are overconstrained, calculate margin_right.
            (false, false, false) => {
                margin_right = Length(margin_right.to_px() + underflow, Px);
            }

            // If exactly one size is auto, its used value follows from the equality.
            (false, false, true) => { margin_right = Length(underflow, Px); }
            (false, true, false) => { margin_left  = Length(underflow, Px); }

            // If width is set to auto, any other auto values become 0.
            (true, _, _) => {
                if margin_left == auto { margin_left = Length(0.0, Px); }
                if margin_right == auto { margin_right = Length(0.0, Px); }

                if underflow >= 0.0 {
                    // Expand width to fill the underflow.
                    width = Length(underflow, Px);
                } else {
                    // Width can't be negative. Adjust the right margin instead.
                    width = Length(0.0, Px);
                    margin_right = Length(margin_right.to_px() + underflow, Px);
                }
            }

            // If margin-left and margin-right are both auto, their used values are equal.
            (false, true, true) => {
                margin_left = Length(underflow / 2.0, Px);
                margin_right = Length(underflow / 2.0, Px);
            }
        }

        let d = &mut self.dimensions;
        d.content.width = width.to_px();

        d.padding.left = padding_left.to_px();
        d.padding.right = padding_right.to_px();

        d.border.left = border_left.to_px();
        d.border.right = border_right.to_px();

        d.margin.left = margin_left.to_px();
        d.margin.right = margin_right.to_px();
    }

    /// Finish calculating the block's edge sizes, and position it within its containing block.
    ///
    /// http://www.w3.org/TR/CSS2/visudet.html#normal-block
    ///
    /// Sets the vertical margin/padding/border dimensions, and the `x`, `y` values.
    fn calculate_block_position(&mut self, containing_block: Dimensions) {
        let style = self.get_style_node();
        let d = &mut self.dimensions;

        // margin, border, and padding have initial value 0.
        let zero = Length(0.0, Px);

        // If margin-top or margin-bottom is `auto`, the used value is zero.
        d.margin.top = style.lookup("margin-top", "margin", &zero).to_px();
        d.margin.bottom = style.lookup("margin-bottom", "margin", &zero).to_px();

        d.border.top = style.lookup("border-top-width", "border-width", &zero).to_px();
        d.border.bottom = style.lookup("border-bottom-width", "border-width", &zero).to_px();

        d.padding.top = style.lookup("padding-top", "padding", &zero).to_px();
        d.padding.bottom = style.lookup("padding-bottom", "padding", &zero).to_px();

        // Position the box below all the previous boxes in the container.
        d.content.x = containing_block.content.x +
                      d.margin.left + d.border.left + d.padding.left;
        d.content.y = containing_block.content.y + containing_block.content.height +
                      d.margin.top + d.border.top + d.padding.top;
    }

    /// Lay out the block's children within its content area.
    ///
    /// Sets `self.dimensions.height` to the total content height.
    fn layout_block_children(&mut self) {
        let d = &mut self.dimensions;
        for child in self.children.iter_mut() {
            child.layout(*d);
            // Increment the height so each child is laid out below the previous one.
            d.content.height = d.content.height + child.dimensions.margin_box().height;
        }
    }

    /// Height of a block-level non-replaced element in normal flow with overflow visible.
    fn calculate_block_height(&mut self) {
        // If the height is set to an explicit length, use that exact length.
        // Otherwise, just keep the value set by `layout_block_children`.
        match self.get_style_node().value("height") {
            Some(Length(h, Px)) => { self.dimensions.content.height = h; }
            _ => {}
        }
    }

    /// Where a new inline child should go.
    fn get_inline_container(&mut self) -> &mut LayoutBox<'a> {
        match self.box_type {
            InlineNode(_) | AnonymousBlock => self,
            BlockNode(_) => {
                // If we've just generated an anonymous block box, keep using it.
                // Otherwise, create a new one.
                match self.children.last() {
                    Some(&LayoutBox { box_type: AnonymousBlock,..}) => {}
                    _ => self.children.push(LayoutBox::new(AnonymousBlock))
                }
                self.children.last_mut().unwrap()
            }
        }
    }
}

impl Rect {
    pub fn expanded_by(self, edge: EdgeSizes) -> Rect {
        Rect {
            x: self.x - edge.left,
            y: self.y - edge.top,
            width: self.width + edge.left + edge.right,
            height: self.height + edge.top + edge.bottom,
        }
    }
}

impl Dimensions {
    /// The area covered by the content area plus its padding.
    pub fn padding_box(self) -> Rect {
        self.content.expanded_by(self.padding)
    }
    /// The area covered by the content area plus padding and borders.
    pub fn border_box(self) -> Rect {
        self.padding_box().expanded_by(self.border)
    }
    /// The area covered by the content area plus padding, borders, and margin.
    pub fn margin_box(self) -> Rect {
        self.border_box().expanded_by(self.margin)
    }
}
<commit_msg>Code cleanup<commit_after>///! Basic CSS block layout.

use style::{StyledNode, Display};
use css::Value::{Keyword, Length};
use css::Unit::Px;
use std::default::Default;
use std::iter::AdditiveIterator; // for `sum`

pub use self::BoxType::{AnonymousBlock, InlineNode, BlockNode};

// CSS box model. All sizes are in px.

#[derive(Default, Show)]
pub struct Rect {
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
}

#[derive(Default, Show)]
pub struct Dimensions {
    /// Position of the content area relative to the document origin:
    pub content: Rect,
    // Surrounding edges:
    pub padding: EdgeSizes,
    pub border: EdgeSizes,
    pub margin: EdgeSizes,
}

#[derive(Default, Show)]
pub struct EdgeSizes {
    pub left: f32,
    pub right: f32,
    pub top: f32,
    pub bottom: f32,
}

impl Copy for Rect {}
impl Copy for Dimensions {}
impl Copy for EdgeSizes {}

/// A node in the layout tree.
pub struct LayoutBox<'a> {
    pub dimensions: Dimensions,
    pub box_type: BoxType<'a>,
    pub children: Vec<LayoutBox<'a>>,
}

pub enum BoxType<'a> {
    BlockNode(&'a StyledNode<'a>),
    InlineNode(&'a StyledNode<'a>),
    AnonymousBlock,
}

impl<'a> LayoutBox<'a> {
    fn new(box_type: BoxType) -> LayoutBox {
        LayoutBox {
            box_type: box_type,
            dimensions: Default::default(),
            children: Vec::new(),
        }
    }

    fn get_style_node(&self) -> &'a StyledNode<'a> {
        match self.box_type {
            BlockNode(node) => node,
            InlineNode(node) => node,
            AnonymousBlock => panic!("Anonymous block box has no style node")
        }
    }
}

/// Transform a style tree into a layout tree.
pub fn layout_tree<'a>(node: &'a StyledNode<'a>, mut containing_block: Dimensions) -> LayoutBox<'a> {
    // The layout algorithm expects the container height to start at 0.
    // TODO: Save the initial containing block height, for calculating percent heights.
    containing_block.content.height = 0.0;

    let mut root_box = build_layout_tree(node);
    root_box.layout(containing_block);
    return root_box;
}

/// Build the tree of LayoutBoxes, but don't perform any layout calculations yet.
fn build_layout_tree<'a>(style_node: &'a StyledNode<'a>) -> LayoutBox<'a> {
    // Create the root box.
    let mut root = LayoutBox::new(match style_node.display() {
        Display::Block => BlockNode(style_node),
        Display::Inline => InlineNode(style_node),
        Display::None => panic!("Root node has display: none.")
    });

    // Create the descendant boxes.
    for child in style_node.children.iter() {
        match child.display() {
            Display::Block => root.children.push(build_layout_tree(child)),
            Display::Inline => root.get_inline_container().children.push(build_layout_tree(child)),
            Display::None => {} // Don't lay out nodes with `display: none;`
        }
    }
    return root;
}

impl<'a> LayoutBox<'a> {
    /// Lay out a box and its descendants.
    fn layout(&mut self, containing_block: Dimensions) {
        match self.box_type {
            BlockNode(_) => self.layout_block(containing_block),
            InlineNode(_) => {} // TODO
            AnonymousBlock => {} // TODO
        }
    }

    /// Lay out a block-level element and its descendants.
    fn layout_block(&mut self, containing_block: Dimensions) {
        // Child width can depend on parent width, so we need to calculate this box's width before
        // laying out its children.
        self.calculate_block_width(containing_block);

        // Determine where the box is located within its container.
        self.calculate_block_position(containing_block);

        // Recursively lay out the children of this box.
        self.layout_block_children();

        // Parent height can depend on child height, so `calculate_height` must be called after the
        // children are laid out.
        self.calculate_block_height();
    }

    #[allow(unstable)]
    /// Calculate the width of a block-level non-replaced element in normal flow.
    ///
    /// http://www.w3.org/TR/CSS2/visudet.html#blockwidth
    ///
    /// Sets the horizontal margin/padding/border dimensions, and the `width`.
    fn calculate_block_width(&mut self, containing_block: Dimensions) {
        let style = self.get_style_node();

        // `width` has initial value `auto`.
        let auto = Keyword("auto".to_string());
        let mut width = style.value("width").unwrap_or(auto.clone());

        // margin, border, and padding have initial value 0.
        let zero = Length(0.0, Px);

        let mut margin_left = style.lookup("margin-left", "margin", &zero);
        let mut margin_right = style.lookup("margin-right", "margin", &zero);

        let border_left = style.lookup("border-left-width", "border-width", &zero);
        let border_right = style.lookup("border-right-width", "border-width", &zero);

        let padding_left = style.lookup("padding-left", "padding", &zero);
        let padding_right = style.lookup("padding-right", "padding", &zero);

        let total = [&margin_left, &margin_right, &border_left, &border_right,
                     &padding_left, &padding_right, &width].iter().map(|v| v.to_px()).sum();

        // If width is not auto and the total is wider than the container, treat auto margins as 0.
        if width != auto && total > containing_block.content.width {
            if margin_left == auto {
                margin_left = Length(0.0, Px);
            }
            if margin_right == auto {
                margin_right = Length(0.0, Px);
            }
        }

        // Adjust used values so that the above sum equals `containing_block.width`.
        // Each arm of the `match` should increase the total width by exactly `underflow`,
        // and afterward all values should be absolute lengths in px.
        let underflow = containing_block.content.width - total;

        match (width == auto, margin_left == auto, margin_right == auto) {
            // If the values are overconstrained, calculate margin_right.
            (false, false, false) => {
                margin_right = Length(margin_right.to_px() + underflow, Px);
            }

            // If exactly one size is auto, its used value follows from the equality.
            (false, false, true) => { margin_right = Length(underflow, Px); }
            (false, true, false) => { margin_left  = Length(underflow, Px); }

            // If width is set to auto, any other auto values become 0.
            (true, _, _) => {
                if margin_left == auto { margin_left = Length(0.0, Px); }
                if margin_right == auto { margin_right = Length(0.0, Px); }

                if underflow >= 0.0 {
                    // Expand width to fill the underflow.
                    width = Length(underflow, Px);
                } else {
                    // Width can't be negative. Adjust the right margin instead.
                    width = Length(0.0, Px);
                    margin_right = Length(margin_right.to_px() + underflow, Px);
                }
            }

            // If margin-left and margin-right are both auto, their used values are equal.
            (false, true, true) => {
                margin_left = Length(underflow / 2.0, Px);
                margin_right = Length(underflow / 2.0, Px);
            }
        }

        let d = &mut self.dimensions;
        d.content.width = width.to_px();

        d.padding.left = padding_left.to_px();
        d.padding.right = padding_right.to_px();

        d.border.left = border_left.to_px();
        d.border.right = border_right.to_px();

        d.margin.left = margin_left.to_px();
        d.margin.right = margin_right.to_px();
    }

    /// Finish calculating the block's edge sizes, and position it within its containing block.
    ///
    /// http://www.w3.org/TR/CSS2/visudet.html#normal-block
    ///
    /// Sets the vertical margin/padding/border dimensions, and the `x`, `y` values.
    fn calculate_block_position(&mut self, containing_block: Dimensions) {
        let style = self.get_style_node();
        let d = &mut self.dimensions;

        // margin, border, and padding have initial value 0.
        let zero = Length(0.0, Px);

        // If margin-top or margin-bottom is `auto`, the used value is zero.
        d.margin.top = style.lookup("margin-top", "margin", &zero).to_px();
        d.margin.bottom = style.lookup("margin-bottom", "margin", &zero).to_px();

        d.border.top = style.lookup("border-top-width", "border-width", &zero).to_px();
        d.border.bottom = style.lookup("border-bottom-width", "border-width", &zero).to_px();

        d.padding.top = style.lookup("padding-top", "padding", &zero).to_px();
        d.padding.bottom = style.lookup("padding-bottom", "padding", &zero).to_px();

        d.content.x = containing_block.content.x +
                      d.margin.left + d.border.left + d.padding.left;

        // Position the box below all the previous boxes in the container.
        d.content.y = containing_block.content.height + containing_block.content.y +
                      d.margin.top + d.border.top + d.padding.top;
    }

    /// Lay out the block's children within its content area.
    ///
    /// Sets `self.dimensions.height` to the total content height.
    fn layout_block_children(&mut self) {
        let d = &mut self.dimensions;
        for child in self.children.iter_mut() {
            child.layout(*d);
            // Increment the height so each child is laid out below the previous one.
            d.content.height = d.content.height + child.dimensions.margin_box().height;
        }
    }

    /// Height of a block-level non-replaced element in normal flow with overflow visible.
    fn calculate_block_height(&mut self) {
        // If the height is set to an explicit length, use that exact length.
        // Otherwise, just keep the value set by `layout_block_children`.
        if let Some(Length(h, Px)) = self.get_style_node().value("height") {
            self.dimensions.content.height = h;
        }
    }

    /// Where a new inline child should go.
    fn get_inline_container(&mut self) -> &mut LayoutBox<'a> {
        match self.box_type {
            InlineNode(_) | AnonymousBlock => self,
            BlockNode(_) => {
                // If we've just generated an anonymous block box, keep using it.
                // Otherwise, create a new one.
                match self.children.last() {
                    Some(&LayoutBox { box_type: AnonymousBlock,..}) => {}
                    _ => self.children.push(LayoutBox::new(AnonymousBlock))
                }
                self.children.last_mut().unwrap()
            }
        }
    }
}

impl Rect {
    pub fn expanded_by(self, edge: EdgeSizes) -> Rect {
        Rect {
            x: self.x - edge.left,
            y: self.y - edge.top,
            width: self.width + edge.left + edge.right,
            height: self.height + edge.top + edge.bottom,
        }
    }
}

impl Dimensions {
    /// The area covered by the content area plus its padding.
    pub fn padding_box(self) -> Rect {
        self.content.expanded_by(self.padding)
    }
    /// The area covered by the content area plus padding and borders.
    pub fn border_box(self) -> Rect {
        self.padding_box().expanded_by(self.border)
    }
    /// The area covered by the content area plus padding, borders, and margin.
    pub fn margin_box(self) -> Rect {
        self.border_box().expanded_by(self.margin)
    }
}
<|endoftext|>


<commit_before>//!Router asigns handlers to paths and resolves them per request

#[cfg(test)]
use http::method;
use http::method::{ Method, Get, Post, Put, Delete };
use http::server::request::{AbsolutePath};
use regex::Regex;
use std::collections::hashmap::HashMap;
use request::Request;
use response::Response;
use middleware::{ Middleware, Action, Halt, Continue };
use nickel_error::NickelError;

/// A Route is the basic data structure that stores both the path
/// and the handler that gets executed for the route.
/// The path can contain variable pattern such as `user/:userid/invoices`
pub struct Route {
    pub path: String,
    pub method: Method,
    pub handler: fn(request: &Request, response: &mut Response),
    pub variables: HashMap<String, uint>,
    matcher: Regex
}

impl Clone for Route {
    fn clone(&self) -> Route {
        Route {
            path: self.path.clone(),
            method: self.method.clone(),
            handler: self.handler,
            matcher: self.matcher.clone(),
            variables: self.variables.clone()
        }
    }
}

/// A RouteResult is what the router returns when `match_route` is called.
/// It contains the matched `route` and also a `params` property holding
/// a HashMap with the keys being the variable names and the value being the
/// evaluated string
pub struct RouteResult<'a> {
    pub route: &'a Route,
    pub params: HashMap<String, String>
}

/// The PathUtils collects some small helper methods that operate on the path
struct PathUtils;

// matches named variables (e.g. :userid)
static REGEX_VAR_SEQ: Regex                 = regex!(r":([,a-zA-Z0-9_-]*)");
static VAR_SEQ:&'static str                 = "[,a-zA-Z0-9_-]*";
static VAR_SEQ_WITH_SLASH:&'static str      = "[,/a-zA-Z0-9_-]*";
static VAR_SEQ_WITH_CAPTURE:&'static str    = "([,a-zA-Z0-9%_-]*)";
// matches request params (e.g. ?foo=true&bar=false)
static REGEX_PARAM_SEQ:&'static str         = "(\\?[a-zA-Z0-9%_=&-]*)?";
static REGEX_START:&'static str             = "^";
static REGEX_END:&'static str               = "$";

impl PathUtils {
    fn create_regex (route_path: &str) -> Regex {

        let updated_path = route_path.to_string()
                                     // first mark all double wildcards for replacement. We can't directly replace them
                                     // since the replacement does contain the * symbol as well, which would get overwritten
                                     // with the next replace call
                                     .replace("**", "___DOUBLE_WILDCARD___")
                                     // then replace the regular wildcard symbols (*) with the appropriate regex
                                     .replace("*", VAR_SEQ)
                                     // now replace the previously marked double wild cards (**)
                                     .replace("___DOUBLE_WILDCARD___", VAR_SEQ_WITH_SLASH);

        // then replace the variable symbols (:variable) with the appropriate regex
        let result = [REGEX_START,
                      REGEX_VAR_SEQ.replace_all(updated_path.as_slice(),
                                                VAR_SEQ_WITH_CAPTURE)
                                   .as_slice(),
                      REGEX_PARAM_SEQ,
                      REGEX_END].concat();

        match Regex::new(result.as_slice()) {
            Ok(re) => re,
            Err(err) => fail!("{}", err)
        }
    }

    fn get_variable_info (route_path: &str) -> HashMap<String, uint> {
        REGEX_VAR_SEQ.captures_iter(route_path)
             .enumerate()
             .map(|(i, matched)| (matched.at(1).to_string(), i))
             .collect()
    }
}

/// The Router's job is it to hold routes and to resolve them later against
/// concrete URLs. The router is also a regular middleware and needs to be
/// added to the middleware stack with `server.utilize(router)`.

#[deriving(Clone)]
pub struct Router{
    routes: Vec<Route>,
}

impl Router {
    pub fn new () -> Router {
        Router {
            routes: Vec::new()
        }
    }

    /// Registers a handler to be used for a specific GET request.
    /// Handlers are assigned to paths and paths are allowed to contain
    /// variables and wildcards.
    ///
    /// # Example without variables and wildcards
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches /user");
    /// };
    /// router.get("/user", handler);
    /// ```
    /// # Example with variables
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     let text = format!("This is user: {}", request.params.get(&"userid".to_string()));
    ///     response.send(text.as_slice());
    /// };
    /// router.get("/user/:userid", handler);
    /// ```
    /// # Example with simple wildcard
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches /user/list/4711 but not /user/extended/list/4711");
    /// };
    /// router.get("/user/*/:userid", handler);
    /// ```
    /// # Example with double wildcard
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches /user/list/4711 and also /user/extended/list/4711");
    /// };
    /// router.get("/user/**/:userid", handler);
    /// ```
    pub fn get(&mut self, uri: &str, handler: fn(request: &Request, response: &mut Response)){
        self.add_route(Get, String::from_str(uri), handler);
    }

    /// Registers a handler to be used for a specific POST request.
    ///
    /// # Example
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches a POST request to /a/post/request");
    /// };
    /// router.post("/a/post/request", handler);
    /// ```
    /// Take a look at `get()` for a more detailed description.
    pub fn post(&mut self, uri: &str, handler: fn(request: &Request, response: &mut Response)){
        self.add_route(Post, String::from_str(uri), handler);
    }

    /// Registers a handler to be used for a specific PUT request.
    ///
    /// # Example
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches a POST request to /a/put/request");
    /// };
    /// router.put("/a/put/request", handler);
    /// ```
    /// Take a look at `get(..)` for a more detailed description.
    pub fn put(&mut self, uri: &str, handler: fn(request: &Request, response: &mut Response)){
        self.add_route(Put, String::from_str(uri), handler);
    }

    /// Registers a handler to be used for a specific DELETE request.
    ///
    /// # Example
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches a DELETE request to /a/delete/request");
    /// };
    /// router.delete("/a/delete/request", handler);
    /// ```
    /// Take a look at `get(...)` for a more detailed description.
    pub fn delete(&mut self, uri: &str, handler: fn(request: &Request, response: &mut Response)){
        self.add_route(Delete, String::from_str(uri), handler);
    }

    pub fn add_route (&mut self, method: Method, path: String, handler: fn(request: &Request, response: &mut Response)) -> () {
        let matcher = PathUtils::create_regex(path.as_slice());
        let variable_infos = PathUtils::get_variable_info(path.as_slice());
        let route = Route {
            path: path,
            method: method,
            matcher: matcher,
            handler: handler,
            variables: variable_infos
        };
        self.routes.push(route);
    }

    pub fn match_route(&self, method: &Method, path: &str) -> Option<RouteResult> {
        self.routes.iter().find(|item| item.method == *method && item.matcher.is_match(path))
            .map(|route| {
                let map = match route.matcher.captures(path) {
                    Some(captures) => {
                        route.variables.iter().map(|(name, pos)| {
                            (name.to_string(), captures.at(pos + 1).to_string())
                        }).collect()
                    },
                    None => HashMap::new(),
                };
                RouteResult {
                    route: route,
                    params: map
                }
            })
    }
}

impl Middleware for Router {
    fn invoke (&self, req: &mut Request, res: &mut Response) -> Result<Action, NickelError> {
        match req.origin.request_uri {
            AbsolutePath(ref url) => {
                match self.match_route(&req.origin.method, url.as_slice()) {
                    Some(route_result) => {
                        res.origin.status = ::http::status::Ok;
                        req.params = route_result.params.clone();
                        (route_result.route.handler)(req, res);
                        Ok(Halt)
                    },
                    None => Ok(Continue)
                }
            },
            _ => Ok(Continue)
        }
    }
}

#[test]
fn creates_map_with_var_variable_infos () {
    let map = PathUtils::get_variable_info("foo/:uid/bar/:groupid");

    assert_eq!(map.len(), 2);
    assert_eq!(map.get(&"uid".to_string()), &0);
    assert_eq!(map.get(&"groupid".to_string()), &1);
}

#[test]
fn creates_regex_with_captures () {
    let regex = PathUtils::create_regex("foo/:uid/bar/:groupid");
    let caps = regex.captures("foo/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");

    let regex = PathUtils::create_regex("foo/*/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");

    let regex = PathUtils::create_regex("foo/**/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/another/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");
}

#[test]
fn creates_valid_regex_for_routes () {
    let regex1 = PathUtils::create_regex("foo/:uid/bar/:groupid");
    let regex2 = PathUtils::create_regex("foo/*/bar");
    let regex3 = PathUtils::create_regex("foo/**/bar");

    assert_eq!(regex1.is_match("foo/4711/bar/5490"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5490?foo=true&bar=false"), true);
    assert_eq!(regex1.is_match("foo/4711/bar"), false);
    assert_eq!(regex1.is_match("foo/4711/bar?foo=true&bar=false"), false);
    assert_eq!(regex1.is_match("foo/4711/bar/test%20spacing"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5281?foo=test%20spacing&bar=false"), true);

    assert_eq!(regex2.is_match("foo/4711/bar"), true);
    assert_eq!(regex2.is_match("foo/4711/barr"), false);
    assert_eq!(regex2.is_match("foo/4711/bar?foo=true&bar=false"), true);
    assert_eq!(regex2.is_match("foo/4711/4712/bar"), false);
    assert_eq!(regex2.is_match("foo/4711/4712/bar?foo=true&bar=false"), false);

    assert_eq!(regex3.is_match("foo/4711/bar"), true);
    assert_eq!(regex3.is_match("foo/4711/bar?foo=true&bar=false"), true);
    assert_eq!(regex3.is_match("foo/4711/4712/bar"), true);
    assert_eq!(regex3.is_match("foo/4711/4712/bar?foo=true&bar=false"), true);

    //ensure that this works with commas too
    assert_eq!(regex1.is_match("foo/4711/bar/5490,1234"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5490,1234?foo=true&bar=false"), true);
    assert_eq!(regex1.is_match("foo/4711/bar"), false);
    assert_eq!(regex1.is_match("foo/4711/bar?foo=1,2,3&bar=false"), false);
}

#[test]
fn can_match_var_routes () {
    let route_store = &mut Router::new();

    fn handler (_request: &Request, response: &mut Response) -> () {
        let _ = response.origin.write("hello from foo".as_bytes());
    };

    route_store.add_route(method::Get, "/foo/:userid".to_string(), handler);
    route_store.add_route(method::Get, "/bar".to_string(), handler);

    let route_result = route_store.match_route(&method::Get, "/foo/4711").unwrap();
    let route = route_result.route;

    assert_eq!(route_result.params.get(&"userid".to_string()), &"4711".to_string());

    //assert the route has identified the variable
    assert_eq!(route.variables.len(), 1);
    assert_eq!(route.variables.get(&"userid".to_string()), &0);

    let route_result = route_store.match_route(&method::Get, "/bar/4711");
    assert!(route_result.is_none());

    let route_result = route_store.match_route(&method::Get, "/foo");
    assert!(route_result.is_none());

    //ensure that this will work with commas too
    let route_result = route_store.match_route(&method::Get, "/foo/123,456");
    assert!(route_result.is_some());

    let route_result = route_result.unwrap();
    assert_eq!(route_result.params.get(&"userid".to_string()), &"123,456".to_string());

    //ensure that this will work with spacing too
    let route_result = route_store.match_route(&method::Get, "/foo/John%20Doe");
    assert!(route_result.is_some());

    let route_result = route_result.unwrap();
    assert_eq!(route_result.params.get(&"userid".to_string()), &"John%20Doe".to_string());
}
<commit_msg>Swap Phantom type for module.<commit_after>//!Router asigns handlers to paths and resolves them per request

#[cfg(test)]
use http::method;
use http::method::{ Method, Get, Post, Put, Delete };
use http::server::request::{AbsolutePath};
use regex::Regex;
use std::collections::hashmap::HashMap;
use request::Request;
use response::Response;
use middleware::{ Middleware, Action, Halt, Continue };
use nickel_error::NickelError;

/// A Route is the basic data structure that stores both the path
/// and the handler that gets executed for the route.
/// The path can contain variable pattern such as `user/:userid/invoices`
pub struct Route {
    pub path: String,
    pub method: Method,
    pub handler: fn(request: &Request, response: &mut Response),
    pub variables: HashMap<String, uint>,
    matcher: Regex
}

impl Clone for Route {
    fn clone(&self) -> Route {
        Route {
            path: self.path.clone(),
            method: self.method.clone(),
            handler: self.handler,
            matcher: self.matcher.clone(),
            variables: self.variables.clone()
        }
    }
}

/// A RouteResult is what the router returns when `match_route` is called.
/// It contains the matched `route` and also a `params` property holding
/// a HashMap with the keys being the variable names and the value being the
/// evaluated string
pub struct RouteResult<'a> {
    pub route: &'a Route,
    pub params: HashMap<String, String>
}

/// The path_utils collects some small helper methods that operate on the path
mod path_utils {
    use regex::Regex;
    use std::collections::hashmap::HashMap;

    // matches named variables (e.g. :userid)
    static REGEX_VAR_SEQ: Regex                 = regex!(r":([,a-zA-Z0-9_-]*)");
    static VAR_SEQ:&'static str                 = "[,a-zA-Z0-9_-]*";
    static VAR_SEQ_WITH_SLASH:&'static str      = "[,/a-zA-Z0-9_-]*";
    static VAR_SEQ_WITH_CAPTURE:&'static str    = "([,a-zA-Z0-9%_-]*)";
    // matches request params (e.g. ?foo=true&bar=false)
    static REGEX_PARAM_SEQ:&'static str         = "(\\?[a-zA-Z0-9%_=&-]*)?";
    static REGEX_START:&'static str             = "^";
    static REGEX_END:&'static str               = "$";
    pub fn create_regex (route_path: &str) -> Regex {

        let updated_path = route_path.to_string()
                                     // first mark all double wildcards for replacement. We can't directly replace them
                                     // since the replacement does contain the * symbol as well, which would get overwritten
                                     // with the next replace call
                                     .replace("**", "___DOUBLE_WILDCARD___")
                                     // then replace the regular wildcard symbols (*) with the appropriate regex
                                     .replace("*", VAR_SEQ)
                                     // now replace the previously marked double wild cards (**)
                                     .replace("___DOUBLE_WILDCARD___", VAR_SEQ_WITH_SLASH);

        // then replace the variable symbols (:variable) with the appropriate regex
        let result = [REGEX_START,
                      REGEX_VAR_SEQ.replace_all(updated_path.as_slice(),
                                                VAR_SEQ_WITH_CAPTURE)
                                   .as_slice(),
                      REGEX_PARAM_SEQ,
                      REGEX_END].concat();

        match Regex::new(result.as_slice()) {
            Ok(re) => re,
            Err(err) => fail!("{}", err)
        }
    }

    pub fn get_variable_info (route_path: &str) -> HashMap<String, uint> {
        REGEX_VAR_SEQ.captures_iter(route_path)
             .enumerate()
             .map(|(i, matched)| (matched.at(1).to_string(), i))
             .collect()
    }
}

/// The Router's job is it to hold routes and to resolve them later against
/// concrete URLs. The router is also a regular middleware and needs to be
/// added to the middleware stack with `server.utilize(router)`.

#[deriving(Clone)]
pub struct Router{
    routes: Vec<Route>,
}

impl Router {
    pub fn new () -> Router {
        Router {
            routes: Vec::new()
        }
    }

    /// Registers a handler to be used for a specific GET request.
    /// Handlers are assigned to paths and paths are allowed to contain
    /// variables and wildcards.
    ///
    /// # Example without variables and wildcards
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches /user");
    /// };
    /// router.get("/user", handler);
    /// ```
    /// # Example with variables
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     let text = format!("This is user: {}", request.params.get(&"userid".to_string()));
    ///     response.send(text.as_slice());
    /// };
    /// router.get("/user/:userid", handler);
    /// ```
    /// # Example with simple wildcard
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches /user/list/4711 but not /user/extended/list/4711");
    /// };
    /// router.get("/user/*/:userid", handler);
    /// ```
    /// # Example with double wildcard
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches /user/list/4711 and also /user/extended/list/4711");
    /// };
    /// router.get("/user/**/:userid", handler);
    /// ```
    pub fn get(&mut self, uri: &str, handler: fn(request: &Request, response: &mut Response)){
        self.add_route(Get, String::from_str(uri), handler);
    }

    /// Registers a handler to be used for a specific POST request.
    ///
    /// # Example
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches a POST request to /a/post/request");
    /// };
    /// router.post("/a/post/request", handler);
    /// ```
    /// Take a look at `get()` for a more detailed description.
    pub fn post(&mut self, uri: &str, handler: fn(request: &Request, response: &mut Response)){
        self.add_route(Post, String::from_str(uri), handler);
    }

    /// Registers a handler to be used for a specific PUT request.
    ///
    /// # Example
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches a POST request to /a/put/request");
    /// };
    /// router.put("/a/put/request", handler);
    /// ```
    /// Take a look at `get(..)` for a more detailed description.
    pub fn put(&mut self, uri: &str, handler: fn(request: &Request, response: &mut Response)){
        self.add_route(Put, String::from_str(uri), handler);
    }

    /// Registers a handler to be used for a specific DELETE request.
    ///
    /// # Example
    ///
    /// ```{rust,ignore}
    /// fn handler (request: Request, response: &mut Response) {
    ///     response.send("This matches a DELETE request to /a/delete/request");
    /// };
    /// router.delete("/a/delete/request", handler);
    /// ```
    /// Take a look at `get(...)` for a more detailed description.
    pub fn delete(&mut self, uri: &str, handler: fn(request: &Request, response: &mut Response)){
        self.add_route(Delete, String::from_str(uri), handler);
    }

    pub fn add_route(&mut self, method: Method, path: String, handler: fn(request: &Request, response: &mut Response)) -> () {
        let matcher = path_utils::create_regex(path.as_slice());
        let variable_infos = path_utils::get_variable_info(path.as_slice());
        let route = Route {
            path: path,
            method: method,
            matcher: matcher,
            handler: handler,
            variables: variable_infos
        };
        self.routes.push(route);
    }

    pub fn match_route(&self, method: &Method, path: &str) -> Option<RouteResult> {
        self.routes.iter().find(|item| item.method == *method && item.matcher.is_match(path))
            .map(|route| {
                let map = match route.matcher.captures(path) {
                    Some(captures) => {
                        route.variables.iter().map(|(name, pos)| {
                            (name.to_string(), captures.at(pos + 1).to_string())
                        }).collect()
                    },
                    None => HashMap::new(),
                };
                RouteResult {
                    route: route,
                    params: map
                }
            })
    }
}

impl Middleware for Router {
    fn invoke (&self, req: &mut Request, res: &mut Response) -> Result<Action, NickelError> {
        match req.origin.request_uri {
            AbsolutePath(ref url) => {
                match self.match_route(&req.origin.method, url.as_slice()) {
                    Some(route_result) => {
                        res.origin.status = ::http::status::Ok;
                        req.params = route_result.params.clone();
                        (route_result.route.handler)(req, res);
                        Ok(Halt)
                    },
                    None => Ok(Continue)
                }
            },
            _ => Ok(Continue)
        }
    }
}

#[test]
fn creates_map_with_var_variable_infos () {
    let map = path_utils::get_variable_info("foo/:uid/bar/:groupid");

    assert_eq!(map.len(), 2);
    assert_eq!(map.get(&"uid".to_string()), &0);
    assert_eq!(map.get(&"groupid".to_string()), &1);
}

#[test]
fn creates_regex_with_captures () {
    let regex = path_utils::create_regex("foo/:uid/bar/:groupid");
    let caps = regex.captures("foo/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");

    let regex = path_utils::create_regex("foo/*/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");

    let regex = path_utils::create_regex("foo/**/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/another/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");
}

#[test]
fn creates_valid_regex_for_routes () {
    let regex1 = path_utils::create_regex("foo/:uid/bar/:groupid");
    let regex2 = path_utils::create_regex("foo/*/bar");
    let regex3 = path_utils::create_regex("foo/**/bar");

    assert_eq!(regex1.is_match("foo/4711/bar/5490"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5490?foo=true&bar=false"), true);
    assert_eq!(regex1.is_match("foo/4711/bar"), false);
    assert_eq!(regex1.is_match("foo/4711/bar?foo=true&bar=false"), false);
    assert_eq!(regex1.is_match("foo/4711/bar/test%20spacing"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5281?foo=test%20spacing&bar=false"), true);

    assert_eq!(regex2.is_match("foo/4711/bar"), true);
    assert_eq!(regex2.is_match("foo/4711/barr"), false);
    assert_eq!(regex2.is_match("foo/4711/bar?foo=true&bar=false"), true);
    assert_eq!(regex2.is_match("foo/4711/4712/bar"), false);
    assert_eq!(regex2.is_match("foo/4711/4712/bar?foo=true&bar=false"), false);

    assert_eq!(regex3.is_match("foo/4711/bar"), true);
    assert_eq!(regex3.is_match("foo/4711/bar?foo=true&bar=false"), true);
    assert_eq!(regex3.is_match("foo/4711/4712/bar"), true);
    assert_eq!(regex3.is_match("foo/4711/4712/bar?foo=true&bar=false"), true);

    //ensure that this works with commas too
    assert_eq!(regex1.is_match("foo/4711/bar/5490,1234"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5490,1234?foo=true&bar=false"), true);
    assert_eq!(regex1.is_match("foo/4711/bar"), false);
    assert_eq!(regex1.is_match("foo/4711/bar?foo=1,2,3&bar=false"), false);
}

#[test]
fn can_match_var_routes () {
    let route_store = &mut Router::new();

    fn handler (_request: &Request, response: &mut Response) -> () {
        let _ = response.origin.write("hello from foo".as_bytes());
    };

    route_store.add_route(method::Get, "/foo/:userid".to_string(), handler);
    route_store.add_route(method::Get, "/bar".to_string(), handler);

    let route_result = route_store.match_route(&method::Get, "/foo/4711").unwrap();
    let route = route_result.route;

    assert_eq!(route_result.params.get(&"userid".to_string()), &"4711".to_string());

    //assert the route has identified the variable
    assert_eq!(route.variables.len(), 1);
    assert_eq!(route.variables.get(&"userid".to_string()), &0);

    let route_result = route_store.match_route(&method::Get, "/bar/4711");
    assert!(route_result.is_none());

    let route_result = route_store.match_route(&method::Get, "/foo");
    assert!(route_result.is_none());

    //ensure that this will work with commas too
    let route_result = route_store.match_route(&method::Get, "/foo/123,456");
    assert!(route_result.is_some());

    let route_result = route_result.unwrap();
    assert_eq!(route_result.params.get(&"userid".to_string()), &"123,456".to_string());

    //ensure that this will work with spacing too
    let route_result = route_store.match_route(&method::Get, "/foo/John%20Doe");
    assert!(route_result.is_some());

    let route_result = route_result.unwrap();
    assert_eq!(route_result.params.get(&"userid".to_string()), &"John%20Doe".to_string());
}
<|endoftext|>


<commit_before>extern crate odbc;
use odbc::*;

#[test]
fn list_tables() {

    let env = Environment::new().unwrap();
    let env = env.set_odbc_version_3().unwrap();
    let ds = DataSource::with_parent(&env).unwrap();
    let mut ds = ds.connect("TestDataSource", "", "").unwrap();
    // scope is required (for now) to close statement before disconnecting
    {
        let statement = Statement::with_parent(&mut ds).unwrap();
        let statement = statement.tables().unwrap();
        assert_eq!(statement.num_result_cols().unwrap(), 5);
    }
    ds.disconnect().unwrap();
}

#[test]
fn not_read_only() {

    let env = Environment::new().unwrap();
    let env = env.set_odbc_version_3().unwrap();
    let conn = DataSource::with_parent(&env).unwrap();
    let conn = conn.connect("TestDataSource", "", "").unwrap();

    assert!(!conn.read_only().unwrap());
    conn.disconnect().unwrap();
}

#[test]
fn implicit_disconnect() {

    let env = Environment::new().unwrap();
    let env = env.set_odbc_version_3().unwrap();
    let conn = DataSource::with_parent(&env).unwrap();
    conn.connect("TestDataSource", "", "").unwrap();

    // if there would be no implicit disconnect, all the drops would panic with function sequence
    // error
}

#[test]
fn invalid_connection_string() {

    let expected = if cfg!(target_os = "windows") {
        "State: IM002, Native error: 0, Message: [Microsoft][ODBC Driver Manager] Data source \
            name not found and no default driver specified"
    } else {
        "State: IM002, Native error: 0, Message: [unixODBC][Driver Manager]Data source name not \
            found, and no default driver specified"
    };

    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let conn = DataSource::with_parent(&environment).unwrap();
    let result = conn.connect_with_connection_string("bla");
    let message = format!("{}", result.err().unwrap());
    assert_eq!(expected, message);
}

#[test]
fn test_connection_string() {

    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let conn = DataSource::with_parent(&environment).unwrap();
    let conn = conn.connect_with_connection_string("dsn=TestDataSource;Uid=;Pwd=;")
        .unwrap();
    conn.disconnect().unwrap();
}

#[test]
fn test_direct_select() {
    let env = Environment::new().unwrap().set_odbc_version_3().unwrap();
    let conn = DataSource::with_parent(&env).unwrap().connect("TestDataSource", "", "").unwrap();
    let stmt = Statement::with_parent(&conn).unwrap();

    let mut stmt = stmt.exec_direct("SELECT TITLE, YEAR FROM MOVIES ORDER BY YEAR").unwrap();
    assert_eq!(stmt.num_result_cols().unwrap(), 2);

    #[derive(PartialEq)]
    struct Movie {
        title: String,
        year: String,
    }

    let mut actual = Vec::new();
    while let Some(mut cursor) = stmt.fetch().unwrap() {
        actual.push(Movie {
            title: cursor.get_data(1).unwrap().unwrap(),
            year: cursor.get_data(2).unwrap().unwrap(),
        })
    }

    assert!(actual ==
            vec![Movie {
                     title: "2001: A Space Odyssey".to_owned(),
                     year: "1968".to_owned(),
                 },
                 Movie {
                     title: "Jurassic Park".to_owned(),
                     year: "1993".to_owned(),
                 }]);
}

// These tests query the results of catalog functions. These results are only likely to match the
// expectation on the travis.ci build on linux. Therefore we limit compilation and execution of
// these tests to this platform.
#[cfg(unix)]
#[test]
fn list_drivers() {
    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let drivers = environment.drivers()
        .expect("Drivers can be iterated over");
    println!("{:?}", drivers);

    let expected = ["PostgreSQL ANSI", "PostgreSQL Unicode", "SQLite", "SQLite3"];
    assert!(drivers.iter().map(|d| &d.description).eq(expected.iter()));
}

#[cfg(unix)]
#[test]
fn list_data_sources() {
    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let sources = environment.data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected = [DataSourceInfo {
                        server_name: "PostgreSQL".to_owned(),
                        description: "PostgreSQL Unicode".to_owned(),
                    },
                    DataSourceInfo {
                        server_name: "TestDataSource".to_owned(),
                        description: "Test database for odbc-rs".to_owned(),
                    };
    assert!(sources.iter().eq(expected.iter()));
}

#[cfg(unix)]
#[test]
fn list_user_data_sources() {
    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let sources = environment.user_data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected = [DataSourceInfo {
                        server_name: "PostgreSQL".to_owned(),
                        description: "PostgreSQL Unicode".to_owned(),
                    },
                    DataSourceInfo {
                        server_name: "TestDataSource".to_owned(),
                        description: "Test database for odbc-rs".to_owned(),
                    }];
    assert!(sources.iter().eq(expected.iter()));
}

#[cfg(unix)]
#[test]
fn list_system_data_sources() {
    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let sources = environment.system_data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected: [DataSourceInfo; 0] = [];
    assert!(sources.iter().eq(expected.iter()));
}
<commit_msg>add missing ']'<commit_after>extern crate odbc;
use odbc::*;

#[test]
fn list_tables() {

    let env = Environment::new().unwrap();
    let env = env.set_odbc_version_3().unwrap();
    let ds = DataSource::with_parent(&env).unwrap();
    let mut ds = ds.connect("TestDataSource", "", "").unwrap();
    // scope is required (for now) to close statement before disconnecting
    {
        let statement = Statement::with_parent(&mut ds).unwrap();
        let statement = statement.tables().unwrap();
        assert_eq!(statement.num_result_cols().unwrap(), 5);
    }
    ds.disconnect().unwrap();
}

#[test]
fn not_read_only() {

    let env = Environment::new().unwrap();
    let env = env.set_odbc_version_3().unwrap();
    let conn = DataSource::with_parent(&env).unwrap();
    let conn = conn.connect("TestDataSource", "", "").unwrap();

    assert!(!conn.read_only().unwrap());
    conn.disconnect().unwrap();
}

#[test]
fn implicit_disconnect() {

    let env = Environment::new().unwrap();
    let env = env.set_odbc_version_3().unwrap();
    let conn = DataSource::with_parent(&env).unwrap();
    conn.connect("TestDataSource", "", "").unwrap();

    // if there would be no implicit disconnect, all the drops would panic with function sequence
    // error
}

#[test]
fn invalid_connection_string() {

    let expected = if cfg!(target_os = "windows") {
        "State: IM002, Native error: 0, Message: [Microsoft][ODBC Driver Manager] Data source \
            name not found and no default driver specified"
    } else {
        "State: IM002, Native error: 0, Message: [unixODBC][Driver Manager]Data source name not \
            found, and no default driver specified"
    };

    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let conn = DataSource::with_parent(&environment).unwrap();
    let result = conn.connect_with_connection_string("bla");
    let message = format!("{}", result.err().unwrap());
    assert_eq!(expected, message);
}

#[test]
fn test_connection_string() {

    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let conn = DataSource::with_parent(&environment).unwrap();
    let conn = conn.connect_with_connection_string("dsn=TestDataSource;Uid=;Pwd=;")
        .unwrap();
    conn.disconnect().unwrap();
}

#[test]
fn test_direct_select() {
    let env = Environment::new().unwrap().set_odbc_version_3().unwrap();
    let conn = DataSource::with_parent(&env).unwrap().connect("TestDataSource", "", "").unwrap();
    let stmt = Statement::with_parent(&conn).unwrap();

    let mut stmt = stmt.exec_direct("SELECT TITLE, YEAR FROM MOVIES ORDER BY YEAR").unwrap();
    assert_eq!(stmt.num_result_cols().unwrap(), 2);

    #[derive(PartialEq)]
    struct Movie {
        title: String,
        year: String,
    }

    let mut actual = Vec::new();
    while let Some(mut cursor) = stmt.fetch().unwrap() {
        actual.push(Movie {
            title: cursor.get_data(1).unwrap().unwrap(),
            year: cursor.get_data(2).unwrap().unwrap(),
        })
    }

    assert!(actual ==
            vec![Movie {
                     title: "2001: A Space Odyssey".to_owned(),
                     year: "1968".to_owned(),
                 },
                 Movie {
                     title: "Jurassic Park".to_owned(),
                     year: "1993".to_owned(),
                 }]);
}

// These tests query the results of catalog functions. These results are only likely to match the
// expectation on the travis.ci build on linux. Therefore we limit compilation and execution of
// these tests to this platform.
#[cfg(unix)]
#[test]
fn list_drivers() {
    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let drivers = environment.drivers()
        .expect("Drivers can be iterated over");
    println!("{:?}", drivers);

    let expected = ["PostgreSQL ANSI", "PostgreSQL Unicode", "SQLite", "SQLite3"];
    assert!(drivers.iter().map(|d| &d.description).eq(expected.iter()));
}

#[cfg(unix)]
#[test]
fn list_data_sources() {
    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let sources = environment.data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected = [DataSourceInfo {
                        server_name: "PostgreSQL".to_owned(),
                        description: "PostgreSQL Unicode".to_owned(),
                    },
                    DataSourceInfo {
                        server_name: "TestDataSource".to_owned(),
                        description: "Test database for odbc-rs".to_owned(),
                    }];
    assert!(sources.iter().eq(expected.iter()));
}

#[cfg(unix)]
#[test]
fn list_user_data_sources() {
    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let sources = environment.user_data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected = [DataSourceInfo {
                        server_name: "PostgreSQL".to_owned(),
                        description: "PostgreSQL Unicode".to_owned(),
                    },
                    DataSourceInfo {
                        server_name: "TestDataSource".to_owned(),
                        description: "Test database for odbc-rs".to_owned(),
                    }];
    assert!(sources.iter().eq(expected.iter()));
}

#[cfg(unix)]
#[test]
fn list_system_data_sources() {
    let environment = Environment::new().unwrap();
    let environment = environment.set_odbc_version_3().unwrap();
    let sources = environment.system_data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected: [DataSourceInfo; 0] = [];
    assert!(sources.iter().eq(expected.iter()));
}
<|endoftext|>


<commit_before><commit_msg>Added SECS tests<commit_after>#![feature(custom_attribute, plugin)]
#![plugin(secs)]

use std::marker::PhantomData;
extern crate id;

#[secs(id)]
struct Proto<X: Send> {
    x: i8,
    y: PhantomData<X>,
}

#[test]
fn test_macro() {}

#[test]
fn test_world() {
    let _ = World::<i8>::new();
}
<|endoftext|>


<commit_before><commit_msg>16 - destructuring and guards<commit_after>fn main() {
    let pair = (2i, -2);
    // TODO ^ Try different values for `pair`

    println!("Tell me about {}", pair);
    // Match can be used to destructure a tuple
    match pair {
        // Destructure the tuple
        (x, y) if x == y => println!("These are twins"),
        // The ^ `if condition` part is a guard
        (x, y) if x + y == 0 => println!("Antimatter, kaboom!"),
        // `_` means don't bind the value to a variable
        (x, _) if x % 2 == 1 => println!("The first one is odd"),
        _ => println!("No correlation..."),
    }
}
<|endoftext|>


<commit_before><commit_msg>Improve 'State' docs.<commit_after><|endoftext|>


<commit_before><commit_msg>Hints for Deref and DerefMut traits<commit_after>struct Selector<T> {
    elements: Vec<T>,
    current: usize
}

use std::ops::{Deref, DerefMut};

impl<T> Deref for Selector<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.elements[self.current]
    }
}

impl<T> DerefMut for Selector<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.elements[self.current]
    }
}

fn main() {
    let mut s = Selector { elements: vec!['x', 'y', 'z'],
                           current: 2 };

    assert_eq!(*s, 'z');
}

<|endoftext|>


<commit_before><commit_msg>Add a test that assignment of unique boxes to locals does a copy<commit_after>fn main() {
    let i = ~mutable 1;
    // Should be a copy
    let j;
    j = i;
    *i = 2;
    *j = 3;
    assert *i == 2;
    assert *j == 3;
}<|endoftext|>


<commit_before><commit_msg>Add rust code for largest-series-product<commit_after>#![feature(ascii_ctype)]
use std::ascii::AsciiExt;

pub fn lsp(numbers: &str, length: usize) -> Result<usize, String> {
    if length == 0 {
        return Ok(1);
    }

    if numbers.len() < length {
        return Err("Invalid length".to_string());
    }

    let v = numbers
        .chars()
        .filter_map(|x| match x {
            _ if x.is_ascii_digit() => Some(x as usize - '0' as usize),
            _ => None,
        })
        .collect::<Vec<usize>>();

    if v.len() != numbers.len() {
        return Err("Non-digit found".to_string());
    }

    v.windows(length)
        .map(|x| x.iter().product())
        .max()
        .ok_or_else(|| "None".to_string())
}
<|endoftext|>


<commit_before><commit_msg>attribute<commit_after><|endoftext|>


<commit_before><commit_msg>Add initial benchmarks<commit_after>#![feature(test)]

extern crate persistent_vector;
extern crate test;

use persistent_vector::PVec;
use test::Bencher;

#[bench]
fn bench_push_get_pvec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    b.iter(|| {
        let mut v = PVec::new();
        for i in 0..n {
            v = v.push(i);
        }
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_push_get_vec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    b.iter(|| {
        let mut v = Vec::new();
        for i in 0..n {
            v.push(i);
        }
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_push_pvec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    b.iter(|| {
        let mut v = PVec::new();
        for i in 0..n {
            v = v.push(i);
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_push_vec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    b.iter(|| {
        let mut v = Vec::new();
        for i in 0..n {
            v.push(i);
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_get_pvec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    let mut v = PVec::new();
    for i in 0..n {
        v = v.push(i);
    }
    b.iter(|| {
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_get_vec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    let mut v = Vec::new();
    for i in 0..n {
        v.push(i);
    }
    b.iter(|| {
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}
<|endoftext|>


<commit_before><commit_msg>Remove unecessary clone<commit_after><|endoftext|>


<commit_before><commit_msg>Add regression test for #18883<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.

// Test that we don't ICE due to encountering unsubstituted type
// parameters when untupling FnOnce parameters during translation of
// an unboxing shim.

#![feature(unboxed_closures)]

fn main() {
    let _: Box<FnOnce<(),()>> = box move |&mut:| {};
}
<|endoftext|>


<commit_before>// FIXME: Importing std::task doesn't work under check-fast?!
use std;
import std::task;
import std::comm;
import std::uint;

fn die() {
    fail;
}

fn iloop() {
    task::unsupervise();
    let f = die;
    task::spawn(f);
}

fn main() {
    for each i in uint::range(0u, 100u) {
        let f = iloop;
        task::spawn(f);
    }
}<commit_msg>Tweak random thing to make windows build succeed. Awesome.<commit_after>// xfail-fast
use std;
import std::task;
import std::comm;
import std::uint;

fn die() {
    fail;
}

fn iloop() {
    task::unsupervise();
    let f = die;
    task::spawn(f);
}

fn main() {
    for each i in uint::range(0u, 100u) {
        let f = iloop;
        task::spawn(f);
    }
}<|endoftext|>


<commit_before>// Copyright 2018 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.

// compile-flags: -O

#![crate_type = "lib"]

use std::mem::swap;

type RGB48 = [u16; 3];

// CHECK-LABEL: @swap_rgb48
#[no_mangle]
pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) {
// CHECK-NOT: alloca
// CHECK: load i48
// CHECK: store i48
    swap(x, y)
}
<commit_msg>Only run the test on x86_64<commit_after>// Copyright 2018 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.

// compile-flags: -O
// only-x86_64

#![crate_type = "lib"]

use std::mem::swap;

type RGB48 = [u16; 3];

// CHECK-LABEL: @swap_rgb48
#[no_mangle]
pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) {
// CHECK-NOT: alloca
// CHECK: load i48
// CHECK: store i48
    swap(x, y)
}
<|endoftext|>