<commit_before>use alloc::boxed::Box;

use collections::string::ToString;
use collections::vec::Vec;

use core::intrinsics::{volatile_load, volatile_store};
use core::{cmp, mem, ptr, slice};

use scheduler::context::{self, Context};
use common::debug;
use common::event::MouseEvent;
use common::memory::{self, Memory};
use common::time::{self, Duration};

use drivers::pciconfig::PciConfig;
use drivers::pio::*;

use graphics::display::VBEMODEINFO;

use schemes::KScheme;

use super::UsbMsg;
use super::desc::*;
use super::setup::Setup;

pub struct Uhci {
    pub base: usize,
    pub irq: u8,
}

impl KScheme for Uhci {
    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            // d("UHCI IRQ\n");
        }
    }

    fn on_poll(&mut self) {
    }
}

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Td {
    link_ptr: u32,
    ctrl_sts: u32,
    token: u32,
    buffer: u32,
}

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Qh {
    head_ptr: u32,
    element_ptr: u32,
}

impl Uhci {
    pub unsafe fn new(mut pci: PciConfig) -> Box<Self> {
        pci.flag(4, 4, true); // Bus mastering

        let module = box Uhci {
            base: pci.read(0x20) as usize & 0xFFFFFFF0,
            irq: pci.read(0x3C) as u8 & 0xF,
        };

        module.init();

        return module;
    }

    unsafe fn msg(&self, frame_list: *mut u32, address: u8, msgs: &[UsbMsg]) {
        debugln!("{}: {} Messages", address, msgs.len());

        for msg in msgs.iter() {
            debugln!("{:#?}", msg);
        }

        let mut tds = Vec::new();
        for msg in msgs.iter().rev() {
            let link_ptr = match tds.get(0) {
                Some(td) => (td as *const Td) as u32 | 4,
                None => 1
            };

            match *msg {
                UsbMsg::Setup(setup) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: (mem::size_of::<Setup>() as u32 - 1) << 21 | (address as u32) << 8 | 0x2D,
                    buffer: (&*setup as *const Setup) as u32,
                }),
                UsbMsg::In(ref data) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: ((data.len() as u32 - 1) & 0x7FF) << 21 | (address as u32) << 8 | 0x69,
                    buffer: data.as_ptr() as u32,
                }),
                UsbMsg::Out(ref data) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: ((data.len() as u32 - 1) & 0x7FF) << 21 | (address as u32) << 8 | 0xE1,
                    buffer: data.as_ptr() as u32,
                })
            }
        }

        if ! tds.is_empty() {
            let queue_head = box Qh {
                 head_ptr: 1,
                 element_ptr: (tds.last().unwrap() as *const Td) as u32,
            };

            let frnum = Pio16::new(self.base as u16 + 6);
            let frame = (frnum.read() + 2) & 0x3FF;
            ptr::write(frame_list.offset(frame as isize),
                       (&*queue_head as *const Qh) as u32 | 2);

            for td in tds.iter().rev() {
                debugln!("Start {:#?}", volatile_load(td as *const Td));
                let mut i = 1000000;
                while volatile_load(td as *const Td).ctrl_sts & 1 << 23 == 1 << 23 && i > 0 {
                    i -= 1;
                }
                debugln!("End {:#?}", volatile_load(td as *const Td));
            }

            ptr::write(frame_list.offset(frame as isize), 1);
        }
    }

    unsafe fn set_address(&self, frame_list: *mut u32, address: u8) {
        self.msg(frame_list, 0, &[
            UsbMsg::Setup(&Setup::set_address(address)),
            UsbMsg::In(&mut [])
        ]);
    }

    unsafe fn descriptor(&self,
                         frame_list: *mut u32,
                         address: u8,
                         descriptor_type: u8,
                         descriptor_index: u8,
                         descriptor_ptr: usize,
                         descriptor_len: usize) {
        self.msg(frame_list, address, &[
            UsbMsg::Setup(&Setup::get_descriptor(descriptor_type, descriptor_index, 0, descriptor_len as u16)),
            UsbMsg::In(&mut slice::from_raw_parts_mut(descriptor_ptr as *mut u8, descriptor_len as usize)),
            UsbMsg::Out(&[])
        ]);
    }

    unsafe fn device(&self, frame_list: *mut u32, address: u8) {
        self.set_address(frame_list, address);

        let mut desc_dev = box DeviceDescriptor::default();
        self.descriptor(frame_list,
                        address,
                        DESC_DEV,
                        0,
                        (&mut *desc_dev as *mut DeviceDescriptor) as usize,
                        mem::size_of_val(&*desc_dev));
        debugln!("{:#?}", *desc_dev);

        for configuration in 0..(*desc_dev).configurations {
            let desc_cfg_len = 1023;
            let desc_cfg_buf = memory::alloc(desc_cfg_len) as *mut u8;
            for i in 0..desc_cfg_len as isize {
                ptr::write(desc_cfg_buf.offset(i), 0);
            }
            self.descriptor(frame_list,
                            address,
                            DESC_CFG,
                            configuration,
                            desc_cfg_buf as usize,
                            desc_cfg_len);

            let desc_cfg = ptr::read(desc_cfg_buf as *const ConfigDescriptor);
            debugln!("{:#?}", desc_cfg);

            let mut hid = false;

            let mut i = desc_cfg.length as isize;
            while i < desc_cfg.total_length as isize {
                let length = ptr::read(desc_cfg_buf.offset(i));
                let descriptor_type = ptr::read(desc_cfg_buf.offset(i + 1));
                match descriptor_type {
                    DESC_INT => {
                        let desc_int = ptr::read(desc_cfg_buf.offset(i) as *const InterfaceDescriptor);
                        debugln!("{:#?}", desc_int);
                    }
                    DESC_END => {
                        let desc_end = ptr::read(desc_cfg_buf.offset(i) as *const EndpointDescriptor);
                        debugln!("{:#?}", desc_end);

                        let endpoint = desc_end.address & 0xF;
                        let in_len = desc_end.max_packet_size as usize;

                        let base = self.base as u16;
                        let frnum = base + 0x6;

                        if hid {
                            Context::spawn("kuhci_hid".to_string(), box move || {
                                debugln!("Starting HID driver");

                                let in_ptr = memory::alloc(in_len) as *mut u8;
                                let mut in_td = Memory::<Td>::new(1).unwrap();

                                loop {
                                    for i in 0..in_len as isize {
                                        volatile_store(in_ptr.offset(i), 0);
                                    }

                                    in_td.store(0,
                                               Td {
                                                   link_ptr: 1,
                                                   ctrl_sts: 1 << 25 | 1 << 23,
                                                   token: (in_len as u32 - 1) << 21 |
                                                          (endpoint as u32) << 15 |
                                                          (address as u32) << 8 |
                                                          0x69,
                                                   buffer: in_ptr as u32,
                                               });

                                    let frame = (inw(frnum) + 2) & 0x3FF;
                                    volatile_store(frame_list.offset(frame as isize), in_td.address() as u32);

                                    while in_td.load(0).ctrl_sts & 1 << 23 == 1 << 23 {
                                        context::context_switch(false);
                                    }

                                    volatile_store(frame_list.offset(frame as isize), 1);

                                    if in_td.load(0).ctrl_sts & 0x7FF > 0 {
                                       let buttons = ptr::read(in_ptr.offset(0) as *const u8) as usize;
                                       let x = ptr::read(in_ptr.offset(1) as *const u16) as usize;
                                       let y = ptr::read(in_ptr.offset(3) as *const u16) as usize;

                                       let mode_info = &*VBEMODEINFO;
                                       let mouse_x = (x * mode_info.xresolution as usize) / 32768;
                                       let mouse_y = (y * mode_info.yresolution as usize) / 32768;

                                       let mouse_event = MouseEvent {
                                           x: cmp::max(0, cmp::min(mode_info.xresolution as i32 - 1, mouse_x as i32)),
                                           y: cmp::max(0, cmp::min(mode_info.yresolution as i32 - 1, mouse_y as i32)),
                                           left_button: buttons & 1 == 1,
                                           middle_button: buttons & 4 == 4,
                                           right_button: buttons & 2 == 2,
                                       };
                                       ::env().events.lock().push_back(mouse_event.to_event());
                                    }

                                    Duration::new(0, 10 * time::NANOS_PER_MILLI).sleep();
                                }
                            });
                        }
                    }
                    DESC_HID => {
                        let desc_hid = &*(desc_cfg_buf.offset(i) as *const HIDDescriptor);
                        debugln!("{:#?}", desc_hid);
                        hid = true;
                    }
                    _ => {
                        debug::d("Unknown Descriptor Length ");
                        debug::dd(length as usize);
                        debug::d(" Type ");
                        debug::dh(descriptor_type as usize);
                        debug::dl();
                    }
                }
                i += length as isize;
            }

            memory::unalloc(desc_cfg_buf as usize);
        }
    }

    pub unsafe fn init(&self) {
        debug::d("UHCI on: ");
        debug::dh(self.base);
        debug::d(", IRQ: ");
        debug::dbh(self.irq);

        let base = self.base as u16;
        let usbcmd = base;
        let usbsts = base + 02;
        let usbintr = base + 0x4;
        let frnum = base + 0x6;
        let flbaseadd = base + 0x8;
        let portsc1 = base + 0x10;
        let portsc2 = base + 0x12;

        debug::d(" CMD ");
        debug::dh(inw(usbcmd) as usize);
        outw(usbcmd, 1 << 2 | 1 << 1);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        outw(usbcmd, 0);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        debug::d(" STS ");
        debug::dh(inw(usbsts) as usize);

        debug::d(" INTR ");
        debug::dh(inw(usbintr) as usize);

        debug::d(" FRNUM ");
        debug::dh(inw(frnum) as usize);
        outw(frnum, 0);
        debug::d(" to ");
        debug::dh(inw(frnum) as usize);

        debug::d(" FLBASEADD ");
        debug::dh(ind(flbaseadd) as usize);
        let frame_list = memory::alloc(1024 * 4) as *mut u32;
        for i in 0..1024 {
            ptr::write(frame_list.offset(i), 1);
        }
        outd(flbaseadd, frame_list as u32);
        debug::d(" to ");
        debug::dh(ind(flbaseadd) as usize);

        debug::d(" CMD ");
        debug::dh(inw(usbcmd) as usize);
        outw(usbcmd, 1);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        debug::dl();

        {
            debug::d(" PORTSC1 ");
            debug::dh(inw(portsc1) as usize);

            outw(portsc1, 1 << 9);
            debug::d(" to ");
            debug::dh(inw(portsc1) as usize);

            outw(portsc1, 0);
            debug::d(" to ");
            debug::dh(inw(portsc1) as usize);

            debug::dl();

            if inw(portsc1) & 1 == 1 {
                debug::d(" Device Found ");
                debug::dh(inw(portsc1) as usize);

                outw(portsc1, 4);
                debug::d(" to ");
                debug::dh(inw(portsc1) as usize);
                debug::dl();

                self.device(frame_list, 1);
            }
        }

        {
            debug::d(" PORTSC2 ");
            debug::dh(inw(portsc2) as usize);

            outw(portsc2, 1 << 9);
            debug::d(" to ");
            debug::dh(inw(portsc2) as usize);

            outw(portsc2, 0);
            debug::d(" to ");
            debug::dh(inw(portsc2) as usize);

            debug::dl();

            if inw(portsc2) & 1 == 1 {
                debug::d(" Device Found ");
                debug::dh(inw(portsc2) as usize);

                outw(portsc2, 4);
                debug::d(" to ");
                debug::dh(inw(portsc2) as usize);
                debug::dl();

                self.device(frame_list, 2);
            }
        }
    }
}
<commit_msg>Cleanup HID<commit_after>use alloc::boxed::Box;

use collections::string::ToString;
use collections::vec::Vec;

use core::intrinsics::volatile_load;
use core::{cmp, mem, ptr, slice};

use scheduler::context::{context_switch, Context};
use common::debug;
use common::event::MouseEvent;
use common::memory::{self, Memory};
use common::time::{self, Duration};

use drivers::pciconfig::PciConfig;
use drivers::pio::*;

use graphics::display::VBEMODEINFO;

use schemes::KScheme;

use super::UsbMsg;
use super::desc::*;
use super::setup::Setup;

pub struct Uhci {
    pub base: usize,
    pub irq: u8,
    pub frame_list: Memory<u32>,
}

impl KScheme for Uhci {
    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            // d("UHCI IRQ\n");
        }
    }

    fn on_poll(&mut self) {
    }
}

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Td {
    link_ptr: u32,
    ctrl_sts: u32,
    token: u32,
    buffer: u32,
}

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Qh {
    head_ptr: u32,
    element_ptr: u32,
}

impl Uhci {
    pub unsafe fn new(mut pci: PciConfig) -> Box<Self> {
        pci.flag(4, 4, true); // Bus mastering

        let mut module = box Uhci {
            base: pci.read(0x20) as usize & 0xFFFFFFF0,
            irq: pci.read(0x3C) as u8 & 0xF,
            frame_list: Memory::new(1024).unwrap(),
        };

        module.init();

        return module;
    }

    fn msg(&mut self, address: u8, endpoint: u8, msgs: &[UsbMsg]) -> usize {
        let mut tds = Vec::new();
        for msg in msgs.iter().rev() {
            let link_ptr = match tds.last() {
                Some(td) => (td as *const Td) as u32 | 4,
                None => 1
            };

            match *msg {
                UsbMsg::Setup(setup) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: (mem::size_of::<Setup>() as u32 - 1) << 21 | (endpoint as u32) << 15 | (address as u32) << 8 | 0x2D,
                    buffer: (&*setup as *const Setup) as u32,
                }),
                UsbMsg::In(ref data) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: ((data.len() as u32 - 1) & 0x7FF) << 21 | (endpoint as u32) << 15 | (address as u32) << 8 | 0x69,
                    buffer: data.as_ptr() as u32,
                }),
                UsbMsg::Out(ref data) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: ((data.len() as u32 - 1) & 0x7FF) << 21 | (endpoint as u32) << 15 | (address as u32) << 8 | 0xE1,
                    buffer: data.as_ptr() as u32,
                })
            }
        }

        let mut count = 0;

        if tds.len() > 1 {
            let queue_head = box Qh {
                 head_ptr: 1,
                 element_ptr: (tds.last().unwrap() as *const Td) as u32,
            };

            let frnum = Pio16::new(self.base as u16 + 6);
            let frame = (unsafe { frnum.read() } + 1) & 0x3FF;
            unsafe { self.frame_list.write(frame as usize, (&*queue_head as *const Qh) as u32 | 2) };

            for td in tds.iter().rev() {
                while unsafe { volatile_load(td as *const Td).ctrl_sts } & 1 << 23 == 1 << 23 {
                    unsafe { context_switch(false) };
                }
                count += (unsafe { volatile_load(td as *const Td).ctrl_sts } & 0x7FF) as usize;
            }

            unsafe { self.frame_list.write(frame as usize, 1) };
        } else if tds.len() == 1 {
            tds[0].ctrl_sts |= 1 << 25;

            let frnum = Pio16::new(self.base as u16 + 6);
            let frame = (unsafe { frnum.read() } + 1) & 0x3FF;
            unsafe { self.frame_list.write(frame as usize, (&tds[0] as *const Td) as u32) };

            for td in tds.iter().rev() {
                while unsafe { volatile_load(td as *const Td).ctrl_sts } & 1 << 23 == 1 << 23 {
                    unsafe { context_switch(false) };
                }
                count += (unsafe { volatile_load(td as *const Td).ctrl_sts } & 0x7FF) as usize;
            }

            unsafe { self.frame_list.write(frame as usize, 1) };
        }

        count
    }

    fn descriptor(&mut self,
                         address: u8,
                         descriptor_type: u8,
                         descriptor_index: u8,
                         descriptor_ptr: usize,
                         descriptor_len: usize) {
        self.msg(address, 0, &[
            UsbMsg::Setup(&Setup::get_descriptor(descriptor_type, descriptor_index, 0, descriptor_len as u16)),
            UsbMsg::In(&mut unsafe { slice::from_raw_parts_mut(descriptor_ptr as *mut u8, descriptor_len as usize) }),
            UsbMsg::Out(&[])
        ]);
    }

    unsafe fn device(&mut self, address: u8) {
        self.msg(0, 0, &[
            UsbMsg::Setup(&Setup::set_address(address)),
            UsbMsg::In(&mut [])
        ]);

        let mut desc_dev = box DeviceDescriptor::default();
        self.descriptor(address,
                        DESC_DEV,
                        0,
                        (&mut *desc_dev as *mut DeviceDescriptor) as usize,
                        mem::size_of_val(&*desc_dev));
        debugln!("{:#?}", *desc_dev);

        for configuration in 0..(*desc_dev).configurations {
            let desc_cfg_len = 1023;
            let desc_cfg_buf = memory::alloc(desc_cfg_len) as *mut u8;
            for i in 0..desc_cfg_len as isize {
                ptr::write(desc_cfg_buf.offset(i), 0);
            }
            self.descriptor(address,
                            DESC_CFG,
                            configuration,
                            desc_cfg_buf as usize,
                            desc_cfg_len);

            let desc_cfg = ptr::read(desc_cfg_buf as *const ConfigDescriptor);
            debugln!("{:#?}", desc_cfg);

            let mut hid = false;

            let mut i = desc_cfg.length as isize;
            while i < desc_cfg.total_length as isize {
                let length = ptr::read(desc_cfg_buf.offset(i));
                let descriptor_type = ptr::read(desc_cfg_buf.offset(i + 1));
                match descriptor_type {
                    DESC_INT => {
                        let desc_int = ptr::read(desc_cfg_buf.offset(i) as *const InterfaceDescriptor);
                        debugln!("{:#?}", desc_int);
                    }
                    DESC_END => {
                        let desc_end = ptr::read(desc_cfg_buf.offset(i) as *const EndpointDescriptor);
                        debugln!("{:#?}", desc_end);

                        let endpoint = desc_end.address & 0xF;
                        let in_len = desc_end.max_packet_size as usize;

                        if hid {
                            let this = self as *mut Uhci;
                            Context::spawn("kuhci_hid".to_string(), box move || {
                                debugln!("Starting HID driver");

                                let in_ptr = memory::alloc(in_len) as *mut u8;

                                loop {
                                    for i in 0..in_len as isize {
                                        ptr::write(in_ptr.offset(i), 0);
                                    }

                                    if (*this).msg(address, endpoint, &[
                                        UsbMsg::In(&mut slice::from_raw_parts_mut(in_ptr, in_len))
                                    ]) > 0 {
                                        let buttons = ptr::read(in_ptr.offset(0) as *const u8) as usize;
                                        let x = ptr::read(in_ptr.offset(1) as *const u16) as usize;
                                        let y = ptr::read(in_ptr.offset(3) as *const u16) as usize;

                                        let mode_info = &*VBEMODEINFO;
                                        let mouse_x = (x * mode_info.xresolution as usize) / 32768;
                                        let mouse_y = (y * mode_info.yresolution as usize) / 32768;

                                        let mouse_event = MouseEvent {
                                            x: cmp::max(0, cmp::min(mode_info.xresolution as i32 - 1, mouse_x as i32)),
                                            y: cmp::max(0, cmp::min(mode_info.yresolution as i32 - 1, mouse_y as i32)),
                                            left_button: buttons & 1 == 1,
                                            middle_button: buttons & 4 == 4,
                                            right_button: buttons & 2 == 2,
                                        };
                                        ::env().events.lock().push_back(mouse_event.to_event());
                                    }

                                    Duration::new(0, 10 * time::NANOS_PER_MILLI).sleep();
                                }
                            });
                        }
                    }
                    DESC_HID => {
                        let desc_hid = &*(desc_cfg_buf.offset(i) as *const HIDDescriptor);
                        debugln!("{:#?}", desc_hid);
                        hid = true;
                    }
                    _ => {
                        debugln!("Unknown Descriptor Length {} Type {:X}", length as usize, descriptor_type);
                    }
                }
                i += length as isize;
            }

            memory::unalloc(desc_cfg_buf as usize);
        }
    }

    pub unsafe fn init(&mut self) {
        debugln!("UHCI on: {:X}, IRQ: {:X}", self.base, self.irq);

        let base = self.base as u16;
        let usbcmd = base;
        let usbsts = base + 02;
        let usbintr = base + 0x4;
        let frnum = base + 0x6;
        let flbaseadd = base + 0x8;
        let portsc1 = base + 0x10;
        let portsc2 = base + 0x12;

        debug::d(" CMD ");
        debug::dh(inw(usbcmd) as usize);
        outw(usbcmd, 1 << 2 | 1 << 1);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        outw(usbcmd, 0);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        debug::d(" STS ");
        debug::dh(inw(usbsts) as usize);

        debug::d(" INTR ");
        debug::dh(inw(usbintr) as usize);

        debug::d(" FRNUM ");
        debug::dh(inw(frnum) as usize);
        outw(frnum, 0);
        debug::d(" to ");
        debug::dh(inw(frnum) as usize);

        debug::d(" FLBASEADD ");
        debug::dh(ind(flbaseadd) as usize);
        for i in 0..1024 {
            self.frame_list.write(i, 1);
        }
        outd(flbaseadd, self.frame_list.address() as u32);
        debug::d(" to ");
        debug::dh(ind(flbaseadd) as usize);

        debug::d(" CMD ");
        debug::dh(inw(usbcmd) as usize);
        outw(usbcmd, 1);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        debug::dl();

        {
            debug::d(" PORTSC1 ");
            debug::dh(inw(portsc1) as usize);

            outw(portsc1, 1 << 9);
            debug::d(" to ");
            debug::dh(inw(portsc1) as usize);

            outw(portsc1, 0);
            debug::d(" to ");
            debug::dh(inw(portsc1) as usize);

            debug::dl();

            if inw(portsc1) & 1 == 1 {
                debug::d(" Device Found ");
                debug::dh(inw(portsc1) as usize);

                outw(portsc1, 4);
                debug::d(" to ");
                debug::dh(inw(portsc1) as usize);
                debug::dl();

                self.device(1);
            }
        }

        {
            debug::d(" PORTSC2 ");
            debug::dh(inw(portsc2) as usize);

            outw(portsc2, 1 << 9);
            debug::d(" to ");
            debug::dh(inw(portsc2) as usize);

            outw(portsc2, 0);
            debug::d(" to ");
            debug::dh(inw(portsc2) as usize);

            debug::dl();

            if inw(portsc2) & 1 == 1 {
                debug::d(" Device Found ");
                debug::dh(inw(portsc2) as usize);

                outw(portsc2, 4);
                debug::d(" to ");
                debug::dh(inw(portsc2) as usize);
                debug::dl();

                self.device(2);
            }
        }
    }
}
<|endoftext|>


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

use style::{StyledNode, Inline, Block, DisplayNone};
use css::{Keyword, Length, Px};
use std::default::Default;
use std::iter::AdditiveIterator; // for `sum`

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

#[deriving(Default, Show)]
pub struct Dimensions {
    // Top left corner of the content area, relative to the document origin:
    pub x: f32,
    pub y: f32,

    // Content area size:
    pub width: f32,
    pub height: f32,

    // Surrounding edges:
    pub padding: EdgeSizes,
    pub border: EdgeSizes,
    pub margin: EdgeSizes,
}

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

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

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

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

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

/// Transform a style tree into a layout tree.
pub fn layout_tree<'a>(node: &'a StyledNode<'a>, containing_block: Dimensions) -> LayoutBox<'a> {
    let mut root_box = build_layout_tree(node);
    root_box.layout(containing_block);
    return root_box;
}

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

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

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

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

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

        // Recursively lay out the children of this node within its content area.
        self.layout_block_children();

        // Parent height can depend on child height, so `calculate_height` must be called after the
        // content layout is finished.
        self.calculate_block_height();
    }

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

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

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

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

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

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

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

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

        // Adjust used values so that the above sum equals `containing_block.width`.
        // Each arm of the `match` should increase the total width by exactly `underflow`,
        // and afterward all values should be absolute lengths in px.
        let underflow = containing_block.width - total;
        match (width == auto, margin_left == auto, margin_right == auto) {
            // If the values are overconstrained, calculate margin_right.
            (false, false, false) => {
                margin_right = Length(margin_right.to_px() + underflow, Px);
            }
            // If exactly one value is auto, its used value follows from the equality.
            (false, false, true) => {
                margin_right = Length(underflow, Px);
            }
            (false, true, false) => {
                margin_left = Length(underflow, Px);
            }
            // If width is set to auto, any other auto values become 0.
            (true, _, _) => {
                if margin_left == auto {
                    margin_left = Length(0.0, Px);
                }
                if margin_right == auto {
                    margin_right = Length(0.0, Px);
                }

                if underflow >= 0.0 {
                    // Expand width to fill the underflow.
                    width = Length(underflow, Px);
                } else {
                    // Width can't be negative. Adjust the right margin instead.
                    width = Length(0.0, Px);
                    margin_right = Length(margin_right.to_px() + underflow, Px);
                }
            }
            // If margin-left and margin-right are both auto, their used values are equal.
            (false, true, true) => {
                margin_left = Length(underflow / 2.0, Px);
                margin_right = Length(underflow / 2.0, Px);
            }
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

impl Dimensions {
    /// Total height of a box including its margins, border, and padding.
    fn margin_box_height(&self) -> f32 {
        self.height + self.padding.top + self.padding.bottom
                    + self.border.top + self.border.bottom
                    + self.margin.top + self.margin.bottom
    }
}
<commit_msg>Update comment on layout_block_children<commit_after>///! Basic CSS block layout.

use style::{StyledNode, Inline, Block, DisplayNone};
use css::{Keyword, Length, Px};
use std::default::Default;
use std::iter::AdditiveIterator; // for `sum`

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

#[deriving(Default, Show)]
pub struct Dimensions {
    // Top left corner of the content area, relative to the document origin:
    pub x: f32,
    pub y: f32,

    // Content area size:
    pub width: f32,
    pub height: f32,

    // Surrounding edges:
    pub padding: EdgeSizes,
    pub border: EdgeSizes,
    pub margin: EdgeSizes,
}

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

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

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

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

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

/// Transform a style tree into a layout tree.
pub fn layout_tree<'a>(node: &'a StyledNode<'a>, containing_block: Dimensions) -> LayoutBox<'a> {
    let mut root_box = build_layout_tree(node);
    root_box.layout(containing_block);
    return root_box;
}

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

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

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

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

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

        // Recursively lay out the children of this node within its content area.
        self.layout_block_children();

        // Parent height can depend on child height, so `calculate_height` must be called after the
        // content layout is finished.
        self.calculate_block_height();
    }

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

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

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

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

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

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

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

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

        // Adjust used values so that the above sum equals `containing_block.width`.
        // Each arm of the `match` should increase the total width by exactly `underflow`,
        // and afterward all values should be absolute lengths in px.
        let underflow = containing_block.width - total;
        match (width == auto, margin_left == auto, margin_right == auto) {
            // If the values are overconstrained, calculate margin_right.
            (false, false, false) => {
                margin_right = Length(margin_right.to_px() + underflow, Px);
            }
            // If exactly one value is auto, its used value follows from the equality.
            (false, false, true) => {
                margin_right = Length(underflow, Px);
            }
            (false, true, false) => {
                margin_left = Length(underflow, Px);
            }
            // If width is set to auto, any other auto values become 0.
            (true, _, _) => {
                if margin_left == auto {
                    margin_left = Length(0.0, Px);
                }
                if margin_right == auto {
                    margin_right = Length(0.0, Px);
                }

                if underflow >= 0.0 {
                    // Expand width to fill the underflow.
                    width = Length(underflow, Px);
                } else {
                    // Width can't be negative. Adjust the right margin instead.
                    width = Length(0.0, Px);
                    margin_right = Length(margin_right.to_px() + underflow, Px);
                }
            }
            // If margin-left and margin-right are both auto, their used values are equal.
            (false, true, true) => {
                margin_left = Length(underflow / 2.0, Px);
                margin_right = Length(underflow / 2.0, Px);
            }
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

impl Dimensions {
    /// Total height of a box including its margins, border, and padding.
    fn margin_box_height(&self) -> f32 {
        self.height + self.padding.top + self.padding.bottom
                    + self.border.top + self.border.bottom
                    + self.margin.top + self.margin.bottom
    }
}
<|endoftext|>


<commit_before>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) 2015, Ben Segall <talchas@gmail.com>
// Copyright (c) 2015, Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.
#![cfg(target_os = "linux")]
#![feature(test)]
#![feature(thread_local)]
#![feature(asm)]
extern crate fringe;
extern crate test;
use fringe::Context;
use test::black_box;

#[thread_local]
static mut ctx_slot: *mut Context<fringe::OsStack> = 0 as *mut Context<_>;

const FE_DIVBYZERO: i32 = 0x4;
extern {
  fn feenableexcept(except: i32) -> i32;
}

#[test]
#[ignore]
fn fpe() {
  unsafe extern "C" fn universe_destroyer(_arg: usize) -> ! {
    loop {
        println!("{:?}", 1.0/black_box(0.0));
        Context::swap(ctx_slot, ctx_slot, 0);
    }
  }

  unsafe {
    let stack = fringe::OsStack::new(4 << 20).unwrap();
    let mut ctx = Context::new(stack, universe_destroyer);
    ctx_slot = &mut ctx;

    Context::swap(ctx_slot, ctx_slot, 0);
    feenableexcept(FE_DIVBYZERO);
    Context::swap(ctx_slot, ctx_slot, 0);
  }
}
<commit_msg>Remove copyright year<commit_after>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) Ben Segall <talchas@gmail.com>
// Copyright (c) Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.
#![cfg(target_os = "linux")]
#![feature(test)]
#![feature(thread_local)]
#![feature(asm)]
extern crate fringe;
extern crate test;
use fringe::Context;
use test::black_box;

#[thread_local]
static mut ctx_slot: *mut Context<fringe::OsStack> = 0 as *mut Context<_>;

const FE_DIVBYZERO: i32 = 0x4;
extern {
  fn feenableexcept(except: i32) -> i32;
}

#[test]
#[ignore]
fn fpe() {
  unsafe extern "C" fn universe_destroyer(_arg: usize) -> ! {
    loop {
        println!("{:?}", 1.0/black_box(0.0));
        Context::swap(ctx_slot, ctx_slot, 0);
    }
  }

  unsafe {
    let stack = fringe::OsStack::new(4 << 20).unwrap();
    let mut ctx = Context::new(stack, universe_destroyer);
    ctx_slot = &mut ctx;

    Context::swap(ctx_slot, ctx_slot, 0);
    feenableexcept(FE_DIVBYZERO);
    Context::swap(ctx_slot, ctx_slot, 0);
  }
}
<|endoftext|>


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


<commit_before><commit_msg>Add tests for log functions<commit_after>extern crate glib;

use glib::*;

use std::sync::{Arc, Mutex};

#[derive(Default)]
struct Counters {
    errors: usize,
    criticals: usize,
    warnings: usize,
    messages: usize,
    infos: usize,
    debugs: usize,
}

fn assert_counts(
    count: &Arc<Mutex<Counters>>,
    errors: usize,
    criticals: usize,
    warnings: usize,
    messages: usize,
    infos: usize,
    debugs: usize,
) {
    let count = count.lock().expect("failed to lock 1");
    assert_eq!(count.errors, errors);
    assert_eq!(count.criticals, criticals);
    assert_eq!(count.warnings, warnings);
    assert_eq!(count.messages, messages);
    assert_eq!(count.infos, infos);
    assert_eq!(count.debugs, debugs);
}

#[test]
fn check_log_set_default_handler() {
    let count = Arc::new(Mutex::new(Counters::default()));
    log_set_default_handler(clone!(@strong count => move |_, level, _| {
        match level {
            LogLevel::Error => { (*count.lock().expect("failed to lock 2")).errors += 1; }
            LogLevel::Critical => { (*count.lock().expect("failed to lock 3")).criticals += 1; }
            LogLevel::Warning => { (*count.lock().expect("failed to lock 4")).warnings += 1; }
            LogLevel::Message => { (*count.lock().expect("failed to lock 5")).messages += 1; }
            LogLevel::Info => { (*count.lock().expect("failed to lock 6")).infos += 1; }
            LogLevel::Debug => { (*count.lock().expect("failed to lock 7")).debugs += 1; }
        }
    }));
    assert_counts(&count, 0, 0, 0, 0, 0, 0);
    g_error!("domain", "hello");
    assert_counts(&count, 1, 0, 0, 0, 0, 0);
    g_error!("domain", "hello");
    g_critical!("domain", "hello");
    g_warning!("domain", "hello");
    g_message!("domain", "hello");
    g_info!("domain", "hello");
    g_debug!("domain", "hello");
    g_info!("domain", "hello");
    assert_counts(&count, 2, 1, 1, 1, 2, 1);

    // We now unset our callback and check if it has really been unset.
    log_unset_default_handler();
    g_info!("domain", "hello");
    g_debug!("domain", "hello");
    assert_counts(&count, 2, 1, 1, 1, 2, 1);
}
<|endoftext|>


<commit_before><commit_msg>Add test extracted from rand, checking that StorageDead kills loans<commit_after>// Whenever a `StorageDead` MIR statement destroys a value `x`,
// we should kill all loans of `x`. This is extracted from `rand 0.4.6`,
// is correctly accepted by NLL but was incorrectly rejected by
// Polonius because of these missing `killed` facts.

// build-pass
// compile-flags: -Z borrowck=mir -Z polonius
// ignore-compare-mode-nll

use std::{io, mem};
use std::io::Read;

fn fill(r: &mut Read, mut buf: &mut [u8]) -> io::Result<()> {
    while buf.len() > 0 {
        match r.read(buf).unwrap() {
            0 => return Err(io::Error::new(io::ErrorKind::Other,
                                           "end of file reached")),
            n => buf = &mut mem::replace(&mut buf, &mut [])[n..],
            // ^- Polonius had multiple errors on the previous line (where NLL has none)
            // as it didn't know `buf` was killed here, and would
            // incorrectly reject both the borrow expression, and the assignment.
        }
    }
    Ok(())
}

fn main() {
}
<|endoftext|>


<commit_before><commit_msg>refactor: Make chain manipulation in-place<commit_after><|endoftext|>


<commit_before><commit_msg>Fixup for previous commit<commit_after><|endoftext|>


<commit_before><commit_msg>Added missing result module<commit_after>use std::io;
use std::fmt;

pub enum PartialResult<T, E1, E2> {
    Success(T),
    PartialSuccess(T, E1),
    Failure(E2)
}

impl<T, E1, E2> PartialResult<T, E1, E2> {
    pub fn to_result(self) -> Result<T, E2> {
        match self {
            Success(value) | PartialSuccess(value, _) => Ok(value),
            Failure(e) => Err(e)
        }
    }
}

pub type MarkdownResult<T> = PartialResult<T, MarkdownError, MarkdownError>;

pub enum MarkdownError {
    ParseError(&'static str),
    IoError(io::IoError)
}

impl fmt::Show for MarkdownError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseError(ref msg) => write!(f, "parse error: {}", msg),
            IoError(ref err) => write!(f, "i/o error: {}", err)
        }
    }
}

impl MarkdownError {
    #[inline]
    pub fn from_io(err: io::IoError) -> MarkdownError {
         IoError(err)
    }
}
<|endoftext|>


<commit_before><commit_msg>Bonus time concept implemented<commit_after><|endoftext|>


<commit_before><commit_msg>Compile for redox<commit_after><|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::io::{stdout, Write};

use super::peg::Job;
use super::input_editor::readln;

pub struct Variables {
    variables: BTreeMap<String, String>,
}

impl Variables {
    pub fn new() -> Variables {
        Variables { variables: BTreeMap::new() }
    }

    pub fn read(&mut self, args: &[String]) {
        let mut out = stdout();
        for i in 1..args.len() {
            if let Some(arg_original) = args.get(i) {
                let arg = arg_original.trim();
                print!("{}=", arg);
                if let Err(message) = out.flush() {
                    println!("{}: Failed to flush stdout", message);
                }
                if let Some(value_original) = readln() {
                    let value = value_original.trim();
                    self.set_var(arg, value);
                }
            }
        }
    }

    pub fn let_(&mut self, args: &[String]) {
        match (args.get(1), args.get(2)) {
            (Some(key), Some(value)) => {
                self.variables.insert(key.clone(), value.clone());
            }
            (Some(key), None) => {
                self.variables.remove(key);
            }
            _ => {
                for (key, value) in self.variables.iter() {
                    println!("{}={}", key, value);
                }
            }
        }
    }

    pub fn set_var(&mut self, name: &str, value: &str) {
        if !name.is_empty() {
            if value.is_empty() {
                self.variables.remove(&name.to_string());
            } else {
                self.variables.insert(name.to_string(), value.to_string());
            }
        }
    }

    pub fn expand_variables(&self, jobs: &mut [Job]) {
        for mut job in &mut jobs[..] {
            job.command = self.expand_string(&job.command).to_string();
            job.args = job.args
                          .iter()
                          .map(|original: &String| self.expand_string(&original).to_string())
                          .collect();
        }
    }

    #[inline]
    fn expand_string<'a>(&'a self, original: &'a str) -> &'a str {
        if original.starts_with("$") {
            if let Some(value) = self.variables.get(&original[1..]) {
                &value
            } else {
                ""
            }
        } else {
            original
        }
    }
}
<commit_msg>Remove bindings, no need to cache<commit_after>use std::collections::BTreeMap;
use std::io::{stdout, Write};

use super::peg::Job;
use super::input_editor::readln;

pub struct Variables {
    variables: BTreeMap<String, String>,
}

impl Variables {
    pub fn new() -> Variables {
        Variables { variables: BTreeMap::new() }
    }

    pub fn read(&mut self, args: &[String]) {
        let mut out = stdout();
        for i in 1..args.len() {
            if let Some(arg) = args.get(i) {
                print!("{}=", arg.trim());
                if let Err(message) = out.flush() {
                    println!("{}: Failed to flush stdout", message);
                }
                if let Some(value) = readln() {
                    self.set_var(arg, value.trim());
                }
            }
        }
    }

    pub fn let_(&mut self, args: &[String]) {
        match (args.get(1), args.get(2)) {
            (Some(key), Some(value)) => {
                self.variables.insert(key.clone(), value.clone());
            }
            (Some(key), None) => {
                self.variables.remove(key);
            }
            _ => {
                for (key, value) in self.variables.iter() {
                    println!("{}={}", key, value);
                }
            }
        }
    }

    pub fn set_var(&mut self, name: &str, value: &str) {
        if !name.is_empty() {
            if value.is_empty() {
                self.variables.remove(&name.to_string());
            } else {
                self.variables.insert(name.to_string(), value.to_string());
            }
        }
    }

    pub fn expand_variables(&self, jobs: &mut [Job]) {
        for mut job in &mut jobs[..] {
            job.command = self.expand_string(&job.command).to_string();
            job.args = job.args
                          .iter()
                          .map(|original: &String| self.expand_string(&original).to_string())
                          .collect();
        }
    }

    #[inline]
    fn expand_string<'a>(&'a self, original: &'a str) -> &'a str {
        if original.starts_with("$") {
            if let Some(value) = self.variables.get(&original[1..]) {
                &value
            } else {
                ""
            }
        } else {
            original
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>derive_common: Fix example in documentation<commit_after><|endoftext|>


<commit_before><commit_msg>added barrier sync test<commit_after>extern crate timely;

use timely::dataflow::channels::pact::Pipeline;
use timely::progress::timestamp::RootTimestamp;

use timely::dataflow::operators::{LoopVariable, ConnectLoop};
use timely::dataflow::operators::generic::unary::Unary;

#[test]
fn barrier_sync() {
    timely::example(|scope| {
        let (handle, stream) = scope.loop_variable::<u64>(100, 1);
        stream.unary_notify(
            Pipeline,
            "Barrier",
            vec![RootTimestamp::new(0)],
            move |_, _, notificator| {
                let mut once = true;
                while let Some((cap, _count)) = notificator.next() {
                    assert!(once);
                    once = false;
                    let mut time = cap.time().clone();
                    time.inner += 1;
                    if time.inner < 100 {
                        notificator.notify_at(cap.delayed(&time));
                    }
                }
            }
        )
        .connect_loop(handle);
    }); // asserts error-free execution;
}
<|endoftext|>


<commit_before><commit_msg>Rust file write study source code<commit_after>/**
 * author: KBuild<qwer7995@gmail.com>
 * desc: file save example
 */

#![feature(io)] // use old_io
#![feature(path)] // use file path
#![feature(core)] // use as_slice

use std::old_io::{File, Append, ReadWrite};
use std::old_io::stdin;
use std::str::FromStr;

struct Book {
	name : String,
	cost : u32,
}

impl Book {
	fn new(_name: String, _cost: u32) -> Book{
		Book{ name : _name, cost : _cost}
	}

	fn get_name(&self) -> &String {
		&self.name
	}

	fn get_cost(&self) -> u32 {
		self.cost
	}

	fn to_string(&self) -> String {
		let mut ret = String::new();
		ret.push_str(self.name.as_slice());
		ret.push_str(",");
		ret.push_str(self.cost.to_string().as_slice());
		ret
	}
}

fn main() {

	let p = Path::new("data.txt");

	let mut file = match File::open_mode(&p, Append, ReadWrite) {
		Ok(f) => f,
		Err(e) => panic!("file error: {}", e),
	};

	print!("Input Book's name : ");
	let inputn = stdin().read_line().ok().expect("Fail to read line");
	let name: String = FromStr::from_str(inputn.trim()).unwrap();

	print!("Input Book's cost : ");
	let inputc = stdin().read_line().ok().expect("Fail to read line");
	let cost: u32 = FromStr::from_str(inputc.trim()).unwrap();

	let book = Book::new(name, cost);
	println!("{}, {} saved", book.get_name(), book.get_cost());
	file.write_str(book.to_string().as_slice());
	file.write_str("\n");

/*
 	let book1 = Book::new("옥상의 민들레꽃", 10000);
	let book2 = Book::new("동의보감", 300000);

	file.write_str(book1.to_string().as_slice());
	file.write_str("\n");
	file.write_str(book2.to_string().as_slice());
	file.write_str("\n");
*/
}
<|endoftext|>


<commit_before><commit_msg>Implement `Default` for `NameSp` manually due to some issues.<commit_after><|endoftext|>


<commit_before><commit_msg>Add skeleton code for HashJoinExec.<commit_after>use common::types::Ty;
use driver::DriverContext;
use super::{Executor, ExecutorFactory};

pub struct HashJoinExecFactory
{
	types: Vec<Ty>
}

impl HashJoinExecFactory
{
	pub fn new(lf: Box<ExecutorFactory>, rf: Box<ExecutorFactory>) -> HashJoinExecFactory
	{
		HashJoinExecFactory {
			types: Vec::new()
		}
	}
}

impl ExecutorFactory for HashJoinExecFactory
{
	fn create(&self, ctx: &DriverContext) -> Option<Box<Executor>>
	{
		None
	}

	fn types(&self) -> &Vec<Ty>
	{
		&self.types
	}
}

pub struct HashJoinExec;<|endoftext|>


<commit_before>use super::*;
use redox::prelude::v1::*;
use redox::fs::File;
use redox::io::Read;

pub enum OpenStatus {
    Ok,
    NotFound,
}

impl Editor {
    /// Open a file
    pub fn open(&mut self, path: &str) -> OpenStatus {
        if let Some(mut file) = File::open(path) {
            let mut con = String::new();
            file.read_to_string(&mut con);

            self.text = con.lines().map(|x| x.chars().collect::<VecDeque<char>>()).collect::<VecDeque<VecDeque<char>>>();

            OpenStatus::Ok
        } else {
            OpenStatus::NotFound
        }
    }
}
<commit_msg>Show file name in status bar<commit_after>use super::*;
use redox::prelude::v1::*;
use redox::fs::File;
use redox::io::Read;

pub enum OpenStatus {
    Ok,
    NotFound,
}

impl Editor {
    /// Open a file
    pub fn open(&mut self, path: &str) -> OpenStatus {
        self.status_bar.file = path.to_string();
        if let Some(mut file) = File::open(path) {
            let mut con = String::new();
            file.read_to_string(&mut con);

            self.text = con.lines().map(|x| x.chars().collect::<VecDeque<char>>()).collect::<VecDeque<VecDeque<char>>>();

            OpenStatus::Ok
        } else {
            OpenStatus::NotFound
        }

    }
}
<|endoftext|>


<commit_before><commit_msg> adding the build config<commit_after>extern crate gcc;

fn main () {
    println!("cargo:rustc-flags=-lstdc++");
}
<|endoftext|>


<commit_before><commit_msg>Solve Salary in rust<commit_after>use std::io;

fn main() {
    let mut input_a = String::new();
    let mut input_b = String::new();
    let mut input_c = String::new();

    if let Err(_e) = io::stdin().read_line(&mut input_a){}
    let a: i32 = input_a.trim().parse().unwrap();

    if let Err(_e) = io::stdin().read_line(&mut input_b){}
    let b: f64 = input_b.trim().parse().unwrap();

    if let Err(_e) = io::stdin().read_line(&mut input_c){}
    let c: f64 = input_c.trim().parse().unwrap();

    println!("NUMBER = {}", a);
    println!("SALARY = U$ {:.2}", b * c);
}
<|endoftext|>


<commit_before><commit_msg>Use Macros To Simplify String Method Handling<commit_after><|endoftext|>


<commit_before><commit_msg>Update (7 kyu) Remove duplicate words.rs<commit_after><|endoftext|>


<commit_before><commit_msg>rustfmt<commit_after><|endoftext|>


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

fn main() {
    match ("", 1u) {
        (_, 42u) => (),
        ("", _) => (),
        _ => ()
    }
}
<commit_msg>Ignore issue-14393 on Windows<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-win32: FIXME #13793

fn main() {
    match ("", 1u) {
        (_, 42u) => (),
        ("", _) => (),
        _ => ()
    }
}
<|endoftext|>


<commit_before><commit_msg>Auto merge of #34243 - c3st7n:add_test_issue_issue_23477, r=nagisa<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compiler-flags: -g

pub struct Dst {
    pub a: (),
    pub b: (),
    pub data: [u8],
}

pub unsafe fn borrow(bytes: &[u8]) -> &Dst {
    let dst: &Dst = std::mem::transmute((bytes.as_ptr(), bytes.len()));
    dst
}

fn main() {}
<|endoftext|>


<commit_before><commit_msg>add missing automation.rs<commit_after>extern crate num;
use self::num::complex::Complex32;

/// describes an automation of the form:
/// y = coeff * exp(i*wt*t) * exp(i*ww*w)
/// where coeff is a complex exponential, which is used to encode both the
/// amplitude and phase shift of the sinusoid.
/// wt (omega) is the frequency of the automation,
/// and ww (omega_w) is the modulation parameter.
/// w is substituted with the partial's wt upon multiplication.
#[derive(Clone, Copy, Debug)]
pub struct Automation {
    /// complex amplitude coefficient
    coeff : Complex32,
    /// frequency of the sinusoid, in radians/second
    omega : f32,
    /// modulation frequency (used in binary operations)
    omega_w : f32,
}

impl Automation {
    pub fn new(coeff : Complex32, omega : f32, omega_w : f32) -> Automation {
        Automation{
            coeff: coeff,
            omega: omega,
            omega_w: omega_w
        }
    }
    pub fn coeff(&self) -> Complex32 {
        self.coeff
    }
    pub fn omega(&self) -> f32 {
        self.omega
    }
    pub fn omega_w(&self) -> f32 {
        self.omega_w
    }
}<|endoftext|>


<commit_before><commit_msg>Synchronise only the uniform buffers that are about to be bound as descriptor sets<commit_after><|endoftext|>


<commit_before><commit_msg>Remove hardcoded Position.<commit_after><|endoftext|>


<commit_before><commit_msg>add serialize for EntityRef<commit_after><|endoftext|>


<commit_before><commit_msg>Add example: FLIC browser.<commit_after>//! FLIC browser.

extern crate flic;
extern crate sdl2;

use std::env;
use std::path::Path;
use flic::{FlicFile,RasterMut};
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::PixelFormatEnum;

const SCREEN_W: u32 = 640;
const SCREEN_H: u32 = 400;
const MIN_SCREEN_W: u32 = 320;
const MIN_SCREEN_H: u32 = 200;
const MAX_PSTAMP_W: u32 = 98;
const MAX_PSTAMP_H: u32 = 61;

fn main() {
    let dirname = env::args().nth(1);
    if dirname.is_none() {
        usage();
        return;
    }

    let dir = Path::new(dirname.as_ref().unwrap());
    if !dir.is_dir() {
        usage();
        return;
    }

    // Initialise SDL window.
    let sdl = sdl2::init().unwrap();
    let video = sdl.video().unwrap();

    let mut window
        = video.window("FLIC Browser", SCREEN_W, SCREEN_H)
        .resizable()
        .position_centered()
        .opengl()
        .build().unwrap();

    let _ = window.set_minimum_size(MIN_SCREEN_W, MIN_SCREEN_H);
    let mut renderer = window.renderer().build().unwrap();
    let mut event_pump = sdl.event_pump().unwrap();
    let mut texture = renderer.create_texture_streaming(
            PixelFormatEnum::RGB24, SCREEN_W, SCREEN_H).unwrap();

    if let Ok(entries) = dir.read_dir() {
        let mut filenames = Vec::new();
        let mut count = 0;

        // Find FLIC files by extension.
        for entry in entries {
            if entry.is_err() {
                continue;
            }

            let path = entry.unwrap().path();
            if !path.is_file() || path.extension().is_none() {
                continue;
            }

            // Surely something better is possible...
            let ext = path.extension().unwrap()
                    .to_os_string().into_string().unwrap()
                    .to_lowercase();
            if ext != "flc" && ext != "fli" {
                continue;
            }

            filenames.push(path);
        }

        filenames.sort();

        let mut buf = [0; (SCREEN_W * SCREEN_H) as usize];
        let mut pal = [0; 3 * 256];

        // Render postage stamps.
        for filename in filenames {
            let mut flic = match FlicFile::open(&filename) {
                Ok(f) => f,
                Err(e) => {
                    println!("Error loading {} -- {}",
                            filename.to_string_lossy(), e);
                    continue;
                },
            };

            let (pstamp_w, pstamp_h) = get_postage_stamp_size(
                    MAX_PSTAMP_W, MAX_PSTAMP_H,
                    flic.width() as u32, flic.height() as u32);

            let gridx = count % 6;
            let gridy = count / 6;
            let x = 27 + 102 * gridx + (MAX_PSTAMP_W - pstamp_w) / 2;
            let y =  1 +  80 * gridy + (MAX_PSTAMP_H - pstamp_h) / 2;

            {
                let mut raster = RasterMut::with_offset(
                        x as usize, y as usize,
                        pstamp_w as usize, pstamp_h as usize, SCREEN_W as usize,
                        &mut buf, &mut pal);
                if let Err(e) = flic.read_postage_stamp(&mut raster) {
                    println!("Error reading postage stamp -- {}", e);
                    continue;
                }
            }

            draw_rect(&mut buf, x - 1, y - 1, pstamp_w + 2, pstamp_h + 2);

            count = count + 1;
            if count >= 6 * 5 {
                break;
            }
        }

        pal[3 * 255 + 0] = 0x98;
        pal[3 * 255 + 1] = 0x98;
        pal[3 * 255 + 2] = 0x98;
        render_to_texture(&mut texture,
                SCREEN_W as usize, SCREEN_H as usize, &buf, &pal);
    }

    present_to_screen(&mut renderer, &texture);

    'mainloop: loop {
        if let Some(e) = event_pump.wait_event_timeout(100) {
            match e {
                Event::Quit {..}
                | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'mainloop;
                },

                _ => (),
            }
        } else {
            present_to_screen(&mut renderer, &texture);
        }
    }
}

fn usage() {
    println!("Usage: browse <directory containing FLIC files>");
}

fn get_postage_stamp_size(
        max_w: u32, max_h: u32, w: u32, h: u32)
        -> (u32, u32) {
    assert!(w > 0 && h > 0);

    let mut scale_w;
    let mut scale_h;

    if w * max_h / h > max_w {
        scale_w = max_w;
        scale_h = h * max_w / w;
    } else {
        scale_w = w * max_h / h;
        scale_h = max_h;
    }

    if scale_w <= 0 {
        scale_w = 1;
    }
    if scale_h <= 0 {
        scale_h = 1;
    }

    (scale_w, scale_h)
}

fn draw_rect(
        buf: &mut [u8], x: u32, y: u32, w: u32, h: u32) {
    let stride = SCREEN_W;
    let c = 0xFF;

    for i in x..(x + w) {
        buf[(stride * y + i) as usize] = c;
    }

    for i in y..(y + h) {
        buf[(stride * i + x) as usize] = c;
    }

    for i in y..(y + h) {
        buf[(stride * i + (x + w - 1)) as usize] = c;
    }

    for i in x..(x + w) {
        buf[(stride * (y + h - 1) + i) as usize] = c;
    }
}

fn render_to_texture(
        texture: &mut sdl2::render::Texture,
        w: usize, h: usize, buf: &[u8], pal: &[u8]) {
    texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
        for y in 0..h {
            for x in 0..w {
                let offset = pitch * y + 3 * x;
                let c = buf[w * y + x] as usize;

                buffer[offset + 0] = pal[3 * c + 0];
                buffer[offset + 1] = pal[3 * c + 1];
                buffer[offset + 2] = pal[3 * c + 2];
            }
        }
    }).unwrap();
}

fn present_to_screen(
        renderer: &mut sdl2::render::Renderer,
        texture: &sdl2::render::Texture) {
    renderer.clear();
    let _ = renderer.copy(&texture, None, None);
    renderer.present();
}
<|endoftext|>


<commit_before><commit_msg>rpc macro<commit_after>#![allow(dead_code)]
extern crate rustc_serialize;

macro_rules! rpc {
    ($server:ident: $($fn_name:ident($in_:ty) -> $out:ty;)* ) => {
        mod $server {
            use rustc_serialize::json;
            use std::net::{TcpListener, TcpStream};
            use std::thread;
            use std::io::{self, Read, Write};

            pub trait Service: Clone + Send {
                $(
                    fn $fn_name(&self, $in_) -> $out;
                )*

                fn handle_request(self, mut conn: TcpStream) -> Result<(), io::Error> {
                    let mut s = String::new();
                    try!(conn.read_to_string(&mut s));
                    let request: Request = json::decode(&s).unwrap();
                    let response = match request {
                        $(
                            Request::$fn_name(in_) => {
                                Response::$fn_name(self.$fn_name(in_))
                            }
                        )*
                    };
                    conn.write_all(json::encode(&response).unwrap().as_bytes())
                }
            }

            #[allow(non_camel_case_types)]
            #[derive(RustcEncodable, RustcDecodable)]
            enum Request {
                $(
                    $fn_name($in_),
                )*
            }

            #[allow(non_camel_case_types)]
            #[derive(RustcEncodable, RustcDecodable)]
            enum Response {
                $(
                    $fn_name($out),
                )*
            }

            pub struct Server<S: 'static + Service>(S);

            impl<S: Service> Server<S> {
                pub fn new(service: S) -> Server<S> {
                    Server(service)
                }

                pub fn serve(&self, listener: TcpListener) -> io::Error {
                    for conn in listener.incoming() {
                        let conn = match conn {
                            Err(err) => return err,
                            Ok(c) => c,
                        };
                        let service = self.0.clone();
                        thread::spawn(move || {
                            if let Err(err) = service.handle_request(conn) {
                                println!("error handling connection: {:?}", err);
                            }
                        });
                    }
                    unreachable!()
                }
            }
        }
    }
}

rpc!(my_server:
    hello(String) -> ();
    add((i32, i32)) -> i32;
);

use my_server::*;

impl Service for () {
    fn hello(&self, s: String) {
        println!("Hello, {}", s);
    }

    fn add(&self, (x, y): (i32, i32)) -> i32 {
        x + y
    }
}

fn main() {
    let server = Server::new(());
}
<|endoftext|>


<commit_before><commit_msg>adds any bound<commit_after><|endoftext|>


<commit_before>use redox::{Vec, String, ToString};
use redox::collections::{BTreeMap, VecDeque};

use super::dvaddr::DVAddr;
use super::zio;

/// MRU - Most Recently Used cache
struct Mru {
    // TODO: keep track of use counts. So mru_map becomes (use_count: u64, Vec<u8>)
    map: BTreeMap<DVAddr, (u64, Vec<u8>)>,
    queue: VecDeque<DVAddr>, // Oldest DVAddrs are at the end
    size: usize, // Max mru cache size in bytes
    used: usize, // Used bytes in mru cache
}

impl Mru {
    pub fn new() -> Self {
        Mru {
            map: BTreeMap::new(),
            queue: VecDeque::new(),
            size: 1000,
            used: 0,
        }
    }

    fn cache_block(&mut self, dva: &DVAddr, block: Vec<u8>) -> Result<Vec<u8>, String> {
        // If necessary, make room for the block in the cache
        while self.used + block.len() > self.size {
            let last_dva = match self.queue.pop_back() {
                Some(dva) => dva,
                None => return Err("No more ARC MRU items to free".to_string()),
            };
            self.map.remove(&last_dva);
            self.used -= last_dva.asize() as usize;
        }

        // Add the block to the cache
        self.used += block.len();
        self.map.insert(*dva, (1337, block));
        self.queue.push_front(*dva);
        Ok(self.map.get(dva).unwrap().1.clone())
    }
}

/// MFU - Most Frequently Used cache
struct Mfu {
    // TODO: Keep track of use counts. So mfu_map becomes (use_count: u64, Vec<u8>). Reset the use
    // count every once in a while. For instance, every 1000 reads. This will probably end up being
    // a knob for the user.
    // TODO: Keep track of minimum frequency and corresponding DVA
    map: BTreeMap<DVAddr, (u64, Vec<u8>)>,
    size: usize, // Max mfu cache size in bytes
    used: usize, // Used bytes in mfu cache
}

impl Mfu {
    pub fn new() -> Self {
        Mfu {
            map: BTreeMap::new(),
            size: 1000,
            used: 0,
        }
    }

    // TODO: cache_block. Remove the DVA with the lowest frequency
    fn cache_block(&mut self, dva: &DVAddr, block: Vec<u8>) -> Result<Vec<u8>, String> {
    }
}

// Our implementation of the Adaptive Replacement Cache (ARC) is set up to allocate
// its buffer on the heap rather than in a private pool thing. This makes it much
// simpler to implement, but defers the fragmentation problem to the heap allocator.
// We named the type `ArCache` to avoid confusion with Rust's `Arc` reference type.
pub struct ArCache {
    mru: Mru,
    mfu: Mfu,
}

impl ArCache {
    pub fn new() -> Self {
        ArCache {
            mru: Mru::new(),
            mfu: Mfu::new(),
        }
    }

    pub fn read(&mut self, reader: &mut zio::Reader, dva: &DVAddr) -> Result<Vec<u8>, String> {
        if let Some(block) = self.mru.map.get(dva) {
            // TODO: Keep track of MRU DVA use count. If it gets used a second time, move the block into
            // the MFU cache.

            // Block is cached
            return Ok(block.1.clone());
        }
        if let Some(block) = self.mfu.map.get(dva) {
            // TODO: keep track of DVA use count
            // Block is cached
            return Ok(block.1.clone());
        }

        // Block isn't cached, have to read it from disk
        let block = reader.read(dva.sector() as usize, dva.asize() as usize);

        // Blocks start in MRU cache
        self.mru.cache_block(dva, block)
    }
}
<commit_msg>Increment the blocks<commit_after>use redox::{Vec, String, ToString};
use redox::collections::{BTreeMap, VecDeque};

use super::dvaddr::DVAddr;
use super::zio;

/// MRU - Most Recently Used cache
struct Mru {
    // TODO: keep track of use counts. So mru_map becomes (use_count: u64, Vec<u8>)
    map: BTreeMap<DVAddr, (u64, Vec<u8>)>,
    queue: VecDeque<DVAddr>, // Oldest DVAddrs are at the end
    size: usize, // Max mru cache size in bytes
    used: usize, // Used bytes in mru cache
}

impl Mru {
    pub fn new() -> Self {
        Mru {
            map: BTreeMap::new(),
            queue: VecDeque::new(),
            size: 1000,
            used: 0,
        }
    }

    fn cache_block(&mut self, dva: &DVAddr, block: Vec<u8>) -> Result<Vec<u8>, String> {
        // If necessary, make room for the block in the cache
        while self.used + block.len() > self.size {
            let last_dva = match self.queue.pop_back() {
                Some(dva) => dva,
                None => return Err("No more ARC MRU items to free".to_string()),
            };
            self.map.remove(&last_dva);
            self.used -= last_dva.asize() as usize;
        }

        // Add the block to the cache
        self.used += block.len();
        self.map.insert(*dva, (0, block));
        self.queue.push_front(*dva);
        Ok(self.map.get(dva).unwrap().1.clone())
    }
}

/// MFU - Most Frequently Used cache
struct Mfu {
    // TODO: Keep track of use counts. So mfu_map becomes (use_count: u64, Vec<u8>). Reset the use
    // count every once in a while. For instance, every 1000 reads. This will probably end up being
    // a knob for the user.
    // TODO: Keep track of minimum frequency and corresponding DVA
    map: BTreeMap<DVAddr, (u64, Vec<u8>)>,
    size: usize, // Max mfu cache size in bytes
    used: usize, // Used bytes in mfu cache
}

impl Mfu {
    pub fn new() -> Self {
        Mfu {
            map: BTreeMap::new(),
            size: 1000,
            used: 0,
        }
    }

    // TODO: cache_block. Remove the DVA with the lowest frequency
    /*
    fn cache_block(&mut self, dva: &DVAddr, block: Vec<u8>) -> Result<Vec<u8>, String> {
    }
    */
}

// Our implementation of the Adaptive Replacement Cache (ARC) is set up to allocate
// its buffer on the heap rather than in a private pool thing. This makes it much
// simpler to implement, but defers the fragmentation problem to the heap allocator.
// We named the type `ArCache` to avoid confusion with Rust's `Arc` reference type.
pub struct ArCache {
    mru: Mru,
    mfu: Mfu,
}

impl ArCache {
    pub fn new() -> Self {
        ArCache {
            mru: Mru::new(),
            mfu: Mfu::new(),
        }
    }

    pub fn read(&mut self, reader: &mut zio::Reader, dva: &DVAddr) -> Result<Vec<u8>, String> {
        if let Some(block) = self.mru.map.get_mut(dva) {
            // TODO: Keep track of MRU DVA use count. If it gets used a second time, move the block into
            // the MFU cache.

            block.0 += 1;

            // Block is cached
            return Ok(block.1.clone());
        }
        if let Some(block) = self.mfu.map.get_mut(dva) {
            // TODO: keep track of DVA use count
            // Block is cached

            block.0 += 1;

            return Ok(block.1.clone());
        }

        // Block isn't cached, have to read it from disk
        let block = reader.read(dva.sector() as usize, dva.asize() as usize);

        // Blocks start in MRU cache
        self.mru.cache_block(dva, block)
    }
}
<|endoftext|>


<commit_before><commit_msg>Refactor Option<> out of most of the Vulkan renderer<commit_after><|endoftext|>


<commit_before><commit_msg>chore: extend for existent trait<commit_after><|endoftext|>


<commit_before>#[deny(non_camel_case_types)];
//! Unsafe debugging functions for inspecting values.

import unsafe::reinterpret_cast;

export debug_tydesc;
export debug_opaque;
export debug_box;
export debug_tag;
export debug_fn;
export ptr_cast;
export breakpoint;

#[abi = "cdecl"]
extern mod rustrt {
    fn debug_tydesc(td: *sys::TypeDesc);
    fn debug_opaque(td: *sys::TypeDesc, x: *());
    fn debug_box(td: *sys::TypeDesc, x: *());
    fn debug_tag(td: *sys::TypeDesc, x: *());
    fn debug_fn(td: *sys::TypeDesc, x: *());
    fn debug_ptrcast(td: *sys::TypeDesc, x: *()) -> *();
    fn rust_dbg_breakpoint();
}

fn debug_tydesc<T>() {
    rustrt::debug_tydesc(sys::get_type_desc::<T>());
}

fn debug_opaque<T>(x: T) {
    rustrt::debug_opaque(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}

fn debug_box<T>(x: @T) {
    rustrt::debug_box(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}

fn debug_tag<T>(x: T) {
    rustrt::debug_tag(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}

fn debug_fn<T>(x: T) {
    rustrt::debug_fn(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}

unsafe fn ptr_cast<T, U>(x: @T) -> @U {
    reinterpret_cast(
        rustrt::debug_ptrcast(sys::get_type_desc::<T>(),
                              reinterpret_cast(x)))
}

/// Triggers a debugger breakpoint
fn breakpoint() {
    rustrt::rust_dbg_breakpoint();
}

#[test]
fn test_breakpoint_should_not_abort_process_when_not_under_gdb() {
    // Triggering a breakpoint involves raising SIGTRAP, which terminates
    // the process under normal circumstances
    breakpoint();
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Remove deprecated modes from dbg.rs<commit_after>#[deny(non_camel_case_types)];
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
//! Unsafe debugging functions for inspecting values.

import unsafe::reinterpret_cast;

export debug_tydesc;
export debug_opaque;
export debug_box;
export debug_tag;
export debug_fn;
export ptr_cast;
export breakpoint;

#[abi = "cdecl"]
extern mod rustrt {
    fn debug_tydesc(td: *sys::TypeDesc);
    fn debug_opaque(td: *sys::TypeDesc, x: *());
    fn debug_box(td: *sys::TypeDesc, x: *());
    fn debug_tag(td: *sys::TypeDesc, x: *());
    fn debug_fn(td: *sys::TypeDesc, x: *());
    fn debug_ptrcast(td: *sys::TypeDesc, x: *()) -> *();
    fn rust_dbg_breakpoint();
}

fn debug_tydesc<T>() {
    rustrt::debug_tydesc(sys::get_type_desc::<T>());
}

fn debug_opaque<T>(+x: T) {
    rustrt::debug_opaque(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}

fn debug_box<T>(x: @T) {
    rustrt::debug_box(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}

fn debug_tag<T>(+x: T) {
    rustrt::debug_tag(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}

fn debug_fn<T>(+x: T) {
    rustrt::debug_fn(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}

unsafe fn ptr_cast<T, U>(x: @T) -> @U {
    reinterpret_cast(
        rustrt::debug_ptrcast(sys::get_type_desc::<T>(),
                              reinterpret_cast(x)))
}

/// Triggers a debugger breakpoint
fn breakpoint() {
    rustrt::rust_dbg_breakpoint();
}

#[test]
fn test_breakpoint_should_not_abort_process_when_not_under_gdb() {
    // Triggering a breakpoint involves raising SIGTRAP, which terminates
    // the process under normal circumstances
    breakpoint();
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>