<commit_before>use core::mem;
use syscall::IntRegisters;

#[allow(dead_code)]
#[derive(Default)]
#[repr(packed)]
pub struct ScratchRegisters {
    pub r11: usize,
    pub r10: usize,
    pub r9: usize,
    pub r8: usize,
    pub rsi: usize,
    pub rdi: usize,
    pub rdx: usize,
    pub rcx: usize,
    pub rax: usize,
}

impl ScratchRegisters {
    pub fn dump(&self) {
        println!("RAX:   {:>016X}", { self.rax });
        println!("RCX:   {:>016X}", { self.rcx });
        println!("RDX:   {:>016X}", { self.rdx });
        println!("RDI:   {:>016X}", { self.rdi });
        println!("RSI:   {:>016X}", { self.rsi });
        println!("R8:    {:>016X}", { self.r8 });
        println!("R9:    {:>016X}", { self.r9 });
        println!("R10:   {:>016X}", { self.r10 });
        println!("R11:   {:>016X}", { self.r11 });
    }
}

#[allow(dead_code)]
#[derive(Default)]
#[repr(packed)]
pub struct PreservedRegisters {
    pub r15: usize,
    pub r14: usize,
    pub r13: usize,
    pub r12: usize,
    pub rbp: usize,
    pub rbx: usize,
}

impl PreservedRegisters {
    pub fn dump(&self) {
        println!("RBX:   {:>016X}", { self.rbx });
        println!("RBP:   {:>016X}", { self.rbp });
        println!("R12:   {:>016X}", { self.r12 });
        println!("R13:   {:>016X}", { self.r13 });
        println!("R14:   {:>016X}", { self.r14 });
        println!("R15:   {:>016X}", { self.r15 });
    }
}

#[allow(dead_code)]
#[derive(Default)]
#[repr(packed)]
pub struct IretRegisters {
    pub rip: usize,
    pub cs: usize,
    pub rflags: usize,
    // Will only be present if interrupt is raised from another
    // privilege ring
    pub rsp: usize,
    pub ss: usize
}

impl IretRegisters {
    pub fn dump(&self) {
        println!("RFLAG: {:>016X}", { self.rflags });
        println!("CS:    {:>016X}", { self.cs });
        println!("RIP:   {:>016X}", { self.rip });
    }
}

#[allow(dead_code)]
#[derive(Default)]
#[repr(packed)]
pub struct InterruptStack {
    pub fs: usize,
    pub preserved: PreservedRegisters,
    pub scratch: ScratchRegisters,
    pub iret: IretRegisters,
}

impl InterruptStack {
    pub fn dump(&self) {
        self.iret.dump();
        self.scratch.dump();
        self.preserved.dump();
        println!("FS:    {:>016X}", { self.fs });
    }
    /// Saves all registers to a struct used by the proc:
    /// scheme to read/write registers.
    pub fn save(&self, all: &mut IntRegisters) {
        all.fs = self.fs;

        all.r15 = self.preserved.r15;
        all.r14 = self.preserved.r14;
        all.r13 = self.preserved.r13;
        all.r12 = self.preserved.r12;
        all.rbp = self.preserved.rbp;
        all.rbx = self.preserved.rbx;
        all.r11 = self.scratch.r11;
        all.r10 = self.scratch.r10;
        all.r9 = self.scratch.r9;
        all.r8 = self.scratch.r8;
        all.rsi = self.scratch.rsi;
        all.rdi = self.scratch.rdi;
        all.rdx = self.scratch.rdx;
        all.rcx = self.scratch.rcx;
        all.rax = self.scratch.rax;
        all.rip = self.iret.rip;
        all.cs = self.iret.cs;
        all.rflags = self.iret.rflags;

        // Set rsp and ss:

        const CPL_MASK: usize = 0b11;

        let cs: usize;
        unsafe {
            asm!("mov $0, cs" : "=r"(cs) ::: "intel");
        }

        if self.iret.cs & CPL_MASK == cs & CPL_MASK {
            // Privilege ring didn't change, so neither did the stack
            all.rsp = self as *const Self as usize // rsp after Self was pushed to the stack
                + mem::size_of::<Self>() // disregard Self
                - mem::size_of::<usize>() * 2; // well, almost: rsp and ss need to be excluded as they aren't present
            unsafe {
                asm!("mov $0, ss" : "=r"(all.ss) ::: "intel");
            }
        } else {
            all.rsp = self.iret.rsp;
            all.ss = self.iret.ss;
        }
    }
    /// Loads all registers from a struct used by the proc:
    /// scheme to read/write registers.
    pub fn load(&mut self, all: &IntRegisters) {
        // TODO: Which of these should be allowed to change?

        // self.fs = all.fs;
        self.preserved.r15 = all.r15;
        self.preserved.r14 = all.r14;
        self.preserved.r13 = all.r13;
        self.preserved.r12 = all.r12;
        self.preserved.rbp = all.rbp;
        self.preserved.rbx = all.rbx;
        self.scratch.r11 = all.r11;
        self.scratch.r10 = all.r10;
        self.scratch.r9 = all.r9;
        self.scratch.r8 = all.r8;
        self.scratch.rsi = all.rsi;
        self.scratch.rdi = all.rdi;
        self.scratch.rdx = all.rdx;
        self.scratch.rcx = all.rcx;
        self.scratch.rax = all.rax;
        self.iret.rip = all.rip;

        // These should probably be restricted
        // self.iret.cs = all.cs;
        // self.iret.rflags = all.eflags;
    }
    /// Enables the "Trap Flag" in the FLAGS register, causing the CPU
    /// to send a Debug exception after the next instruction. This is
    /// used for singlestep in the proc: scheme.
    pub fn set_singlestep(&mut self, enabled: bool) {
        if enabled {
            self.iret.rflags |= 1 << 8;
        } else {
            self.iret.rflags &= !(1 << 8);
        }
    }
    /// Checks if the trap flag is enabled, see `set_singlestep`
    pub fn is_singlestep(&self) -> bool {
        self.iret.rflags & 1 << 8 == 1 << 8
    }
}

#[allow(dead_code)]
#[derive(Default)]
#[repr(packed)]
pub struct InterruptErrorStack {
    pub code: usize,
    pub inner: InterruptStack,
}

impl InterruptErrorStack {
    pub fn dump(&self) {
        println!("CODE:  {:>016X}", { self.code });
        self.inner.dump();
    }
}

#[macro_export]
macro_rules! intel_asm {
    ($($strings:expr,)+) => {
        global_asm!(concat!(
            ".intel_syntax noprefix\n",
            $($strings),+,
            ".att_syntax prefix\n",
        ));
    };
}
#[macro_export]
macro_rules! function {
    ($name:ident => { $($body:expr,)+ }) => {
        intel_asm!(
            ".global ", stringify!($name), "\n",
            stringify!($name), ":\n",
            $($body,)+
        );
        extern "C" {
            pub fn $name();
        }
    };
}

#[macro_export]
macro_rules! push_scratch {
    () => { "
        // Push scratch registers
        push rcx
        push rdx
        push rdi
        push rsi
        push r8
        push r9
        push r10
        push r11
    " };
}
#[macro_export]
macro_rules! pop_scratch {
    () => { "
        // Pop scratch registers
        pop r11
        pop r10
        pop r9
        pop r8
        pop rsi
        pop rdi
        pop rdx
        pop rcx
        pop rax
    " };
}

#[macro_export]
macro_rules! push_preserved {
    () => { "
        // Push preserved registers
        push rbx
        push rbp
        push r12
        push r13
        push r14
        push r15
    " };
}
#[macro_export]
macro_rules! pop_preserved {
    () => { "
        // Pop preserved registers
        pop r15
        pop r14
        pop r13
        pop r12
        pop rbp
        pop rbx
    " };
}

#[macro_export]
macro_rules! push_fs {
    () => { "
        // Push fs
        push fs

        // Load kernel tls
        // We can't load the value directly into `fs`. We also can't use `rax`
        // as the temporary value, as during errors that's already used for the
        // error code.
        mov rbx, 0x18
        mov fs, bx
    " };
}
#[macro_export]
macro_rules! pop_fs {
    () => { "
        // Pop fs
        pop fs
    " };
}

#[macro_export]
macro_rules! interrupt_stack {
    ($name:ident, |$stack:ident| $code:block) => {
        paste::item! {
            #[no_mangle]
            unsafe extern "C" fn [<__interrupt_ $name>](stack: *mut $crate::arch::x86_64::interrupt::InterruptStack) {
                // This inner function is needed because macros are buggy:
                // https://github.com/dtolnay/paste/issues/7
                #[inline(always)]
                unsafe fn inner($stack: &mut $crate::arch::x86_64::interrupt::InterruptStack) {
                    $code
                }
                let _guard = $crate::ptrace::set_process_regs(stack);
                inner(&mut *stack);
            }

            function!($name => {
                // Backup all userspace registers to stack
                "push rax\n",
                push_scratch!(),
                push_preserved!(),
                push_fs!(),

                // TODO: Map PTI
                // $crate::arch::x86_64::pti::map();

                // Call inner function with pointer to stack
                "mov rdi, rsp\n",
                "call __interrupt_", stringify!($name), "\n",

                // TODO: Unmap PTI
                // $crate::arch::x86_64::pti::unmap();

                // Restore all userspace registers
                pop_fs!(),
                pop_preserved!(),
                pop_scratch!(),

                "iretq\n",
            });
        }
    };
}

#[macro_export]
macro_rules! interrupt {
    ($name:ident, || $code:block) => {
        paste::item! {
            #[no_mangle]
            unsafe extern "C" fn [<__interrupt_ $name>]() {
                $code
            }

            function!($name => {
                // Backup all userspace registers to stack
                "push rax\n",
                push_scratch!(),
                push_fs!(),

                // TODO: Map PTI
                // $crate::arch::x86_64::pti::map();

                // Call inner function with pointer to stack
                "call __interrupt_", stringify!($name), "\n",

                // TODO: Unmap PTI
                // $crate::arch::x86_64::pti::unmap();

                // Restore all userspace registers
                pop_fs!(),
                pop_scratch!(),

                "iretq\n",
            });
        }
    };
}

#[macro_export]
macro_rules! interrupt_error {
    ($name:ident, |$stack:ident| $code:block) => {
        paste::item! {
            #[no_mangle]
            unsafe extern "C" fn [<__interrupt_ $name>](stack: *mut $crate::arch::x86_64::interrupt::handler::InterruptErrorStack) {
                // This inner function is needed because macros are buggy:
                // https://github.com/dtolnay/paste/issues/7
                unsafe fn inner($stack: &mut $crate::arch::x86_64::interrupt::handler::InterruptErrorStack) {
                    $code
                }
                let _guard = $crate::ptrace::set_process_regs(&mut (*stack).inner);
                inner(&mut *stack);
            }

            function!($name => {
                // Move rax into code's place, put code in last instead (to be
                // compatible with InterruptStack)
                "xchg [rsp], rax\n",

                // Push all userspace registers
                push_scratch!(),
                push_preserved!(),
                push_fs!(),

                // Put code in, it's now in rax
                "push rax\n",

                // TODO: Map PTI
                // $crate::arch::x86_64::pti::map();

                // Call inner function with pointer to stack
                "mov rdi, rsp\n",
                "call __interrupt_", stringify!($name), "\n",

                // TODO: Unmap PTI
                // $crate::arch::x86_64::pti::unmap();

                // Pop code
                "add rsp, 8\n",

                // Restore all userspace registers
                pop_fs!(),
                pop_preserved!(),
                pop_scratch!(),

                "iretq\n",
            });
        }
    };
}
<commit_msg>Fix random userspace page faults<commit_after>use core::mem;
use syscall::IntRegisters;

#[allow(dead_code)]
#[derive(Default)]
#[repr(packed)]
pub struct ScratchRegisters {
    pub r11: usize,
    pub r10: usize,
    pub r9: usize,
    pub r8: usize,
    pub rsi: usize,
    pub rdi: usize,
    pub rdx: usize,
    pub rcx: usize,
    pub rax: usize,
}

impl ScratchRegisters {
    pub fn dump(&self) {
        println!("RAX:   {:>016X}", { self.rax });
        println!("RCX:   {:>016X}", { self.rcx });
        println!("RDX:   {:>016X}", { self.rdx });
        println!("RDI:   {:>016X}", { self.rdi });
        println!("RSI:   {:>016X}", { self.rsi });
        println!("R8:    {:>016X}", { self.r8 });
        println!("R9:    {:>016X}", { self.r9 });
        println!("R10:   {:>016X}", { self.r10 });
        println!("R11:   {:>016X}", { self.r11 });
    }
}

#[allow(dead_code)]
#[derive(Default)]
#[repr(packed)]
pub struct PreservedRegisters {
    pub r15: usize,
    pub r14: usize,
    pub r13: usize,
    pub r12: usize,
    pub rbp: usize,
    pub rbx: usize,
}

impl PreservedRegisters {
    pub fn dump(&self) {
        println!("RBX:   {:>016X}", { self.rbx });
        println!("RBP:   {:>016X}", { self.rbp });
        println!("R12:   {:>016X}", { self.r12 });
        println!("R13:   {:>016X}", { self.r13 });
        println!("R14:   {:>016X}", { self.r14 });
        println!("R15:   {:>016X}", { self.r15 });
    }
}

#[allow(dead_code)]
#[derive(Default)]
#[repr(packed)]
pub struct IretRegisters {
    pub rip: usize,
    pub cs: usize,
    pub rflags: usize,
    // Will only be present if interrupt is raised from another
    // privilege ring
    pub rsp: usize,
    pub ss: usize
}

impl IretRegisters {
    pub fn dump(&self) {
        println!("RFLAG: {:>016X}", { self.rflags });
        println!("CS:    {:>016X}", { self.cs });
        println!("RIP:   {:>016X}", { self.rip });
    }
}

#[allow(dead_code)]
#[derive(Default)]
#[repr(packed)]
pub struct InterruptStack {
    pub fs: usize,
    pub preserved: PreservedRegisters,
    pub scratch: ScratchRegisters,
    pub iret: IretRegisters,
}

impl InterruptStack {
    pub fn dump(&self) {
        self.iret.dump();
        self.scratch.dump();
        self.preserved.dump();
        println!("FS:    {:>016X}", { self.fs });
    }
    /// Saves all registers to a struct used by the proc:
    /// scheme to read/write registers.
    pub fn save(&self, all: &mut IntRegisters) {
        all.fs = self.fs;

        all.r15 = self.preserved.r15;
        all.r14 = self.preserved.r14;
        all.r13 = self.preserved.r13;
        all.r12 = self.preserved.r12;
        all.rbp = self.preserved.rbp;
        all.rbx = self.preserved.rbx;
        all.r11 = self.scratch.r11;
        all.r10 = self.scratch.r10;
        all.r9 = self.scratch.r9;
        all.r8 = self.scratch.r8;
        all.rsi = self.scratch.rsi;
        all.rdi = self.scratch.rdi;
        all.rdx = self.scratch.rdx;
        all.rcx = self.scratch.rcx;
        all.rax = self.scratch.rax;
        all.rip = self.iret.rip;
        all.cs = self.iret.cs;
        all.rflags = self.iret.rflags;

        // Set rsp and ss:

        const CPL_MASK: usize = 0b11;

        let cs: usize;
        unsafe {
            asm!("mov $0, cs" : "=r"(cs) ::: "intel");
        }

        if self.iret.cs & CPL_MASK == cs & CPL_MASK {
            // Privilege ring didn't change, so neither did the stack
            all.rsp = self as *const Self as usize // rsp after Self was pushed to the stack
                + mem::size_of::<Self>() // disregard Self
                - mem::size_of::<usize>() * 2; // well, almost: rsp and ss need to be excluded as they aren't present
            unsafe {
                asm!("mov $0, ss" : "=r"(all.ss) ::: "intel");
            }
        } else {
            all.rsp = self.iret.rsp;
            all.ss = self.iret.ss;
        }
    }
    /// Loads all registers from a struct used by the proc:
    /// scheme to read/write registers.
    pub fn load(&mut self, all: &IntRegisters) {
        // TODO: Which of these should be allowed to change?

        // self.fs = all.fs;
        self.preserved.r15 = all.r15;
        self.preserved.r14 = all.r14;
        self.preserved.r13 = all.r13;
        self.preserved.r12 = all.r12;
        self.preserved.rbp = all.rbp;
        self.preserved.rbx = all.rbx;
        self.scratch.r11 = all.r11;
        self.scratch.r10 = all.r10;
        self.scratch.r9 = all.r9;
        self.scratch.r8 = all.r8;
        self.scratch.rsi = all.rsi;
        self.scratch.rdi = all.rdi;
        self.scratch.rdx = all.rdx;
        self.scratch.rcx = all.rcx;
        self.scratch.rax = all.rax;
        self.iret.rip = all.rip;

        // These should probably be restricted
        // self.iret.cs = all.cs;
        // self.iret.rflags = all.eflags;
    }
    /// Enables the "Trap Flag" in the FLAGS register, causing the CPU
    /// to send a Debug exception after the next instruction. This is
    /// used for singlestep in the proc: scheme.
    pub fn set_singlestep(&mut self, enabled: bool) {
        if enabled {
            self.iret.rflags |= 1 << 8;
        } else {
            self.iret.rflags &= !(1 << 8);
        }
    }
    /// Checks if the trap flag is enabled, see `set_singlestep`
    pub fn is_singlestep(&self) -> bool {
        self.iret.rflags & 1 << 8 == 1 << 8
    }
}

#[allow(dead_code)]
#[derive(Default)]
#[repr(packed)]
pub struct InterruptErrorStack {
    pub code: usize,
    pub inner: InterruptStack,
}

impl InterruptErrorStack {
    pub fn dump(&self) {
        println!("CODE:  {:>016X}", { self.code });
        self.inner.dump();
    }
}

#[macro_export]
macro_rules! intel_asm {
    ($($strings:expr,)+) => {
        global_asm!(concat!(
            ".intel_syntax noprefix\n",
            $($strings),+,
            ".att_syntax prefix\n",
        ));
    };
}
#[macro_export]
macro_rules! function {
    ($name:ident => { $($body:expr,)+ }) => {
        intel_asm!(
            ".global ", stringify!($name), "\n",
            stringify!($name), ":\n",
            $($body,)+
        );
        extern "C" {
            pub fn $name();
        }
    };
}

#[macro_export]
macro_rules! push_scratch {
    () => { "
        // Push scratch registers
        push rcx
        push rdx
        push rdi
        push rsi
        push r8
        push r9
        push r10
        push r11
    " };
}
#[macro_export]
macro_rules! pop_scratch {
    () => { "
        // Pop scratch registers
        pop r11
        pop r10
        pop r9
        pop r8
        pop rsi
        pop rdi
        pop rdx
        pop rcx
        pop rax
    " };
}

#[macro_export]
macro_rules! push_preserved {
    () => { "
        // Push preserved registers
        push rbx
        push rbp
        push r12
        push r13
        push r14
        push r15
    " };
}
#[macro_export]
macro_rules! pop_preserved {
    () => { "
        // Pop preserved registers
        pop r15
        pop r14
        pop r13
        pop r12
        pop rbp
        pop rbx
    " };
}

#[macro_export]
macro_rules! push_fs {
    () => { "
        // Push fs
        push fs

        // Load kernel tls
        //
        // NOTE: We can't load the value directly into `fs`. So we need to use a
        // scratch register (as preserved registers aren't backed up by the
        // interrupt! macro) to store it. We also can't use `rax` as the temporary
        // value, as during errors that's already used for the error code.
        mov rcx, 0x18
        mov fs, cx
    " };
}
#[macro_export]
macro_rules! pop_fs {
    () => { "
        // Pop fs
        pop fs
    " };
}

#[macro_export]
macro_rules! interrupt_stack {
    ($name:ident, |$stack:ident| $code:block) => {
        paste::item! {
            #[no_mangle]
            unsafe extern "C" fn [<__interrupt_ $name>](stack: *mut $crate::arch::x86_64::interrupt::InterruptStack) {
                // This inner function is needed because macros are buggy:
                // https://github.com/dtolnay/paste/issues/7
                #[inline(always)]
                unsafe fn inner($stack: &mut $crate::arch::x86_64::interrupt::InterruptStack) {
                    $code
                }
                let _guard = $crate::ptrace::set_process_regs(stack);
                inner(&mut *stack);
            }

            function!($name => {
                // Backup all userspace registers to stack
                "push rax\n",
                push_scratch!(),
                push_preserved!(),
                push_fs!(),

                // TODO: Map PTI
                // $crate::arch::x86_64::pti::map();

                // Call inner function with pointer to stack
                "mov rdi, rsp\n",
                "call __interrupt_", stringify!($name), "\n",

                // TODO: Unmap PTI
                // $crate::arch::x86_64::pti::unmap();

                // Restore all userspace registers
                pop_fs!(),
                pop_preserved!(),
                pop_scratch!(),

                "iretq\n",
            });
        }
    };
}

#[macro_export]
macro_rules! interrupt {
    ($name:ident, || $code:block) => {
        paste::item! {
            #[no_mangle]
            unsafe extern "C" fn [<__interrupt_ $name>]() {
                $code
            }

            function!($name => {
                // Backup all userspace registers to stack
                "push rax\n",
                push_scratch!(),
                push_fs!(),

                // TODO: Map PTI
                // $crate::arch::x86_64::pti::map();

                // Call inner function with pointer to stack
                "call __interrupt_", stringify!($name), "\n",

                // TODO: Unmap PTI
                // $crate::arch::x86_64::pti::unmap();

                // Restore all userspace registers
                pop_fs!(),
                pop_scratch!(),

                "iretq\n",
            });
        }
    };
}

#[macro_export]
macro_rules! interrupt_error {
    ($name:ident, |$stack:ident| $code:block) => {
        paste::item! {
            #[no_mangle]
            unsafe extern "C" fn [<__interrupt_ $name>](stack: *mut $crate::arch::x86_64::interrupt::handler::InterruptErrorStack) {
                // This inner function is needed because macros are buggy:
                // https://github.com/dtolnay/paste/issues/7
                unsafe fn inner($stack: &mut $crate::arch::x86_64::interrupt::handler::InterruptErrorStack) {
                    $code
                }
                let _guard = $crate::ptrace::set_process_regs(&mut (*stack).inner);
                inner(&mut *stack);
            }

            function!($name => {
                // Move rax into code's place, put code in last instead (to be
                // compatible with InterruptStack)
                "xchg [rsp], rax\n",

                // Push all userspace registers
                push_scratch!(),
                push_preserved!(),
                push_fs!(),

                // Put code in, it's now in rax
                "push rax\n",

                // TODO: Map PTI
                // $crate::arch::x86_64::pti::map();

                // Call inner function with pointer to stack
                "mov rdi, rsp\n",
                "call __interrupt_", stringify!($name), "\n",

                // TODO: Unmap PTI
                // $crate::arch::x86_64::pti::unmap();

                // Pop code
                "add rsp, 8\n",

                // Restore all userspace registers
                pop_fs!(),
                pop_preserved!(),
                pop_scratch!(),

                "iretq\n",
            });
        }
    };
}
<|endoftext|>


<commit_before>use serialize::json::{Json};
use anymap::AnyMap;
use std::os;

use server::{Request, Response};
use errors::{Error, FileError};
use middleware::{Application, HandleResult};
use framework::endpoint::Endpoint;
use framework::media::Media;
use server_backend::status;
use server_backend::mime;
use server_backend::header::{Header, HeaderFormat};
use server_backend::header::common::{ContentType, Location};
use {Extensible};

pub struct Client<'a> {
    pub app: &'a Application,
    pub endpoint: &'a Endpoint,
    pub request: &'a mut Request,
    pub media: &'a Media,
    pub ext: AnyMap,
    pub response: Response
}

pub type ClientResult<'a> = HandleResult<Client<'a>>;

impl<'a> Client<'a> {

    pub fn new(app: &'a Application, endpoint: &'a Endpoint, request: &'a mut Request, media: &'a Media) -> Client<'a> {
        Client {
            app: app,
            endpoint: endpoint,
            request: request,
            media: media,
            ext: AnyMap::new(),
            response: Response::new(status::Ok)
        }
    }

    //
    // Work with status
    //

    pub fn status(&mut self) -> status::StatusCode {
        self.response.status
    }

    pub fn set_status(&mut self, status: status::StatusCode) -> &mut Client<'a> {
        self.response.status = status;
        self
    }

    pub fn unauthorized(&mut self) -> &mut Client<'a> {
        self.response.status = status::Unauthorized;
        self
    }

    pub fn forbidden(&mut self) -> &mut Client<'a> {
        self.response.status = status::Forbidden;
        self
    }

    pub fn not_found(&mut self) -> &mut Client<'a> {
        self.response.status = status::NotFound;
        self
    }

    pub fn internal_server_error(&mut self) -> &mut Client<'a> {
        self.response.status = status::InternalServerError;
        self
    }

    pub fn not_implemented(&mut self) -> &mut Client<'a> {
        self.response.status = status::NotImplemented;
        self
    }

    //

    pub fn set_header<H: Header + HeaderFormat>(&mut self, header: H) -> &mut Client<'a> {
        self.response.set_header(header);
        self
    }

    pub fn set_json_content_type(&mut self) -> &mut Client<'a> {
        self.set_header(ContentType(mime::Mime(mime::Application, mime::Json, vec![])));
        self
    }

    pub fn set_content_type(&mut self, mime: mime::Mime) -> &mut Client<'a> {
        self.set_header(ContentType(mime));
        self
    }

    pub fn error<T: Error>(self, error: T) -> ClientResult<'a> {
        Err(box error as Box<Error>)
    }

    pub fn json(mut self, result: &Json) -> ClientResult<'a> {
        self.set_json_content_type();
        self.response.push_string(result.to_string());

        Ok(self)
    }

    pub fn text(mut self, result: String) -> ClientResult<'a> {
        self.response.push_string(result);

        Ok(self)
    }

    pub fn file(mut self, path: &Path) -> ClientResult<'a> {
       match self.response.push_file(&os::make_absolute(path)) {
            Ok(()) => Ok(self),
            Err(err) => {
                return Err(box FileError(err) as Box<Error>);
            }
        }
    }

    pub fn redirect(mut self, to: &str) -> ClientResult<'a> {
        self.set_status(status::Found);
        self.set_header(Location(to.to_string()));

        Ok(self)
    }

    pub fn permanent_redirect(mut self, to: &str) -> ClientResult<'a> {
        self.set_status(status::MovedPermanently);
        self.set_header(Location(to.to_string()));

        Ok(self)
    }

    pub fn move_response(self) -> Response {
        self.response
    }

    pub fn ext(&self) -> &AnyMap {
        &self.ext
    }

    pub fn ext_mut(&mut self) -> &mut AnyMap {
        &mut self.ext
    }

}

impl<'a> Extensible for Client<'a> {
    fn ext(&self) -> &::anymap::AnyMap { &self.ext }
    fn ext_mut(&mut self) -> &mut ::anymap::AnyMap { &mut self.ext }
}<commit_msg>Revert "Allow to chain `Client` methods"<commit_after>use serialize::json::{Json};
use anymap::AnyMap;
use std::os;

use server::{Request, Response};
use errors::{Error, FileError};
use middleware::{Application, HandleResult};
use framework::endpoint::Endpoint;
use framework::media::Media;
use server_backend::status;
use server_backend::mime;
use server_backend::header::{Header, HeaderFormat};
use server_backend::header::common::{ContentType, Location};
use {Extensible};

pub struct Client<'a> {
    pub app: &'a Application,
    pub endpoint: &'a Endpoint,
    pub request: &'a mut Request,
    pub media: &'a Media,
    pub ext: AnyMap,
    pub response: Response
}

pub type ClientResult<'a> = HandleResult<Client<'a>>;

impl<'a> Client<'a> {

    pub fn new(app: &'a Application, endpoint: &'a Endpoint, request: &'a mut Request, media: &'a Media) -> Client<'a> {
        Client {
            app: app,
            endpoint: endpoint,
            request: request,
            media: media,
            ext: AnyMap::new(),
            response: Response::new(status::Ok)
        }
    }

    //
    // Work with status
    //

    pub fn status(&mut self) -> status::StatusCode {
        self.response.status
    }

    pub fn set_status(&mut self, status: status::StatusCode) {
        self.response.status = status;
    }

    pub fn unauthorized(&mut self) {
        self.response.status = status::Unauthorized;
    }

    pub fn forbidden(&mut self) {
        self.response.status = status::Forbidden;
    }

    pub fn not_found(&mut self) {
        self.response.status = status::NotFound;
    }

    pub fn internal_server_error(&mut self) {
        self.response.status = status::InternalServerError;
    }

    pub fn not_implemented(&mut self) {
        self.response.status = status::NotImplemented;
    }

    //

    pub fn set_header<H: Header + HeaderFormat>(&mut self, header: H) {
        self.response.set_header(header);
    }

    pub fn set_json_content_type(&mut self) {
        self.set_header(ContentType(mime::Mime(mime::Application, mime::Json, vec![])));
    }

    pub fn set_content_type(&mut self, mime: mime::Mime) {
        self.set_header(ContentType(mime));
    }

    pub fn error<T: Error>(self, error: T) -> ClientResult<'a> {
        Err(box error as Box<Error>)
    }

    pub fn json(mut self, result: &Json) -> ClientResult<'a> {
        self.set_json_content_type();
        self.response.push_string(result.to_string());

        Ok(self)
    }

    pub fn text(mut self, result: String) -> ClientResult<'a> {
        self.response.push_string(result);

        Ok(self)
    }

    pub fn file(mut self, path: &Path) -> ClientResult<'a> {
       match self.response.push_file(&os::make_absolute(path)) {
            Ok(()) => Ok(self),
            Err(err) => {
                return Err(box FileError(err) as Box<Error>);
            }
        }
    }

    pub fn redirect(mut self, to: &str) -> ClientResult<'a> {
        self.set_status(status::Found);
        self.set_header(Location(to.to_string()));

        Ok(self)
    }

    pub fn permanent_redirect(mut self, to: &str) -> ClientResult<'a> {
        self.set_status(status::MovedPermanently);
        self.set_header(Location(to.to_string()));

        Ok(self)
    }

    pub fn move_response(self) -> Response {
        self.response
    }

    pub fn ext(&self) -> &AnyMap {
        &self.ext
    }

    pub fn ext_mut(&mut self) -> &mut AnyMap {
        &mut self.ext
    }

}

impl<'a> Extensible for Client<'a> {
    fn ext(&self) -> &::anymap::AnyMap { &self.ext }
    fn ext_mut(&mut self) -> &mut ::anymap::AnyMap { &mut self.ext }
}<|endoftext|>


<commit_before>#![feature(asm)]

// External libraries
extern crate dylib;
use dylib::DynamicLibrary;

use std::path::Path;
use std::mem::transmute;

use std::process::Command;
use std::thread;

use std::sync::atomic::{AtomicBool, Ordering, AtomicPtr};
use std::option::Option;

use std::sync::{Arc, RwLock};
use std::fmt;

// Internal libraries
extern crate gr;
use gr::*;

#[derive(Clone)]
enum OpType {
    Func(String),
    Const(usize),
    Var(usize),
    UVar(usize),
    Op(String),
    Pow(i32)
}

impl fmt::Display for OpType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        let outstring = match self {
            &OpType::Func(ref s) => format!("f{}", s),
            &OpType::Const(i) => format!("c{}", i),
            &OpType::Var(i) => format!("i{}", i),
            &OpType::UVar(i) => format!("v{}", i),
            &OpType::Op(ref s) => format!("o{}", s),
            &OpType::Pow(i) => format!("p{}", i)
        };
        write!(f, "{}", outstring)
    }

}

#[derive(Clone)]
pub struct FuncObj {
    handle: Arc<RwLock<Option<DynamicLibrary>>>,
    user_vars: Vec<GI>,
    constants: Vec<GI>,
    instructions: Vec<OpType>,
    switched: Arc<AtomicBool>,
    function: Arc<AtomicPtr<fn(&Vec<GI>, &Vec<GI>) -> (GI, Option<Vec<GI>>)>>,

}

unsafe impl Sync for FuncObj {}
unsafe impl Send for FuncObj {}
fn dummy(_x: &Vec<GI>, _c: &Vec<GI>) -> (GI, Option<Vec<GI>>) {
    (GI::new_c("1.0").unwrap(), None)
}

impl FuncObj {
    pub fn call(&self, _x: &Vec<GI>) -> (GI, Option<Vec<GI>>) {
        if self.switched.load(Ordering::Acquire) {
            let real_func = unsafe{
                std::mem::transmute::<*mut fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>),
                                      fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>)>(
                    (self.function.load(Ordering::Acquire)))};
            real_func(_x, &self.constants)
        }
        else {
            self.interpreted(_x, &self.constants)
        }
    }

    fn set(&self, f: fn(&Vec<GI>,&Vec<GI>) -> (GI, Option<Vec<GI>>), handle: DynamicLibrary) {
        // This FuncObj owns the handle from the dynamic lib as the lifetime of
        // f is tied to the lifetime of the handle.
        self.function.store(unsafe{std::mem::transmute::<fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>),
                                                         *mut fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>)>(f)}, Ordering::Release);
        let mut h = self.handle.write().unwrap();
        *h = Some(handle);
        self.switched.store(true, Ordering::Release);
    }

    fn interpreted(&self, _x: &Vec<GI>, _c: &Vec<GI>) -> (GI, Option<Vec<GI>>) {
        let mut stack: Vec<GI> = Vec::new();
        for inst in &self.instructions {
            match inst {
                &OpType::Func(ref s) => {
                    let op = stack.last_mut().unwrap();
                    match s.as_str() {
                        "abs" => op.abs(),
                        "sin" => op.sin(),
                        "asin"=> op.asin(),
                        "cos" => op.cos(),
                        "acos" => op.acos(),
                        "tan" => op.tan(),
                        "atan" => op.atan(),
                        "exp" => op.exp(),
                        "log" => op.log(),
                        "neg" => op.neg(),
                        "sqrt" => op.sqrt(),
                        "sinh" => op.sinh(),
                        "cosh" => op.cosh(),
                        "tanh" => op.tanh(),
                        "asinh" => op.asinh(),
                        "acosh" => op.acosh(),
                        "atanh" => op.atanh(),
                        _     => unreachable!()
                    };
                },
                &OpType::Const(i) => {
                    stack.push(self.constants[i]);
                },
                &OpType::Var(i) => {
                    stack.push(_x[i]);
                },
                &OpType::UVar(i) => {
                    stack.push(self.user_vars[i]);
                },
                &OpType::Op(ref s) => {
                    let right = stack.pop().unwrap();
                    let left = stack.last_mut().unwrap();
                    match s.as_str() {
                        "+" => left.add(right),
                        "-" => left.sub(right),
                        "*" => left.mul(right),
                        "/" => left.div(right),
                        "p" => left.powi(right),
                        _   => unreachable!()
                    };
                },
                &OpType::Pow(exp) => {
                    let arg = stack.last_mut().unwrap();
                    arg.pow(exp);
                }
            }
        }
        (stack[0], None)
    }

    pub fn new(consts: &Vec<GI>, instructions: &String, debug: bool, suffix: String) -> FuncObj {
        let mut insts = vec![];

        for inst in instructions.split(',') {
            let dummy = inst.trim().to_string();
            let (first, rest) = dummy.split_at(1);
            insts.push(match first {
                "c" => OpType::Const(rest.to_string().parse::<usize>().unwrap()),
                "i" => OpType::Var(rest.to_string().parse::<usize>().unwrap()),
                "v" => OpType::UVar(rest.to_string().parse::<usize>().unwrap()),
                "o" => OpType::Op(rest.to_string()),
                "f" => OpType::Func(rest.to_string()),
                "p" => OpType::Pow(rest.to_string().parse::<i32>().unwrap()),
                _   => panic!()
            });
        }
        let result =
            FuncObj{handle: Arc::new(RwLock::new(Option::None)),
                user_vars: vec![],
                constants: consts.clone(),
                instructions: insts,
                switched: Arc::new(AtomicBool::new(false)),
                function: Arc::new(AtomicPtr::new(unsafe{std::mem::transmute::<fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>),
                                                                               *mut fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>)>(dummy)}))
        };

        {
            let fo_c = result.clone();
            thread::spawn(move || {
                &fo_c.compile(debug, &suffix);
            })
        };
        result
    }

    fn compile(&self, debug: bool, suffix: &String) {
        let mut process = Command::new("build_func.sh");
        if debug {
            println!("compile suffix: {}", suffix);
        }
        let ignore = process.arg(suffix.clone()).output()
            .unwrap_or_else(|e| {panic!("Could not compile: {}", e)});

        if !ignore.status.success() {
            panic!("Could not compile: {}\n----\n{}", String::from_utf8(ignore.stdout).unwrap(),
                   String::from_utf8(ignore.stderr).unwrap());
        }

        DynamicLibrary::prepend_search_path(Path::new("./.compiled"));
        let dylib: String = "libfunc_".to_string() + suffix + ".so".into();

        let f = match DynamicLibrary::open(Some(Path::new(&dylib)))
        {
            Ok(lib) => lib,
            Err(err) => panic!("Could not load library: {}", err)
        };
        let g = unsafe{match f.symbol("gelpia_func") {
            Ok(func) => transmute::<*mut u32, fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>)>(func),
            Err(err) => panic!("Could not load function: {}", err),
        }};

        self.set(g, f);
    }
}

#[test]
fn test1() {
    let constants = vec![GI::new_c("1"), GI::new_c("2"), GI::new_c("3")];
    let f = FuncObj::new(&constants,
                         &"c0,c1,o-,c2,o+".to_string());
    let expected = ((GI::new_c("1") - GI::new_c("2")) + GI::new_c("3")).to_string();
    assert!(f.call(&vec![]).to_string() == expected);
}

#[test]
fn test2() {
    let consts = vec![GI::new_c("1"), GI::new_c("2"), GI::new_c("3")];
    let f = FuncObj::new(&consts,
                         &"c0,fsin,c1,o*,fcos,c2,o/".to_string());
    let expected = cos(sin(consts[0]) * consts[1])/consts[2];
    assert!(f.call(&vec![]).to_string() == expected.to_string());
}

#[test]
fn sum_inputs() {
    let consts = vec![];
    let v = vec![GI::new_d(1.0, 1.0), GI::new_d(1.0, 2.0), GI::new_d(1.0, 3.0),
                 GI::new_d(1.0, 4.0), GI::new_d(1.0, 5.0), GI::new_d(1.0, 6.0)];
    let f = FuncObj::new(&consts,
                         &"i0,i1, o+, i2, o+, i3, o+, i4, o+, i5, o+".to_string());
    let expected = (v[0] + v[1] + v[2] + v[3] + v[4] + v[5]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test3() {
    let consts = vec![GI::new_c("0.1")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fsin".to_string());
    let expected = sin(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test4() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fabs".to_string());
    let expected = abs(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test5() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fcos".to_string());
    let expected = cos(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test6() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, ftan".to_string());
    let expected = tan(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test7() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fexp".to_string());
    let expected = exp(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test8() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fneg".to_string());
    let expected = (-consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test9() {
    let consts = vec![GI::new_c("[0.1, .2]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, flog".to_string());
    let expected = log(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
#[test]
fn test10() {
    let consts = vec![GI::new_c("[2.0, 3.0]"),
                      GI::new_c("[1.5, 2.5]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                         &"c0, c1, op".to_string());
    let expected = powi(consts[0], consts[1]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
#[test]
fn test_power() {
    let consts = vec![GI::new_c("[2.0, 3.0]"),
                      GI::new_c("[1.5, 2.5]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                         &"c0, p-1, c1, p2, o+".to_string());
    let expected = (pow(consts[0], -1) + pow(consts[1], 2)).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
<commit_msg>Integrated floor_power2 and sym_interval into interpreter<commit_after>#![feature(asm)]

// External libraries
extern crate dylib;
use dylib::DynamicLibrary;

use std::path::Path;
use std::mem::transmute;

use std::process::Command;
use std::thread;

use std::sync::atomic::{AtomicBool, Ordering, AtomicPtr};
use std::option::Option;

use std::sync::{Arc, RwLock};
use std::fmt;

// Internal libraries
extern crate gr;
use gr::*;

#[derive(Clone)]
enum OpType {
    Func(String),
    Const(usize),
    Var(usize),
    UVar(usize),
    Op(String),
    Pow(i32)
}

impl fmt::Display for OpType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        let outstring = match self {
            &OpType::Func(ref s) => format!("f{}", s),
            &OpType::Const(i) => format!("c{}", i),
            &OpType::Var(i) => format!("i{}", i),
            &OpType::UVar(i) => format!("v{}", i),
            &OpType::Op(ref s) => format!("o{}", s),
            &OpType::Pow(i) => format!("p{}", i)
        };
        write!(f, "{}", outstring)
    }

}

#[derive(Clone)]
pub struct FuncObj {
    handle: Arc<RwLock<Option<DynamicLibrary>>>,
    user_vars: Vec<GI>,
    constants: Vec<GI>,
    instructions: Vec<OpType>,
    switched: Arc<AtomicBool>,
    function: Arc<AtomicPtr<fn(&Vec<GI>, &Vec<GI>) -> (GI, Option<Vec<GI>>)>>,

}

unsafe impl Sync for FuncObj {}
unsafe impl Send for FuncObj {}
fn dummy(_x: &Vec<GI>, _c: &Vec<GI>) -> (GI, Option<Vec<GI>>) {
    (GI::new_c("1.0").unwrap(), None)
}

impl FuncObj {
    pub fn call(&self, _x: &Vec<GI>) -> (GI, Option<Vec<GI>>) {
        if self.switched.load(Ordering::Acquire) {
            let real_func = unsafe{
                std::mem::transmute::<*mut fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>),
                                      fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>)>(
                    (self.function.load(Ordering::Acquire)))};
            real_func(_x, &self.constants)
        }
        else {
            self.interpreted(_x, &self.constants)
        }
    }

    fn set(&self, f: fn(&Vec<GI>,&Vec<GI>) -> (GI, Option<Vec<GI>>), handle: DynamicLibrary) {
        // This FuncObj owns the handle from the dynamic lib as the lifetime of
        // f is tied to the lifetime of the handle.
        self.function.store(unsafe{std::mem::transmute::<fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>),
                                                         *mut fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>)>(f)}, Ordering::Release);
        let mut h = self.handle.write().unwrap();
        *h = Some(handle);
        self.switched.store(true, Ordering::Release);
    }

    fn interpreted(&self, _x: &Vec<GI>, _c: &Vec<GI>) -> (GI, Option<Vec<GI>>) {
        let mut stack: Vec<GI> = Vec::new();
        for inst in &self.instructions {
            match inst {
                &OpType::Func(ref s) => {
                    let op = stack.last_mut().unwrap();
                    match s.as_str() {
                        "abs" => op.abs(),
                        "sin" => op.sin(),
                        "asin"=> op.asin(),
                        "cos" => op.cos(),
                        "acos" => op.acos(),
                        "tan" => op.tan(),
                        "atan" => op.atan(),
                        "exp" => op.exp(),
                        "log" => op.log(),
                        "neg" => op.neg(),
                        "sqrt" => op.sqrt(),
                        "sinh" => op.sinh(),
                        "cosh" => op.cosh(),
                        "tanh" => op.tanh(),
                        "asinh" => op.asinh(),
                        "acosh" => op.acosh(),
                        "atanh" => op.atanh(),
                        "floor_power2" => op.floor_power2(),
                        "sym_interval" => op.sym_interval(),
                        _     => unreachable!()
                    };
                },
                &OpType::Const(i) => {
                    stack.push(self.constants[i]);
                },
                &OpType::Var(i) => {
                    stack.push(_x[i]);
                },
                &OpType::UVar(i) => {
                    stack.push(self.user_vars[i]);
                },
                &OpType::Op(ref s) => {
                    let right = stack.pop().unwrap();
                    let left = stack.last_mut().unwrap();
                    match s.as_str() {
                        "+" => left.add(right),
                        "-" => left.sub(right),
                        "*" => left.mul(right),
                        "/" => left.div(right),
                        "p" => left.powi(right),
                        _   => unreachable!()
                    };
                },
                &OpType::Pow(exp) => {
                    let arg = stack.last_mut().unwrap();
                    arg.pow(exp);
                }
            }
        }
        (stack[0], None)
    }

    pub fn new(consts: &Vec<GI>, instructions: &String, debug: bool, suffix: String) -> FuncObj {
        let mut insts = vec![];

        for inst in instructions.split(',') {
            let dummy = inst.trim().to_string();
            let (first, rest) = dummy.split_at(1);
            insts.push(match first {
                "c" => OpType::Const(rest.to_string().parse::<usize>().unwrap()),
                "i" => OpType::Var(rest.to_string().parse::<usize>().unwrap()),
                "v" => OpType::UVar(rest.to_string().parse::<usize>().unwrap()),
                "o" => OpType::Op(rest.to_string()),
                "f" => OpType::Func(rest.to_string()),
                "p" => OpType::Pow(rest.to_string().parse::<i32>().unwrap()),
                _   => panic!()
            });
        }
        let result =
            FuncObj{handle: Arc::new(RwLock::new(Option::None)),
                user_vars: vec![],
                constants: consts.clone(),
                instructions: insts,
                switched: Arc::new(AtomicBool::new(false)),
                function: Arc::new(AtomicPtr::new(unsafe{std::mem::transmute::<fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>),
                                                                               *mut fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>)>(dummy)}))
        };

        {
            let fo_c = result.clone();
            thread::spawn(move || {
                &fo_c.compile(debug, &suffix);
            })
        };
        result
    }

    fn compile(&self, debug: bool, suffix: &String) {
        let mut process = Command::new("build_func.sh");
        if debug {
            println!("compile suffix: {}", suffix);
        }
        let ignore = process.arg(suffix.clone()).output()
            .unwrap_or_else(|e| {panic!("Could not compile: {}", e)});

        if !ignore.status.success() {
            panic!("Could not compile: {}\n----\n{}", String::from_utf8(ignore.stdout).unwrap(),
                   String::from_utf8(ignore.stderr).unwrap());
        }

        DynamicLibrary::prepend_search_path(Path::new("./.compiled"));
        let dylib: String = "libfunc_".to_string() + suffix + ".so".into();

        let f = match DynamicLibrary::open(Some(Path::new(&dylib)))
        {
            Ok(lib) => lib,
            Err(err) => panic!("Could not load library: {}", err)
        };
        let g = unsafe{match f.symbol("gelpia_func") {
            Ok(func) => transmute::<*mut u32, fn(&Vec<GI>, &Vec<GI>)->(GI, Option<Vec<GI>>)>(func),
            Err(err) => panic!("Could not load function: {}", err),
        }};

        self.set(g, f);
    }
}

#[test]
fn test1() {
    let constants = vec![GI::new_c("1"), GI::new_c("2"), GI::new_c("3")];
    let f = FuncObj::new(&constants,
                         &"c0,c1,o-,c2,o+".to_string());
    let expected = ((GI::new_c("1") - GI::new_c("2")) + GI::new_c("3")).to_string();
    assert!(f.call(&vec![]).to_string() == expected);
}

#[test]
fn test2() {
    let consts = vec![GI::new_c("1"), GI::new_c("2"), GI::new_c("3")];
    let f = FuncObj::new(&consts,
                         &"c0,fsin,c1,o*,fcos,c2,o/".to_string());
    let expected = cos(sin(consts[0]) * consts[1])/consts[2];
    assert!(f.call(&vec![]).to_string() == expected.to_string());
}

#[test]
fn sum_inputs() {
    let consts = vec![];
    let v = vec![GI::new_d(1.0, 1.0), GI::new_d(1.0, 2.0), GI::new_d(1.0, 3.0),
                 GI::new_d(1.0, 4.0), GI::new_d(1.0, 5.0), GI::new_d(1.0, 6.0)];
    let f = FuncObj::new(&consts,
                         &"i0,i1, o+, i2, o+, i3, o+, i4, o+, i5, o+".to_string());
    let expected = (v[0] + v[1] + v[2] + v[3] + v[4] + v[5]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test3() {
    let consts = vec![GI::new_c("0.1")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fsin".to_string());
    let expected = sin(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test4() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fabs".to_string());
    let expected = abs(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test5() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fcos".to_string());
    let expected = cos(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test6() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, ftan".to_string());
    let expected = tan(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test7() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fexp".to_string());
    let expected = exp(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test8() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fneg".to_string());
    let expected = (-consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test9() {
    let consts = vec![GI::new_c("[0.1, .2]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, flog".to_string());
    let expected = log(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
#[test]
fn test10() {
    let consts = vec![GI::new_c("[2.0, 3.0]"),
                      GI::new_c("[1.5, 2.5]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                         &"c0, c1, op".to_string());
    let expected = powi(consts[0], consts[1]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
#[test]
fn test_power() {
    let consts = vec![GI::new_c("[2.0, 3.0]"),
                      GI::new_c("[1.5, 2.5]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                         &"c0, p-1, c1, p2, o+".to_string());
    let expected = (pow(consts[0], -1) + pow(consts[1], 2)).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
<|endoftext|>


<commit_before>use gc::Address;
use gc::root::IndirectObj;
use gc::space::Space;
use gc::swiper::CARD_SIZE;
use gc::swiper::card::{CardEntry, CardTable};
use gc::swiper::crossing::{CrossingEntry, CrossingMap};
use gc::swiper::old::OldGen;
use gc::swiper::{on_different_cards, start_of_card};
use gc::swiper::Region;
use gc::swiper::young::YoungGen;

use mem;
use object::{Obj, offset_of_array_data};

#[derive(Copy, Clone)]
pub enum VerifierPhase {
    PreMinor,
    PostMinor,
    PreFull,
    PostFull,
}

impl VerifierPhase {
    fn is_pre(self) -> bool {
        match self {
            VerifierPhase::PreMinor => true,
            VerifierPhase::PostMinor => false,
            VerifierPhase::PreFull => true,
            VerifierPhase::PostFull => false,
        }
    }
}

pub struct Verifier<'a> {
    young: &'a YoungGen,
    old: &'a OldGen,
    card_table: &'a CardTable,
    crossing_map: &'a CrossingMap,
    rootset: &'a [IndirectObj],
    perm_space: &'a Space,

    refs_to_young_gen: usize,
    in_old: bool,

    old_region: Region,
    young_region: Region,

    phase: VerifierPhase,
}

impl<'a> Verifier<'a> {
    pub fn new(
        young: &'a YoungGen,
        old: &'a OldGen,
        card_table: &'a CardTable,
        crossing_map: &'a CrossingMap,
        rootset: &'a [IndirectObj],
        perm_space: &'a Space,
        phase: VerifierPhase,
    ) -> Verifier<'a> {
        Verifier {
            young: young,
            old: old,
            card_table: card_table,
            crossing_map: crossing_map,
            rootset: rootset,
            perm_space: perm_space,

            refs_to_young_gen: 0,
            in_old: false,

            young_region: young.used_region(),
            old_region: old.used_region(),

            phase: phase,
        }
    }

    pub fn verify(&mut self) {
        self.verify_roots();
        self.verify_young();
        self.verify_old();
    }

    fn verify_young(&mut self) {
        let region = self.young_region.clone();
        self.verify_objects(region, "young gen");
    }

    fn verify_old(&mut self) {
        let region = self.old_region.clone();
        self.in_old = true;
        self.verify_objects(region, "old gen");
        self.in_old = false;
    }

    fn verify_roots(&mut self) {
        for root in self.rootset {
            let root_ptr = root.get();
            self.verify_reference(root_ptr, root.to_address(), Address::null(), "root set");
        }
    }

    fn verify_objects(&mut self, region: Region, name: &str) {
        let mut curr = region.start;
        self.refs_to_young_gen = 0;

        if self.in_old {
            // we should start at card start
            assert!(self.old.is_card_aligned(curr));
            self.verify_crossing(curr, curr, false);
        }

        while curr < region.end {
            let object = unsafe { &mut *curr.to_mut_ptr::<Obj>() };

            let next = if object.is_array_ref() {
                self.verify_array_ref(object, curr, name)

            } else {
                self.verify_object(object, curr, name)
            };

            curr = next;
        }

        assert!(curr == region.end, "object doesn't end at region end");

        if self.in_old && !start_of_card(curr) {
            self.verify_card(curr);
        }
    }

    fn verify_array_ref(&mut self, object: &mut Obj, mut curr: Address, name: &str) -> Address {
        let object_address = curr;

        object.visit_reference_fields(|child| {
            let child_ptr = child.get();

            if self.in_old && on_different_cards(curr, child.to_address()) {
                self.verify_card(curr);
                curr = child.to_address();
            }

            self.verify_reference(child_ptr, child.to_address(), object_address, name);
        });

        let next = curr.offset(object.size());

        if self.in_old && on_different_cards(curr, next) {
            self.verify_crossing(object_address, next, true);
        }

        next
    }

    fn verify_object(&mut self, object: &mut Obj, curr: Address, name: &str) -> Address {
        object.visit_reference_fields(|child| {
            let child_ptr = child.get();
            self.verify_reference(child_ptr, child.to_address(), curr, name);
        });

        let next = curr.offset(object.size());

        if self.in_old && on_different_cards(curr, next) {
            self.verify_card(curr);
            self.verify_crossing(curr, next, false);
        }

        next
    }

    fn verify_card(&mut self, curr: Address) {
        let curr_card = self.old.card_from_address(curr);

        let card_entry = self.card_table.get(curr_card);
        let expected_card_entry = if self.refs_to_young_gen > 0 {
            CardEntry::Dirty
        } else {
            CardEntry::Clean
        };

        // In the verify-phase before the collection the card's dirty-entry isn't
        // guaranteed to be exact. It could be `dirty` although this card doesn't
        // actually contain any references into the young generation. But it is never
        // clean when there are actual references into the young generation.
        if self.phase.is_pre() && expected_card_entry == CardEntry::Clean {
            self.refs_to_young_gen = 0;
            return;
        }

        if card_entry != expected_card_entry {
            let card_text = match card_entry {
                CardEntry::Dirty => "dirty",
                CardEntry::Clean => "clean",
            };

            println!(
                "CARD: {} is marked {} but has {} reference(s).",
                curr_card.to_usize(),
                card_text,
                self.refs_to_young_gen
            );

            panic!("card table entry wrong.");
        }

        assert!(card_entry == expected_card_entry);

        self.refs_to_young_gen = 0;
    }

    fn verify_crossing(&mut self, old: Address, addr: Address, array_ref: bool) {
        let card = self.old.card_from_address(addr);
        let card_start = self.old.address_from_card(card);
        let offset = addr.offset_from(card_start);
        let offset_words = (offset / mem::ptr_width_usize()) as u8;

        let old_card = self.old.card_from_address(old);
        let old_card_end = self.old.address_from_card(old_card).offset(CARD_SIZE);

        let crossing_middle;
        let loop_start;

        if array_ref {
            let refs_per_card = (CARD_SIZE / mem::ptr_width_usize()) as u8;

            crossing_middle = CrossingEntry::LeadingRefs(refs_per_card);

            if old.offset(offset_of_array_data() as usize) > old_card_end {
                loop_start = old_card.to_usize() + 2;

                let old_next = old_card.to_usize() + 1;
                let crossing = self.crossing_map.get(old_next.into());
                let diff_words = old_card_end.offset_from(old) / mem::ptr_width_usize();
                assert!(crossing == CrossingEntry::ArrayStart(diff_words as u8));

            } else {
                loop_start = old_card.to_usize() + 1;
            }

            if card.to_usize() > loop_start {
                let crossing = self.crossing_map.get(card);
                let expected = CrossingEntry::LeadingRefs(offset_words);
                assert!(crossing == expected, "array crossing at end not correct.");
            }

        } else {
            crossing_middle = CrossingEntry::NoRefs;
            loop_start = old_card.to_usize() + 1;

            let crossing = self.crossing_map.get(card);
            let expected = CrossingEntry::FirstObjectOffset(offset_words);
            assert!(crossing == expected, "crossing at end not correct.");
        }

        for c in loop_start .. card.to_usize() {
            assert!(self.crossing_map.get(c.into()) == crossing_middle, "middle crossing not correct.");
        }
    }

    fn verify_reference(
        &mut self,
        obj: *mut Obj,
        ref_addr: Address,
        obj_addr: Address,
        name: &str,
    ) {
        let addr = Address::from_ptr(obj);

        if obj.is_null() {
            return;
        }

        if self.old_region.contains(addr) || self.young_region.contains(addr) || self.perm_space.contains(addr) {
            let object = unsafe { &mut *obj };

            // Verify that the address is the start of an object,
            // for this access its size.
            // To make sure this isn't optimized out by the compiler,
            // make sure that the size doesn't equal 1.
            assert!(object.size() != 1, "object size shouldn't be 1");

            if self.young_region.contains(addr) {
                self.refs_to_young_gen += 1;
            }

            return;
        }

        println!(
            "YNG: {}-{}; active: {}-{}",
            self.young.total.start,
            self.young.total.end,
            self.young_region.start,
            self.young_region.end
        );
        println!(
            "OLD: {}-{}; active: {}-{}",
            self.old.total.start,
            self.old.total.end,
            self.old_region.start,
            self.old_region.end
        );
        println!(
            "found invalid reference to {} in {} (at {}, in object {}).",
            addr,
            name,
            ref_addr,
            obj_addr
        );

        if self.young.contains(addr) && !self.young_region.contains(addr) {
            println!("reference points into young generation but not into the active semi-space.");
        }

        panic!("reference neither pointing into young nor old generation.");
    }
}<commit_msg>swiper: fix checking of crossing<commit_after>use gc::Address;
use gc::root::IndirectObj;
use gc::space::Space;
use gc::swiper::CARD_SIZE;
use gc::swiper::card::{CardEntry, CardTable};
use gc::swiper::crossing::{CrossingEntry, CrossingMap};
use gc::swiper::old::OldGen;
use gc::swiper::{on_different_cards, start_of_card};
use gc::swiper::Region;
use gc::swiper::young::YoungGen;

use mem;
use object::{Obj, offset_of_array_data};

#[derive(Copy, Clone)]
pub enum VerifierPhase {
    PreMinor,
    PostMinor,
    PreFull,
    PostFull,
}

impl VerifierPhase {
    fn is_pre(self) -> bool {
        match self {
            VerifierPhase::PreMinor => true,
            VerifierPhase::PostMinor => false,
            VerifierPhase::PreFull => true,
            VerifierPhase::PostFull => false,
        }
    }
}

pub struct Verifier<'a> {
    young: &'a YoungGen,
    old: &'a OldGen,
    card_table: &'a CardTable,
    crossing_map: &'a CrossingMap,
    rootset: &'a [IndirectObj],
    perm_space: &'a Space,

    refs_to_young_gen: usize,
    in_old: bool,

    old_region: Region,
    young_region: Region,

    phase: VerifierPhase,
}

impl<'a> Verifier<'a> {
    pub fn new(
        young: &'a YoungGen,
        old: &'a OldGen,
        card_table: &'a CardTable,
        crossing_map: &'a CrossingMap,
        rootset: &'a [IndirectObj],
        perm_space: &'a Space,
        phase: VerifierPhase,
    ) -> Verifier<'a> {
        Verifier {
            young: young,
            old: old,
            card_table: card_table,
            crossing_map: crossing_map,
            rootset: rootset,
            perm_space: perm_space,

            refs_to_young_gen: 0,
            in_old: false,

            young_region: young.used_region(),
            old_region: old.used_region(),

            phase: phase,
        }
    }

    pub fn verify(&mut self) {
        self.verify_roots();
        self.verify_young();
        self.verify_old();
    }

    fn verify_young(&mut self) {
        let region = self.young_region.clone();
        self.verify_objects(region, "young gen");
    }

    fn verify_old(&mut self) {
        let region = self.old_region.clone();
        self.in_old = true;
        self.verify_objects(region, "old gen");
        self.in_old = false;
    }

    fn verify_roots(&mut self) {
        for root in self.rootset {
            let root_ptr = root.get();
            self.verify_reference(root_ptr, root.to_address(), Address::null(), "root set");
        }
    }

    fn verify_objects(&mut self, region: Region, name: &str) {
        let mut curr = region.start;
        self.refs_to_young_gen = 0;

        if self.in_old {
            // we should start at card start
            assert!(self.old.is_card_aligned(curr));
            self.verify_crossing(curr, curr, false);
        }

        while curr < region.end {
            let object = unsafe { &mut *curr.to_mut_ptr::<Obj>() };

            let next = if object.is_array_ref() {
                self.verify_array_ref(object, curr, name)

            } else {
                self.verify_object(object, curr, name)
            };

            curr = next;
        }

        assert!(curr == region.end, "object doesn't end at region end");

        if self.in_old && !start_of_card(curr) {
            self.verify_card(curr);
        }
    }

    fn verify_array_ref(&mut self, object: &mut Obj, mut curr: Address, name: &str) -> Address {
        let object_address = curr;

        object.visit_reference_fields(|child| {
            let child_ptr = child.get();

            if self.in_old && on_different_cards(curr, child.to_address()) {
                self.verify_card(curr);
                curr = child.to_address();
            }

            self.verify_reference(child_ptr, child.to_address(), object_address, name);
        });

        let next = object_address.offset(object.size());

        if self.in_old && on_different_cards(object_address, next) {
            self.verify_crossing(object_address, next, true);
        }

        next
    }

    fn verify_object(&mut self, object: &mut Obj, curr: Address, name: &str) -> Address {
        object.visit_reference_fields(|child| {
            let child_ptr = child.get();
            self.verify_reference(child_ptr, child.to_address(), curr, name);
        });

        let next = curr.offset(object.size());

        if self.in_old && on_different_cards(curr, next) {
            self.verify_card(curr);
            self.verify_crossing(curr, next, false);
        }

        next
    }

    fn verify_card(&mut self, curr: Address) {
        let curr_card = self.old.card_from_address(curr);

        let card_entry = self.card_table.get(curr_card);
        let expected_card_entry = if self.refs_to_young_gen > 0 {
            CardEntry::Dirty
        } else {
            CardEntry::Clean
        };

        // In the verify-phase before the collection the card's dirty-entry isn't
        // guaranteed to be exact. It could be `dirty` although this card doesn't
        // actually contain any references into the young generation. But it is never
        // clean when there are actual references into the young generation.
        if self.phase.is_pre() && expected_card_entry == CardEntry::Clean {
            self.refs_to_young_gen = 0;
            return;
        }

        if card_entry != expected_card_entry {
            let card_text = match card_entry {
                CardEntry::Dirty => "dirty",
                CardEntry::Clean => "clean",
            };

            println!(
                "CARD: {} is marked {} but has {} reference(s).",
                curr_card.to_usize(),
                card_text,
                self.refs_to_young_gen
            );

            panic!("card table entry wrong.");
        }

        assert!(card_entry == expected_card_entry);

        self.refs_to_young_gen = 0;
    }

    fn verify_crossing(&mut self, old: Address, addr: Address, array_ref: bool) {
        let card = self.old.card_from_address(addr);
        let card_start = self.old.address_from_card(card);
        let offset = addr.offset_from(card_start);
        let offset_words = (offset / mem::ptr_width_usize()) as u8;

        let old_card = self.old.card_from_address(old);
        let old_card_end = self.old.address_from_card(old_card).offset(CARD_SIZE);

        let crossing_middle;
        let loop_start;

        if array_ref {
            let refs_per_card = (CARD_SIZE / mem::ptr_width_usize()) as u8;

            crossing_middle = CrossingEntry::LeadingRefs(refs_per_card);

            if old.offset(offset_of_array_data() as usize) > old_card_end {
                loop_start = old_card.to_usize() + 2;

                let old_next = old_card.to_usize() + 1;
                let crossing = self.crossing_map.get(old_next.into());
                let diff_words = old_card_end.offset_from(old) / mem::ptr_width_usize();
                assert!(crossing == CrossingEntry::ArrayStart(diff_words as u8));

            } else {
                loop_start = old_card.to_usize() + 1;
            }

            if card.to_usize() > loop_start {
                let crossing = self.crossing_map.get(card);
                let expected = CrossingEntry::LeadingRefs(offset_words);
                assert!(crossing == expected, "array crossing at end not correct.");
            }

        } else {
            crossing_middle = CrossingEntry::NoRefs;
            loop_start = old_card.to_usize() + 1;

            let crossing = self.crossing_map.get(card);
            let expected = CrossingEntry::FirstObjectOffset(offset_words);
            assert!(crossing == expected, "crossing at end not correct.");
        }

        for c in loop_start .. card.to_usize() {
            assert!(self.crossing_map.get(c.into()) == crossing_middle, "middle crossing not correct.");
        }
    }

    fn verify_reference(
        &mut self,
        obj: *mut Obj,
        ref_addr: Address,
        obj_addr: Address,
        name: &str,
    ) {
        let addr = Address::from_ptr(obj);

        if obj.is_null() {
            return;
        }

        if self.old_region.contains(addr) || self.young_region.contains(addr) || self.perm_space.contains(addr) {
            let object = unsafe { &mut *obj };

            // Verify that the address is the start of an object,
            // for this access its size.
            // To make sure this isn't optimized out by the compiler,
            // make sure that the size doesn't equal 1.
            assert!(object.size() != 1, "object size shouldn't be 1");

            if self.young_region.contains(addr) {
                self.refs_to_young_gen += 1;
            }

            return;
        }

        println!(
            "YNG: {}-{}; active: {}-{}",
            self.young.total.start,
            self.young.total.end,
            self.young_region.start,
            self.young_region.end
        );
        println!(
            "OLD: {}-{}; active: {}-{}",
            self.old.total.start,
            self.old.total.end,
            self.old_region.start,
            self.old_region.end
        );
        println!(
            "found invalid reference to {} in {} (at {}, in object {}).",
            addr,
            name,
            ref_addr,
            obj_addr
        );

        if self.young.contains(addr) && !self.young_region.contains(addr) {
            println!("reference points into young generation but not into the active semi-space.");
        }

        panic!("reference neither pointing into young nor old generation.");
    }
}<|endoftext|>


<commit_before>extern crate pkg_config;

fn main() {
    match pkg_config::find_library("glib-2.0") {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    };
}
<commit_msg>Link gio and gobject explicitly, we export their functions already<commit_after>extern crate pkg_config;

fn main() {
    match pkg_config::find_library("glib-2.0 gio-2.0 gobject-2.0") {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    };
}
<|endoftext|>


<commit_before>use crate::ops::{Deref, DerefMut};

#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(align(64))]
pub(super) struct Aligner;

#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(super) struct CacheAligned<T>(pub T, pub Aligner);

impl<T> Deref for CacheAligned<T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T> DerefMut for CacheAligned<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<T> CacheAligned<T> {
    pub(super) fn new(t: T) -> Self {
        CacheAligned(t, Aligner)
    }
}
<commit_msg>Remove redundant Aligner<commit_after>use crate::ops::{Deref, DerefMut};

#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(align(64))]
pub(super) struct CacheAligned<T>(pub T);

impl<T> Deref for CacheAligned<T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T> DerefMut for CacheAligned<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<T> CacheAligned<T> {
    pub(super) fn new(t: T) -> Self {
        CacheAligned(t)
    }
}
<|endoftext|>


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

use dom::bindings::codegen::BindingDeclarations::HTMLOListElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLOListElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLOListElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLOListElement {
    pub htmlelement: HTMLElement,
}

impl HTMLOListElementDerived for EventTarget {
    fn is_htmlolistelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLOListElementTypeId))
    }
}

impl HTMLOListElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLOListElement {
        HTMLOListElement {
            htmlelement: HTMLElement::new_inherited(HTMLOListElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLOListElement> {
        let element = HTMLOListElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLOListElementBinding::Wrap)
    }
}

pub trait HTMLOListElementMethods {
    fn Reversed(&self) -> bool;
    fn SetReversed(&self, _reversed: bool) -> ErrorResult;
    fn Start(&self) -> i32;
    fn SetStart(&mut self, _start: i32) -> ErrorResult;
    fn Type(&self) -> DOMString;
    fn SetType(&mut self, _type: DOMString) -> ErrorResult;
    fn Compact(&self) -> bool;
    fn SetCompact(&self, _compact: bool) -> ErrorResult;
}

impl<'a> HTMLOListElementMethods for JSRef<'a, HTMLOListElement> {
    fn Reversed(&self) -> bool {
        false
    }

    fn SetReversed(&self, _reversed: bool) -> ErrorResult {
        Ok(())
    }

    fn Start(&self) -> i32 {
        0
    }

    fn SetStart(&mut self, _start: i32) -> ErrorResult {
        Ok(())
    }

    fn Type(&self) -> DOMString {
        "".to_owned()
    }

    fn SetType(&mut self, _type: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Compact(&self) -> bool {
        false
    }

    fn SetCompact(&self, _compact: bool) -> ErrorResult {
        Ok(())
    }
}
<commit_msg>Remove needless '&mut self' from HTMLOListElementMethods.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::BindingDeclarations::HTMLOListElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLOListElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLOListElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLOListElement {
    pub htmlelement: HTMLElement,
}

impl HTMLOListElementDerived for EventTarget {
    fn is_htmlolistelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLOListElementTypeId))
    }
}

impl HTMLOListElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLOListElement {
        HTMLOListElement {
            htmlelement: HTMLElement::new_inherited(HTMLOListElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLOListElement> {
        let element = HTMLOListElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLOListElementBinding::Wrap)
    }
}

pub trait HTMLOListElementMethods {
    fn Reversed(&self) -> bool;
    fn SetReversed(&self, _reversed: bool) -> ErrorResult;
    fn Start(&self) -> i32;
    fn SetStart(&self, _start: i32) -> ErrorResult;
    fn Type(&self) -> DOMString;
    fn SetType(&self, _type: DOMString) -> ErrorResult;
    fn Compact(&self) -> bool;
    fn SetCompact(&self, _compact: bool) -> ErrorResult;
}

impl<'a> HTMLOListElementMethods for JSRef<'a, HTMLOListElement> {
    fn Reversed(&self) -> bool {
        false
    }

    fn SetReversed(&self, _reversed: bool) -> ErrorResult {
        Ok(())
    }

    fn Start(&self) -> i32 {
        0
    }

    fn SetStart(&self, _start: i32) -> ErrorResult {
        Ok(())
    }

    fn Type(&self) -> DOMString {
        "".to_owned()
    }

    fn SetType(&self, _type: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Compact(&self) -> bool {
        false
    }

    fn SetCompact(&self, _compact: bool) -> ErrorResult {
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::path::{Path, PathBuf};

use libmount::BindMount;

use quire::validate as V;
use config::read_config;
use config::containers::Container as Cont;
use version::short_version;
use container::mount::{remount_ro};
use container::util::{copy_dir};
use file_util::{create_dir, shallow_copy};
use path_util::ToRelative;
use build_step::{BuildStep, VersionError, StepError, Digest, Config, Guard};

use builder::error::StepError as E;

// Build Steps
#[derive(Debug)]
pub struct Container(String);
tuple_struct_decode!(Container);

impl Container {
    pub fn config() -> V::Scalar {
        V::Scalar::new()
    }
}

#[derive(RustcDecodable, Debug)]
pub struct Build {
    pub container: String,
    pub source: PathBuf,
    pub path: Option<PathBuf>,
    pub temporary_mount: Option<PathBuf>,
}

impl Build {
    pub fn config() -> V::Structure<'static> {
        V::Structure::new()
        .member("container", V::Scalar::new())
        .member("source".to_string(),
            V::Directory::new().is_absolute(true).default("/"))
        .member("path".to_string(),
            V::Directory::new().is_absolute(true).optional())
        .member("temporary_mount".to_string(),
            V::Directory::new().is_absolute(true).optional())
    }
}

#[derive(RustcDecodable, Debug)]
pub struct GitSource {
    pub url: String,
    pub revision: Option<String>,
    pub branch: Option<String>,
}

#[derive(RustcDecodable, Debug)]
pub enum Source {
    Git(GitSource),
    Container(String),
    Directory,
}

#[derive(RustcDecodable, Debug)]
pub struct SubConfig {
    pub source: Source,
    pub path: PathBuf,
    pub container: String,
    pub cache: Option<bool>,
    pub change_dir: Option<bool>,
}

impl SubConfig {
    pub fn config() -> V::Structure<'static> {
        V::Structure::new()
        .member("source", V::Enum::new()
            .option("Directory", V::Nothing)
            .option("Container", V::Scalar::new())
            .option("Git", V::Structure::new()
                .member("url", V::Scalar::new())
                .member("revision", V::Scalar::new().optional())
                .member("branch", V::Scalar::new().optional()))
            .optional()
            .default_tag("Directory"))
        .member("path".to_string(), V::Directory::new()
            .is_absolute(false)
            .default("vagga.yaml"))
        .member("container", V::Scalar::new())
        .member("cache", V::Scalar::new().optional())
        .member("change_dir", V::Scalar::new().optional())
    }
}

pub fn build(binfo: &Build, guard: &mut Guard, build: bool)
    -> Result<(), StepError>
{
    let ref name = binfo.container;
    let cont = guard.ctx.config.containers.get(name)
        .expect("Subcontainer not found");  // TODO
    if build {
        let version = try!(short_version(&cont, &guard.ctx.config)
            .map_err(|(s, e)| format!("step {}: {}", s, e)));
        let path = Path::new("/vagga/base/.roots")
            .join(format!("{}.{}", name, version)).join("root")
            .join(binfo.source.rel());
        if let Some(ref dest_rel) = binfo.path {
            let dest = Path::new("/vagga/root")
                .join(dest_rel.rel());
            if path.is_dir() {
                try_msg!(copy_dir(&path, &dest, None, None),
                    "Error copying dir {p:?}: {err}", p=path);
            } else {
                try_msg!(shallow_copy(&path, &dest, None, None),
                    "Error copying dir {p:?}: {err}", p=path);
            }
        } else if let Some(ref dest_rel) = binfo.temporary_mount {
            let dest = Path::new("/vagga/root")
                .join(dest_rel.rel());
            try_msg!(create_dir(&dest, false),
                "Error creating destination dir: {err}");
            try!(BindMount::new(&path, &dest).mount());
            try!(remount_ro(&dest));
            guard.ctx.mounted.push(dest);
        }
    }
    Ok(())
}

fn real_build(name: &String, cont: &Cont, guard: &mut Guard)
    -> Result<(), StepError>
{
    let version = try!(short_version(&cont, &guard.ctx.config)
        .map_err(|(s, e)| format!("step {}: {}", s, e)));
    let path = Path::new("/vagga/base/.roots")
        .join(format!("{}.{}", name, version)).join("root");
    try_msg!(copy_dir(&path, &Path::new("/vagga/root"),
                      None, None),
        "Error copying dir {p:?}: {err}", p=path);
    Ok(())
}

pub fn clone(name: &String, guard: &mut Guard, build: bool)
    -> Result<(), StepError>
{
    let cont = guard.ctx.config.containers.get(name)
        .expect("Subcontainer not found");  // TODO
    for b in cont.setup.iter() {
        try!(b.build(guard, false)
            .map_err(|e| E::SubStep(b.0.clone(), Box::new(e))));
    }
    if build {
        try!(real_build(name, cont, guard));
    }
    Ok(())
}

fn find_config(cfg: &SubConfig, guard: &mut Guard)
    -> Result<Config, StepError>
{
    let path = match cfg.source {
        Source::Container(ref container) => {
            let cont = guard.ctx.config.containers.get(container)
                .expect("Subcontainer not found");  // TODO
            let version = try!(short_version(&cont, &guard.ctx.config)
                .map_err(|(s, e)| format!("step {}: {}", s, e)));
            Path::new("/vagga/base/.roots")
                .join(format!("{}.{}", container, version))
                .join("root").join(&cfg.path)
        }
        Source::Git(ref _git) => {
            unimplemented!();
        }
        Source::Directory => {
            Path::new("/work").join(&cfg.path)
        }
    };
    Ok(try!(read_config(&path)))
}

pub fn subconfig(cfg: &SubConfig, guard: &mut Guard, build: bool)
    -> Result<(), StepError>
{
    let subcfg = try!(find_config(cfg, guard));
    let cont = subcfg.containers.get(&cfg.container)
        .expect("Subcontainer not found");  // TODO
    for b in cont.setup.iter() {
        try!(b.build(guard, build)
            .map_err(|e| E::SubStep(b.0.clone(), Box::new(e))));
    }
    Ok(())
}

impl BuildStep for Container {
    fn hash(&self, cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        let cont = try!(cfg.containers.get(&self.0)
            .ok_or(VersionError::ContainerNotFound(self.0.to_string())));
        for b in cont.setup.iter() {
            debug!("Versioning setup: {:?}", b);
            try!(b.hash(cfg, hash));
        }
        Ok(())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        clone(&self.0, guard, build)
    }
    fn is_dependent_on(&self) -> Option<&str> {
        Some(&self.0)
    }
}
impl BuildStep for Build {
    fn hash(&self, cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        let cont = try!(cfg.containers.get(&self.container)
            .ok_or(VersionError::ContainerNotFound(self.container.to_string())));
        for b in cont.setup.iter() {
            debug!("Versioning setup: {:?}", b);
            try!(b.hash(cfg, hash));
        }
        Ok(())
    }
    fn build(&self, guard: &mut Guard, do_build: bool)
        -> Result<(), StepError>
    {
        build(&self, guard, do_build)
    }
    fn is_dependent_on(&self) -> Option<&str> {
        Some(&self.container)
    }
}
impl BuildStep for SubConfig {
    fn hash(&self, cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        let path = match self.source {
            Source::Container(ref container) => {
                let cinfo = try!(cfg.containers.get(container)
                    .ok_or(VersionError::ContainerNotFound(container.clone())));
                let version = try!(short_version(&cinfo, cfg));
                Path::new("/vagga/base/.roots")
                    .join(format!("{}.{}", container, version))
                    .join("root").join(&self.path)
            }
            Source::Git(ref _git) => {
                unimplemented!();
            }
            Source::Directory => {
                Path::new("/work").join(&self.path)
            }
        };
        if !path.exists() {
            return Err(VersionError::New);
        }
        let subcfg = try!(read_config(&path));
        let cont = try!(subcfg.containers.get(&self.container)
            .ok_or(VersionError::ContainerNotFound(self.container.to_string())));
        for b in cont.setup.iter() {
            debug!("Versioning setup: {:?}", b);
            try!(b.hash(cfg, hash));
        }
        Ok(())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        subconfig(self, guard, build)
    }
    fn is_dependent_on(&self) -> Option<&str> {
        match self.source {
            Source::Directory => None,
            Source::Container(ref name) => Some(name),
            Source::Git(ref _git) => None,
        }
    }
}
<commit_msg>Subcontainer copy now updates `last_use` (fixes #267)<commit_after>use std::path::{Path, PathBuf};
use std::fs::File;

use libmount::BindMount;

use quire::validate as V;
use config::read_config;
use config::containers::Container as Cont;
use version::short_version;
use container::mount::{remount_ro};
use container::util::{copy_dir};
use file_util::{create_dir, shallow_copy};
use path_util::ToRelative;
use build_step::{BuildStep, VersionError, StepError, Digest, Config, Guard};

use builder::error::StepError as E;

// Build Steps
#[derive(Debug)]
pub struct Container(String);
tuple_struct_decode!(Container);

impl Container {
    pub fn config() -> V::Scalar {
        V::Scalar::new()
    }
}

#[derive(RustcDecodable, Debug)]
pub struct Build {
    pub container: String,
    pub source: PathBuf,
    pub path: Option<PathBuf>,
    pub temporary_mount: Option<PathBuf>,
}

impl Build {
    pub fn config() -> V::Structure<'static> {
        V::Structure::new()
        .member("container", V::Scalar::new())
        .member("source".to_string(),
            V::Directory::new().is_absolute(true).default("/"))
        .member("path".to_string(),
            V::Directory::new().is_absolute(true).optional())
        .member("temporary_mount".to_string(),
            V::Directory::new().is_absolute(true).optional())
    }
}

#[derive(RustcDecodable, Debug)]
pub struct GitSource {
    pub url: String,
    pub revision: Option<String>,
    pub branch: Option<String>,
}

#[derive(RustcDecodable, Debug)]
pub enum Source {
    Git(GitSource),
    Container(String),
    Directory,
}

#[derive(RustcDecodable, Debug)]
pub struct SubConfig {
    pub source: Source,
    pub path: PathBuf,
    pub container: String,
    pub cache: Option<bool>,
    pub change_dir: Option<bool>,
}

impl SubConfig {
    pub fn config() -> V::Structure<'static> {
        V::Structure::new()
        .member("source", V::Enum::new()
            .option("Directory", V::Nothing)
            .option("Container", V::Scalar::new())
            .option("Git", V::Structure::new()
                .member("url", V::Scalar::new())
                .member("revision", V::Scalar::new().optional())
                .member("branch", V::Scalar::new().optional()))
            .optional()
            .default_tag("Directory"))
        .member("path".to_string(), V::Directory::new()
            .is_absolute(false)
            .default("vagga.yaml"))
        .member("container", V::Scalar::new())
        .member("cache", V::Scalar::new().optional())
        .member("change_dir", V::Scalar::new().optional())
    }
}

pub fn build(binfo: &Build, guard: &mut Guard, build: bool)
    -> Result<(), StepError>
{
    let ref name = binfo.container;
    let cont = guard.ctx.config.containers.get(name)
        .expect("Subcontainer not found");  // TODO
    if build {
        let version = try!(short_version(&cont, &guard.ctx.config)
            .map_err(|(s, e)| format!("step {}: {}", s, e)));
        let container = Path::new("/vagga/base/.roots")
            .join(format!("{}.{}", name, version));
        let path = container.join("root").join(binfo.source.rel());

        // Update container use when using it as subcontainer (fixes #267)
        File::create(Path::new(&container).join("last_use"))
            .map_err(|e| warn!("Can't write image usage info: {}", e)).ok();

        if let Some(ref dest_rel) = binfo.path {
            let dest = Path::new("/vagga/root")
                .join(dest_rel.rel());
            if path.is_dir() {
                try_msg!(copy_dir(&path, &dest, None, None),
                    "Error copying dir {p:?}: {err}", p=path);
            } else {
                try_msg!(shallow_copy(&path, &dest, None, None),
                    "Error copying dir {p:?}: {err}", p=path);
            }
        } else if let Some(ref dest_rel) = binfo.temporary_mount {
            let dest = Path::new("/vagga/root")
                .join(dest_rel.rel());
            try_msg!(create_dir(&dest, false),
                "Error creating destination dir: {err}");
            try!(BindMount::new(&path, &dest).mount());
            try!(remount_ro(&dest));
            guard.ctx.mounted.push(dest);
        }
    }
    Ok(())
}

fn real_copy(name: &String, cont: &Cont, guard: &mut Guard)
    -> Result<(), StepError>
{
    let version = try!(short_version(&cont, &guard.ctx.config)
        .map_err(|(s, e)| format!("step {}: {}", s, e)));
    let container = format!("/vagga/base/.roots/{}.{}", name, version);

    // Update container use when using it as subcontainer (fixes #267)
    File::create(Path::new(&container).join("last_use"))
        .map_err(|e| warn!("Can't write image usage info: {}", e)).ok();

    let root = Path::new(&container).join("root");
    try_msg!(copy_dir(&root, &Path::new("/vagga/root"),
                      None, None),
        "Error copying dir {p:?}: {err}", p=root);
    Ok(())
}

pub fn clone(name: &String, guard: &mut Guard, build: bool)
    -> Result<(), StepError>
{
    let cont = guard.ctx.config.containers.get(name)
        .expect("Subcontainer not found");  // TODO
    for b in cont.setup.iter() {
        try!(b.build(guard, false)
            .map_err(|e| E::SubStep(b.0.clone(), Box::new(e))));
    }
    if build {
        try!(real_copy(name, cont, guard));
    }
    Ok(())
}

fn find_config(cfg: &SubConfig, guard: &mut Guard)
    -> Result<Config, StepError>
{
    let path = match cfg.source {
        Source::Container(ref container) => {
            let cont = guard.ctx.config.containers.get(container)
                .expect("Subcontainer not found");  // TODO
            let version = try!(short_version(&cont, &guard.ctx.config)
                .map_err(|(s, e)| format!("step {}: {}", s, e)));
            let container = Path::new("/vagga/base/.roots")
                .join(format!("{}.{}", container, version));

            // Update container use when using it as subcontainer (fixes #267)
            File::create(Path::new(&container).join("last_use"))
                .map_err(|e| warn!("Can't write image usage info: {}", e))
                .ok();

            container.join("root").join(&cfg.path)
        }
        Source::Git(ref _git) => {
            unimplemented!();
        }
        Source::Directory => {
            Path::new("/work").join(&cfg.path)
        }
    };
    Ok(try!(read_config(&path)))
}

pub fn subconfig(cfg: &SubConfig, guard: &mut Guard, build: bool)
    -> Result<(), StepError>
{
    let subcfg = try!(find_config(cfg, guard));
    let cont = subcfg.containers.get(&cfg.container)
        .expect("Subcontainer not found");  // TODO
    for b in cont.setup.iter() {
        try!(b.build(guard, build)
            .map_err(|e| E::SubStep(b.0.clone(), Box::new(e))));
    }
    Ok(())
}

impl BuildStep for Container {
    fn hash(&self, cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        let cont = try!(cfg.containers.get(&self.0)
            .ok_or(VersionError::ContainerNotFound(self.0.to_string())));
        for b in cont.setup.iter() {
            debug!("Versioning setup: {:?}", b);
            try!(b.hash(cfg, hash));
        }
        Ok(())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        clone(&self.0, guard, build)
    }
    fn is_dependent_on(&self) -> Option<&str> {
        Some(&self.0)
    }
}
impl BuildStep for Build {
    fn hash(&self, cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        let cont = try!(cfg.containers.get(&self.container)
            .ok_or(VersionError::ContainerNotFound(self.container.to_string())));
        for b in cont.setup.iter() {
            debug!("Versioning setup: {:?}", b);
            try!(b.hash(cfg, hash));
        }
        Ok(())
    }
    fn build(&self, guard: &mut Guard, do_build: bool)
        -> Result<(), StepError>
    {
        build(&self, guard, do_build)
    }
    fn is_dependent_on(&self) -> Option<&str> {
        Some(&self.container)
    }
}
impl BuildStep for SubConfig {
    fn hash(&self, cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        let path = match self.source {
            Source::Container(ref container) => {
                let cinfo = try!(cfg.containers.get(container)
                    .ok_or(VersionError::ContainerNotFound(container.clone())));
                let version = try!(short_version(&cinfo, cfg));
                Path::new("/vagga/base/.roots")
                    .join(format!("{}.{}", container, version))
                    .join("root").join(&self.path)
            }
            Source::Git(ref _git) => {
                unimplemented!();
            }
            Source::Directory => {
                Path::new("/work").join(&self.path)
            }
        };
        if !path.exists() {
            return Err(VersionError::New);
        }
        let subcfg = try!(read_config(&path));
        let cont = try!(subcfg.containers.get(&self.container)
            .ok_or(VersionError::ContainerNotFound(self.container.to_string())));
        for b in cont.setup.iter() {
            debug!("Versioning setup: {:?}", b);
            try!(b.hash(cfg, hash));
        }
        Ok(())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        subconfig(self, guard, build)
    }
    fn is_dependent_on(&self) -> Option<&str> {
        match self.source {
            Source::Directory => None,
            Source::Container(ref name) => Some(name),
            Source::Git(ref _git) => None,
        }
    }
}
<|endoftext|>