<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 app_units::Au;
use webrender_traits::{FontKey, NativeFontHandle};

use freetype::freetype::{FTErrorMethods, FT_PIXEL_MODE_GRAY, FT_PIXEL_MODE_MONO};
use freetype::freetype::{FT_Done_FreeType, FT_LOAD_RENDER, FT_LOAD_MONOCHROME};
use freetype::freetype::{FT_Library, FT_Set_Char_Size};
use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6};
use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph};
use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot};

use std::{mem, ptr, slice};
use std::collections::HashMap;
//use util;

struct Face {
    face: FT_Face,
}

pub struct FontContext {
    lib: FT_Library,
    faces: HashMap<FontKey, Face>,
}

pub struct RasterizedGlyph {
    pub left: i32,
    pub top: i32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

fn float_to_fixed(before: usize, f: f64) -> i32 {
    ((1i32 << before) as f64 * f) as i32
}

fn float_to_fixed_ft(f: f64) -> i32 {
    float_to_fixed(6, f)
}

impl FontContext {
    pub fn new() -> FontContext {
//        let _pf = util::ProfileScope::new("  FontContext::new");
        let mut lib: FT_Library = ptr::null_mut();
        unsafe {
            let result = FT_Init_FreeType(&mut lib);
            if !result.succeeded() { panic!("Unable to initialize FreeType library {}", result); }
        }

        FontContext {
            lib: lib,
            faces: HashMap::new(),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
        if !self.faces.contains_key(&font_key) {
            let mut face: FT_Face = ptr::null_mut();
            let face_index = 0 as FT_Long;
            let result = unsafe {
                FT_New_Memory_Face(self.lib,
                                   bytes.as_ptr(),
                                   bytes.len() as FT_Long,
                                   face_index,
                                   &mut face)
            };
            if result.succeeded() && !face.is_null() {
                self.faces.insert(*font_key, Face {
                    face: face,
                    //_bytes: bytes
                });
            } else {
                println!("WARN: webrender failed to load font {:?}", font_key);
            }
        }
    }

    pub fn add_native_font(&mut self, _font_key: &FontKey, _native_font_handle: NativeFontHandle) {
        panic!("TODO: Not supported on Linux");
    }

    pub fn get_glyph(&mut self,
                     font_key: FontKey,
                     size: Au,
                     character: u32,
                     device_pixel_ratio: f32,
                     enable_aa: bool) -> Option<RasterizedGlyph> {
        debug_assert!(self.faces.contains_key(&font_key));

        let face = self.faces.get(&font_key).unwrap();

        unsafe {
            let char_size = float_to_fixed_ft(((0.5f64 + size.to_f64_px()) *
                                               device_pixel_ratio as f64).floor());
            let result = FT_Set_Char_Size(face.face, char_size as FT_F26Dot6, 0, 0, 0);
            assert!(result.succeeded());

            let flags = if enable_aa {
                FT_LOAD_RENDER
            } else {
                FT_LOAD_MONOCHROME | FT_LOAD_RENDER
            };
            let result =  FT_Load_Glyph(face.face, character as FT_UInt, flags);
            if result.succeeded() {

                let void_glyph = (*face.face).glyph;
                let slot: FT_GlyphSlot = mem::transmute(void_glyph);
                assert!(!slot.is_null());

                let bitmap = &(*slot).bitmap;
                debug_assert!((enable_aa && bitmap.pixel_mode as i8 == FT_PIXEL_MODE_GRAY as i8) ||
                              (!enable_aa && bitmap.pixel_mode as i8 == FT_PIXEL_MODE_MONO as i8));

                let mut final_buffer = Vec::with_capacity((bitmap.width * bitmap.rows) as usize * 4);

                if enable_aa {
                    let buffer = slice::from_raw_parts(
                        bitmap.buffer,
                        (bitmap.width * bitmap.rows) as usize
                    );

                    // Convert to RGBA.
                    for &byte in buffer.iter() {
                        final_buffer.extend_from_slice(&[ 0xff, 0xff, 0xff, byte ]);
                    }
                } else {
                    // This is not exactly efficient... but it's only used by the
                    // reftest pass when we have AA disabled on glyphs.
                    for y in 0..bitmap.rows {
                        for x in 0..bitmap.width {
                            let byte_index = (y * bitmap.pitch) + (x >> 3);
                            let bit_index = x & 7;
                            let byte_ptr = bitmap.buffer.offset(byte_index as isize);
                            let bit = (*byte_ptr & (128 >> bit_index)) != 0;
                            let byte_value = if bit {
                                0xff
                            } else {
                                0
                            };
                            final_buffer.extend_from_slice(&[ 0xff, 0xff, 0xff, byte_value ]);
                        }
                    }
                }

                let glyph = RasterizedGlyph {
                    left: (*slot).bitmap_left as i32,
                    top: (*slot).bitmap_top as i32,
                    width: bitmap.width as u32,
                    height: bitmap.rows as u32,
                    bytes: final_buffer.to_vec(),
                };

                Some(glyph)
            } else {
                None
            }
        }
    }
}

impl Drop for FontContext {
    fn drop(&mut self) {
        unsafe {
            FT_Done_FreeType(self.lib);
        }
    }
}
<commit_msg>Auto merge of #476 - jrmuizel:glyph-copy, r=glennw<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 app_units::Au;
use webrender_traits::{FontKey, NativeFontHandle};

use freetype::freetype::{FTErrorMethods, FT_PIXEL_MODE_GRAY, FT_PIXEL_MODE_MONO};
use freetype::freetype::{FT_Done_FreeType, FT_LOAD_RENDER, FT_LOAD_MONOCHROME};
use freetype::freetype::{FT_Library, FT_Set_Char_Size};
use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6};
use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph};
use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot};

use std::{mem, ptr, slice};
use std::collections::HashMap;
//use util;

struct Face {
    face: FT_Face,
}

pub struct FontContext {
    lib: FT_Library,
    faces: HashMap<FontKey, Face>,
}

pub struct RasterizedGlyph {
    pub left: i32,
    pub top: i32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

fn float_to_fixed(before: usize, f: f64) -> i32 {
    ((1i32 << before) as f64 * f) as i32
}

fn float_to_fixed_ft(f: f64) -> i32 {
    float_to_fixed(6, f)
}

impl FontContext {
    pub fn new() -> FontContext {
//        let _pf = util::ProfileScope::new("  FontContext::new");
        let mut lib: FT_Library = ptr::null_mut();
        unsafe {
            let result = FT_Init_FreeType(&mut lib);
            if !result.succeeded() { panic!("Unable to initialize FreeType library {}", result); }
        }

        FontContext {
            lib: lib,
            faces: HashMap::new(),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
        if !self.faces.contains_key(&font_key) {
            let mut face: FT_Face = ptr::null_mut();
            let face_index = 0 as FT_Long;
            let result = unsafe {
                FT_New_Memory_Face(self.lib,
                                   bytes.as_ptr(),
                                   bytes.len() as FT_Long,
                                   face_index,
                                   &mut face)
            };
            if result.succeeded() && !face.is_null() {
                self.faces.insert(*font_key, Face {
                    face: face,
                    //_bytes: bytes
                });
            } else {
                println!("WARN: webrender failed to load font {:?}", font_key);
            }
        }
    }

    pub fn add_native_font(&mut self, _font_key: &FontKey, _native_font_handle: NativeFontHandle) {
        panic!("TODO: Not supported on Linux");
    }

    pub fn get_glyph(&mut self,
                     font_key: FontKey,
                     size: Au,
                     character: u32,
                     device_pixel_ratio: f32,
                     enable_aa: bool) -> Option<RasterizedGlyph> {
        debug_assert!(self.faces.contains_key(&font_key));

        let face = self.faces.get(&font_key).unwrap();

        unsafe {
            let char_size = float_to_fixed_ft(((0.5f64 + size.to_f64_px()) *
                                               device_pixel_ratio as f64).floor());
            let result = FT_Set_Char_Size(face.face, char_size as FT_F26Dot6, 0, 0, 0);
            assert!(result.succeeded());

            let flags = if enable_aa {
                FT_LOAD_RENDER
            } else {
                FT_LOAD_MONOCHROME | FT_LOAD_RENDER
            };
            let result =  FT_Load_Glyph(face.face, character as FT_UInt, flags);
            if result.succeeded() {

                let void_glyph = (*face.face).glyph;
                let slot: FT_GlyphSlot = mem::transmute(void_glyph);
                assert!(!slot.is_null());

                let bitmap = &(*slot).bitmap;
                debug_assert!((enable_aa && bitmap.pixel_mode as i8 == FT_PIXEL_MODE_GRAY as i8) ||
                              (!enable_aa && bitmap.pixel_mode as i8 == FT_PIXEL_MODE_MONO as i8));

                let mut final_buffer = Vec::with_capacity((bitmap.width * bitmap.rows) as usize * 4);

                if enable_aa {
                    let buffer = slice::from_raw_parts(
                        bitmap.buffer,
                        (bitmap.width * bitmap.rows) as usize
                    );

                    // Convert to RGBA.
                    for &byte in buffer.iter() {
                        final_buffer.extend_from_slice(&[ 0xff, 0xff, 0xff, byte ]);
                    }
                } else {
                    // This is not exactly efficient... but it's only used by the
                    // reftest pass when we have AA disabled on glyphs.
                    for y in 0..bitmap.rows {
                        for x in 0..bitmap.width {
                            let byte_index = (y * bitmap.pitch) + (x >> 3);
                            let bit_index = x & 7;
                            let byte_ptr = bitmap.buffer.offset(byte_index as isize);
                            let bit = (*byte_ptr & (128 >> bit_index)) != 0;
                            let byte_value = if bit {
                                0xff
                            } else {
                                0
                            };
                            final_buffer.extend_from_slice(&[ 0xff, 0xff, 0xff, byte_value ]);
                        }
                    }
                }

                let glyph = RasterizedGlyph {
                    left: (*slot).bitmap_left as i32,
                    top: (*slot).bitmap_top as i32,
                    width: bitmap.width as u32,
                    height: bitmap.rows as u32,
                    bytes: final_buffer,
                };

                Some(glyph)
            } else {
                None
            }
        }
    }
}

impl Drop for FontContext {
    fn drop(&mut self) {
        unsafe {
            FT_Done_FreeType(self.lib);
        }
    }
}
<|endoftext|>


<commit_before>use str_arena::StrArena;

use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::{self, Debug, Formatter};
use std::marker::PhantomData;
use std::mem;

/// An interned string, represented as an index into a thread-local string interner.
#[allow(raw_pointer_derive)]
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub struct Symbol {
    index: u32,

    // Disable Send and Sync using a marker type.
    _marker: PhantomData<*const ()>,
}

impl Symbol {
    fn new(index: u32) -> Symbol {
        Symbol { index: index, _marker: PhantomData }
    }

    /// The main entry point to the interner.
    pub fn intern(string: &str) -> Symbol {
        INTERNER.with(|interner| {
            interner.borrow_mut().intern(string)
        })
    }

    pub fn with<F, R>(self, f: F) -> R where F: FnOnce(&str) -> R {
        INTERNER.with(|interner| {
            let string = interner.borrow().sym_to_str[self.index as usize];
            f(string)
        })
    }
}

impl Debug for Symbol {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        self.with(|name| write!(f, "{:?}:{}", name, self.index))
    }
}

thread_local!(static INTERNER: RefCell<Interner> = RefCell::new(Interner::new()));

#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct Interner {
    arena: StrArena,
    str_to_sym: HashMap<&'static str, Symbol>,
    sym_to_str: Vec<&'static str>,

    // Disable Send and Sync using a marker type.
    _marker: PhantomData<*const ()>,
}

impl Interner {
    fn new() -> Self {
        Interner {
            arena: StrArena::new(),
            str_to_sym: HashMap::new(),
            sym_to_str: Vec::new(),
            _marker: PhantomData,
        }
    }

    fn intern(&mut self, string: &str) -> Symbol {
        if let Some(&sym) = self.str_to_sym.get(string) {
            return sym;
        }

        let new_sym = Symbol::new(self.sym_to_str.len() as u32);
        let arena_str = self.arena.allocate(string);

        // Extend the lifetime of the slice pointer into the arena to the static lifetime. This is
        // safe because these static references never escape the interner, and dropping
        // `str_to_sym` and `sym_to_str` doesn't cause any reads of the slices (in case the arena
        // is dropped first).
        let arena_str = unsafe { mem::transmute::<&str, &'static str>(arena_str) };

        self.str_to_sym.insert(arena_str, new_sym);
        self.sym_to_str.push(arena_str);
        new_sym
    }
}
<commit_msg>allow(raw_pointer_derive) no longer needed in Rust 1.6<commit_after>use str_arena::StrArena;

use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::{self, Debug, Formatter};
use std::marker::PhantomData;
use std::mem;

/// An interned string, represented as an index into a thread-local string interner.
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub struct Symbol {
    index: u32,

    // Disable Send and Sync using a marker type.
    _marker: PhantomData<*const ()>,
}

impl Symbol {
    fn new(index: u32) -> Symbol {
        Symbol { index: index, _marker: PhantomData }
    }

    /// The main entry point to the interner.
    pub fn intern(string: &str) -> Symbol {
        INTERNER.with(|interner| {
            interner.borrow_mut().intern(string)
        })
    }

    pub fn with<F, R>(self, f: F) -> R where F: FnOnce(&str) -> R {
        INTERNER.with(|interner| {
            let string = interner.borrow().sym_to_str[self.index as usize];
            f(string)
        })
    }
}

impl Debug for Symbol {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        self.with(|name| write!(f, "{:?}:{}", name, self.index))
    }
}

thread_local!(static INTERNER: RefCell<Interner> = RefCell::new(Interner::new()));

#[derive(Debug)]
struct Interner {
    arena: StrArena,
    str_to_sym: HashMap<&'static str, Symbol>,
    sym_to_str: Vec<&'static str>,

    // Disable Send and Sync using a marker type.
    _marker: PhantomData<*const ()>,
}

impl Interner {
    fn new() -> Self {
        Interner {
            arena: StrArena::new(),
            str_to_sym: HashMap::new(),
            sym_to_str: Vec::new(),
            _marker: PhantomData,
        }
    }

    fn intern(&mut self, string: &str) -> Symbol {
        if let Some(&sym) = self.str_to_sym.get(string) {
            return sym;
        }

        let new_sym = Symbol::new(self.sym_to_str.len() as u32);
        let arena_str = self.arena.allocate(string);

        // Extend the lifetime of the slice pointer into the arena to the static lifetime. This is
        // safe because these static references never escape the interner, and dropping
        // `str_to_sym` and `sym_to_str` doesn't cause any reads of the slices (in case the arena
        // is dropped first).
        let arena_str = unsafe { mem::transmute::<&str, &'static str>(arena_str) };

        self.str_to_sym.insert(arena_str, new_sym);
        self.sym_to_str.push(arena_str);
        new_sym
    }
}
<|endoftext|>


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

extern crate alloc;

extern crate collections;

#[macro_use]
extern crate mopa;

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

use alloc::rc::*;

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

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

use graphics::bmp::*;

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

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

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

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

mod filesystems {
    pub mod unfs;
}

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

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

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

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

mod usb {
    pub mod xhci;
}

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

unsafe fn init(){
    serial_init();

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

    page_init();
    cluster_init();

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

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

    keyboard_init();
    mouse_init();

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

    pci_init(session);

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

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

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

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

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

        outb(0x20, 0x20);
    }
}

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

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

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

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

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

extern crate alloc;

extern crate collections;

#[macro_use]
extern crate mopa;

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

use alloc::rc::*;

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

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

use graphics::bmp::*;

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

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

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

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

mod filesystems {
    pub mod unfs;
}

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

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

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

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

mod usb {
    pub mod xhci;
}

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

unsafe fn init(){
    serial_init();

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

    page_init();
    cluster_init();

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

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

    keyboard_init();
    mouse_init();

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

    pci_init(session);

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

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

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

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

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

        outb(0x20, 0x20);
    }
}

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

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

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

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

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


<commit_before>use sdl2::keyboard::Keycode as Key;

#[derive(Default, Builder, Debug)]
pub struct Keypad
{
    keys: [bool; 16],
}

impl Keypad
{
    pub fn pressed(&mut self, index: usize) -> bool
    {
        self.keys[index]
    }

    pub fn press(&mut self, key: Key, state: bool)
    {
        match key
        {
            Key::Num1 => self.set_key(0x1, state),
            Key::Num2 => self.set_key(0x2, state),
            Key::Num3 => self.set_key(0x3, state),
            Key::Num4 => self.set_key(0xc, state),
            Key::Q => self.set_key(0x4, state),
            Key::W => self.set_key(0x5, state),
            Key::E => self.set_key(0x6, state),
            Key::R => self.set_key(0xd, state),
            Key::A => self.set_key(0x7, state),
            Key::S => self.set_key(0x8, state),
            Key::D => self.set_key(0x9, state),
            Key::F => self.set_key(0xe, state),
            Key::Z => self.set_key(0xa, state),
            Key::X => self.set_key(0x0, state),
            Key::C => self.set_key(0xb, state),
            Key::V => self.set_key(0xf, state),
            _ => (),
        }
    }

    fn set_key(&mut self, index: usize, state: bool)
    {
        self.keys[index] = state;
    }
}
<commit_msg>Formatting changes.<commit_after>

#[derive(Default, Builder, Debug)]
pub struct Keypad
{
    keys: [bool; 16],
}

impl Keypad
{
    pub fn pressed(&mut self, index: usize) -> bool
    {
        self.keys[index]
    }

    pub fn press(&mut self, key: Key, state: bool)
    {
        match key
        {
            use sdl2::keyboard::Keycode::*;

            Num1 => self.set_key(0x1, state),
            Num2 => self.set_key(0x2, state),
            Num3 => self.set_key(0x3, state),
            Num4 => self.set_key(0xc, state),
            Q => self.set_key(0x4, state),
            W => self.set_key(0x5, state),
            E => self.set_key(0x6, state),
            R => self.set_key(0xd, state),
            A => self.set_key(0x7, state),
            S => self.set_key(0x8, state),
            D => self.set_key(0x9, state),
            F => self.set_key(0xe, state),
            Z => self.set_key(0xa, state),
            X => self.set_key(0x0, state),
            C => self.set_key(0xb, state),
            V => self.set_key(0xf, state),
            _ => (),
        }
    }

    fn set_key(&mut self, index: usize, state: bool)
    {
        self.keys[index] = state;
    }
}
<|endoftext|>


<commit_before>//! A list of compiled transfer syntax specifiers.
//!
//! The constants exported here refer to the library's built-in support
//! for DICOM transfer syntaxes.
//!
//! **Fully implemented** means that the default transfer syntax registry
//! provides built-in support for reading and writing data sets,
//! as well as for encoding and decoding encapsulated pixel data,
//! if applicable.
//! **Stub descriptors** serve to provide information about
//! the transfer syntax,
//! and may provide partial support.
//! In most cases it will be possible to read and write data sets,
//! but not encode or decode encapsulated pixel data.
//!
//! Other crates may be developed to replace stubs,
//! hence expanding support for those transfer syntaxes
//! to the registry.

use crate::create_ts_stub;
use byteordered::Endianness;
use dicom_encoding::{
    adapters::rle_lossless::RLELosslessAdapter,
    transfer_syntax::{AdapterFreeTransferSyntax as Ts, Codec, NeverAdapter},
    TransferSyntax,
};

// -- the three base transfer syntaxes, fully supported --

/// **Fully implemented:** Implicit VR Little Endian: Default Transfer Syntax for DICOM
pub const IMPLICIT_VR_LITTLE_ENDIAN: Ts = Ts::new(
    "1.2.840.10008.1.2",
    "Implicit VR Little Endian",
    Endianness::Little,
    false,
    Codec::None,
);

/// **Fully implemented:** Explicit VR Little Endian
pub const EXPLICIT_VR_LITTLE_ENDIAN: Ts = Ts::new(
    "1.2.840.10008.1.2.1",
    "Explicit VR Little Endian",
    Endianness::Little,
    true,
    Codec::None,
);

/// **Fully implemented:** Explicit VR Big Endian
pub const EXPLICIT_VR_BIG_ENDIAN: Ts = Ts::new(
    "1.2.840.10008.1.2.2",
    "Explicit VR Big Endian",
    Endianness::Big,
    true,
    Codec::None,
);

// --- stub transfer syntaxes, known but not supported ---

/// **Stub descriptor:** Deflated Explicit VR Little Endian
pub const DEFLATED_EXPLICIT_VR_LITTLE_ENDIAN: Ts = Ts::new(
    "1.2.840.10008.1.2.1.99",
    "Deflated Explicit VR Little Endian",
    Endianness::Little,
    true,
    Codec::Unsupported,
);

/// **Stub descriptor:** JPIP Referenced Deflate
pub const JPIP_REFERENCED_DEFLATE: Ts = Ts::new(
    "1.2.840.10008.1.2.4.95",
    "JPIP Referenced Deflate",
    Endianness::Little,
    true,
    Codec::Unsupported,
);

// --- partially supported transfer syntaxes, pixel data encapsulation not supported ---

/// **Stub descriptor:** JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression
pub const JPEG_BASELINE: Ts = create_ts_stub("1.2.840.10008.1.2.4.50", "JPEG Baseline (Process 1)");
/// **Stub descriptor:** JPEG Extended (Process 2 & 4): Default Transfer Syntax for Lossy JPEG 12 Bit Image Compression (Process 4 only)
pub const JPEG_EXTENDED: Ts =
    create_ts_stub("1.2.840.10008.1.2.4.51", "JPEG Extended (Process 2 & 4)");
/// **Stub descriptor:** JPEG Lossless, Non-Hierarchical (Process 14)
pub const JPEG_LOSSLESS_NON_HIERARCHICAL: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.57",
    "JPEG Lossless, Non-Hierarchical (Process 14)",
);
/// **Stub descriptor:** JPEG Lossless, Non-Hierarchical, First-Order Prediction
/// (Process 14 [Selection Value 1]):
/// Default Transfer Syntax for Lossless JPEG Image Compression
pub const JPEG_LOSSLESS_NON_HIERARCHICAL_FIRST_ORDER_PREDICTION: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.70",
    "JPEG Lossless, Non-Hierarchical, First-Order Prediction",
);
/// **Stub descriptor:** JPEG-LS Lossless Image Compression
pub const JPEG_LS_LOSSLESS_IMAGE_COMPRESSION: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.80",
    "JPEG-LS Lossless Image Compression",
);
/// **Stub descriptor:** JPEG-LS Lossy (Near-Lossless) Image Compression
pub const JPEG_LS_LOSSY_IMAGE_COMPRESSION: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.81",
    "JPEG-LS Lossy (Near-Lossless) Image Compression",
);
/// **Stub descriptor:** JPEG 2000 Image Compression (Lossless Only)
pub const JPEG_2000_IMAGE_COMPRESSION_LOSSLESS_ONLY: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.90",
    "JPEG 2000 Image Compression (Lossless Only)",
);
/// **Stub descriptor:** JPEG 2000 Image Compression
pub const JPEG_2000_IMAGE_COMPRESSION: Ts =
    create_ts_stub("1.2.840.10008.1.2.4.91", "JPEG 2000 Image Compression");
/// **Stub descriptor:** JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)
pub const JPEG_2000_PART2_MULTI_COMPONENT_IMAGE_COMPRESSION_LOSSLESS_ONLY: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.92",
    "JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)",
);
/// **Stub descriptor:** JPEG 2000 Part 2 Multi-component Image Compression
pub const JPEG_2000_PART2_MULTI_COMPONENT_IMAGE_COMPRESSION: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.93",
    "JPEG 2000 Part 2 Multi-component Image Compression",
);
/// **Stub descriptor:** JPIP Referenced
pub const JPIP_REFERENCED: Ts = create_ts_stub("1.2.840.10008.1.2.4.94", "JPIP Referenced");

/// **Stub descriptor:** MPEG2 Main Profile / Main Level
pub const MPEG2_MAIN_PROFILE_MAIN_LEVEL: Ts =
    create_ts_stub("1.2.840.10008.1.2.4.100", "MPEG2 Main Profile / Main Level");
/// **Stub descriptor:** MPEG2 Main Profile / High Level
pub const MPEG2_MAIN_PROFILE_HIGH_LEVEL: Ts =
    create_ts_stub("1.2.840.10008.1.2.4.101", "MPEG2 Main Profile / High Level");
/// **Stub descriptor:** MPEG-4 AVC/H.264 High Profile / Level 4.1
pub const MPEG4_AVC_H264_HIGH_PROFILE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.102",
    "MPEG-4 AVC/H.264 High Profile / Level 4.1",
);
/// **Stub descriptor:** MPEG-4 AVC/H.264 BD-Compatible High Profile / Level 4.1
pub const MPEG4_AVC_H264_BD_COMPATIBLE_HIGH_PROFILE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.103",
    "MPEG-4 AVC/H.264 BD-Compatible High Profile / Level 4.1",
);
/// **Stub descriptor:** MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video
pub const MPEG4_AVC_H264_HIGH_PROFILE_FOR_2D_VIDEO: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.104",
    "MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video",
);
/// **Stub descriptor:** MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video
pub const MPEG4_AVC_H264_HIGH_PROFILE_FOR_3D_VIDEO: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.105",
    "MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video",
);
/// **Stub descriptor:** MPEG-4 AVC/H.264 High Profile / Level 4.2
pub const MPEG4_AVC_H264_STEREO_HIGH_PROFILE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.106",
    "MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2",
);
/// **Stub descriptor:** HEVC/H.265 Main Profile / Level 5.1
pub const HEVC_H265_MAIN_PROFILE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.107",
    "HEVC/H.265 Main Profile / Level 5.1",
);
/// **Stub descriptor:** HEVC/H.265 Main 10 Profile / Level 5.1
pub const HEVC_H265_MAIN_10_PROFILE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.108",
    "HEVC/H.265 Main 10 Profile / Level 5.1",
);
/// **Stub descriptor:** RLE Lossless
pub const RLE_LOSSLESS: TransferSyntax<NeverAdapter, RLELosslessAdapter> = TransferSyntax::new(
    "1.2.840.10008.1.2.5",
    "RLE Lossless",
    Endianness::Little,
    true,
    Codec::PixelData(RLELosslessAdapter {}),
);
/// **Stub descriptor:** SMPTE ST 2110-20 Uncompressed Progressive Active Video
pub const SMPTE_ST_2110_20_UNCOMPRESSED_PROGRESSIVE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.7.1",
    "SMPTE ST 2110-20 Uncompressed Progressive Active Video",
);
/// **Stub descriptor:** SMPTE ST 2110-20 Uncompressed Interlaced Active Video
pub const SMPTE_ST_2110_20_UNCOMPRESSED_INTERLACED: Ts = create_ts_stub(
    "1.2.840.10008.1.2.7.2",
    "SMPTE ST 2110-20 Uncompressed Interlaced Active Video",
);
/// **Stub descriptor:** SMPTE ST 2110-30 PCM Digital Audio
pub const SMPTE_ST_2110_30_PCM: Ts = create_ts_stub(
    "1.2.840.10008.1.2.7.3",
    "SMPTE ST 2110-30 PCM Digital Audio",
);
<commit_msg>[transfer-syntax-registry] refactor entries<commit_after>//! A list of compiled transfer syntax specifiers.
//!
//! The constants exported here refer to the library's built-in support
//! for DICOM transfer syntaxes.
//!
//! **Fully implemented** means that the default transfer syntax registry
//! provides built-in support for reading and writing data sets,
//! as well as for encoding and decoding encapsulated pixel data,
//! if applicable.
//! **Stub descriptors** serve to provide information about
//! the transfer syntax,
//! and may provide partial support.
//! In most cases it will be possible to read and write data sets,
//! but not encode or decode encapsulated pixel data.
//!
//! Other crates may be developed to replace stubs,
//! hence expanding support for those transfer syntaxes
//! to the registry.

use crate::create_ts_stub;
use byteordered::Endianness;
use dicom_encoding::{
    adapters::rle_lossless::RLELosslessAdapter,
    transfer_syntax::{AdapterFreeTransferSyntax as Ts, Codec, NeverAdapter},
    TransferSyntax,
};

// -- the three base transfer syntaxes, fully supported --

/// **Fully implemented:** Implicit VR Little Endian: Default Transfer Syntax for DICOM
pub const IMPLICIT_VR_LITTLE_ENDIAN: Ts = Ts::new(
    "1.2.840.10008.1.2",
    "Implicit VR Little Endian",
    Endianness::Little,
    false,
    Codec::None,
);

/// **Fully implemented:** Explicit VR Little Endian
pub const EXPLICIT_VR_LITTLE_ENDIAN: Ts = Ts::new(
    "1.2.840.10008.1.2.1",
    "Explicit VR Little Endian",
    Endianness::Little,
    true,
    Codec::None,
);

/// **Fully implemented:** Explicit VR Big Endian
pub const EXPLICIT_VR_BIG_ENDIAN: Ts = Ts::new(
    "1.2.840.10008.1.2.2",
    "Explicit VR Big Endian",
    Endianness::Big,
    true,
    Codec::None,
);

// -- transfer syntaxes with pixel data adapters, fully supported --

/// **Fully supported:** RLE Lossless
pub const RLE_LOSSLESS: TransferSyntax<NeverAdapter, RLELosslessAdapter> = TransferSyntax::new(
    "1.2.840.10008.1.2.5",
    "RLE Lossless",
    Endianness::Little,
    true,
    Codec::PixelData(RLELosslessAdapter),
);

// --- stub transfer syntaxes, known but not supported ---

/// **Stub descriptor:** Deflated Explicit VR Little Endian
pub const DEFLATED_EXPLICIT_VR_LITTLE_ENDIAN: Ts = Ts::new(
    "1.2.840.10008.1.2.1.99",
    "Deflated Explicit VR Little Endian",
    Endianness::Little,
    true,
    Codec::Unsupported,
);

/// **Stub descriptor:** JPIP Referenced Deflate
pub const JPIP_REFERENCED_DEFLATE: Ts = Ts::new(
    "1.2.840.10008.1.2.4.95",
    "JPIP Referenced Deflate",
    Endianness::Little,
    true,
    Codec::Unsupported,
);

// --- partially supported transfer syntaxes, pixel data encapsulation not supported ---

/// **Stub descriptor:** JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression
pub const JPEG_BASELINE: Ts = create_ts_stub("1.2.840.10008.1.2.4.50", "JPEG Baseline (Process 1)");
/// **Stub descriptor:** JPEG Extended (Process 2 & 4): Default Transfer Syntax for Lossy JPEG 12 Bit Image Compression (Process 4 only)
pub const JPEG_EXTENDED: Ts =
    create_ts_stub("1.2.840.10008.1.2.4.51", "JPEG Extended (Process 2 & 4)");
/// **Stub descriptor:** JPEG Lossless, Non-Hierarchical (Process 14)
pub const JPEG_LOSSLESS_NON_HIERARCHICAL: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.57",
    "JPEG Lossless, Non-Hierarchical (Process 14)",
);
/// **Stub descriptor:** JPEG Lossless, Non-Hierarchical, First-Order Prediction
/// (Process 14 [Selection Value 1]):
/// Default Transfer Syntax for Lossless JPEG Image Compression
pub const JPEG_LOSSLESS_NON_HIERARCHICAL_FIRST_ORDER_PREDICTION: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.70",
    "JPEG Lossless, Non-Hierarchical, First-Order Prediction",
);
/// **Stub descriptor:** JPEG-LS Lossless Image Compression
pub const JPEG_LS_LOSSLESS_IMAGE_COMPRESSION: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.80",
    "JPEG-LS Lossless Image Compression",
);
/// **Stub descriptor:** JPEG-LS Lossy (Near-Lossless) Image Compression
pub const JPEG_LS_LOSSY_IMAGE_COMPRESSION: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.81",
    "JPEG-LS Lossy (Near-Lossless) Image Compression",
);
/// **Stub descriptor:** JPEG 2000 Image Compression (Lossless Only)
pub const JPEG_2000_IMAGE_COMPRESSION_LOSSLESS_ONLY: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.90",
    "JPEG 2000 Image Compression (Lossless Only)",
);
/// **Stub descriptor:** JPEG 2000 Image Compression
pub const JPEG_2000_IMAGE_COMPRESSION: Ts =
    create_ts_stub("1.2.840.10008.1.2.4.91", "JPEG 2000 Image Compression");
/// **Stub descriptor:** JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)
pub const JPEG_2000_PART2_MULTI_COMPONENT_IMAGE_COMPRESSION_LOSSLESS_ONLY: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.92",
    "JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)",
);
/// **Stub descriptor:** JPEG 2000 Part 2 Multi-component Image Compression
pub const JPEG_2000_PART2_MULTI_COMPONENT_IMAGE_COMPRESSION: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.93",
    "JPEG 2000 Part 2 Multi-component Image Compression",
);
/// **Stub descriptor:** JPIP Referenced
pub const JPIP_REFERENCED: Ts = create_ts_stub("1.2.840.10008.1.2.4.94", "JPIP Referenced");

/// **Stub descriptor:** MPEG2 Main Profile / Main Level
pub const MPEG2_MAIN_PROFILE_MAIN_LEVEL: Ts =
    create_ts_stub("1.2.840.10008.1.2.4.100", "MPEG2 Main Profile / Main Level");
/// **Stub descriptor:** MPEG2 Main Profile / High Level
pub const MPEG2_MAIN_PROFILE_HIGH_LEVEL: Ts =
    create_ts_stub("1.2.840.10008.1.2.4.101", "MPEG2 Main Profile / High Level");
/// **Stub descriptor:** MPEG-4 AVC/H.264 High Profile / Level 4.1
pub const MPEG4_AVC_H264_HIGH_PROFILE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.102",
    "MPEG-4 AVC/H.264 High Profile / Level 4.1",
);
/// **Stub descriptor:** MPEG-4 AVC/H.264 BD-Compatible High Profile / Level 4.1
pub const MPEG4_AVC_H264_BD_COMPATIBLE_HIGH_PROFILE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.103",
    "MPEG-4 AVC/H.264 BD-Compatible High Profile / Level 4.1",
);
/// **Stub descriptor:** MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video
pub const MPEG4_AVC_H264_HIGH_PROFILE_FOR_2D_VIDEO: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.104",
    "MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video",
);
/// **Stub descriptor:** MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video
pub const MPEG4_AVC_H264_HIGH_PROFILE_FOR_3D_VIDEO: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.105",
    "MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video",
);
/// **Stub descriptor:** MPEG-4 AVC/H.264 High Profile / Level 4.2
pub const MPEG4_AVC_H264_STEREO_HIGH_PROFILE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.106",
    "MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2",
);
/// **Stub descriptor:** HEVC/H.265 Main Profile / Level 5.1
pub const HEVC_H265_MAIN_PROFILE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.107",
    "HEVC/H.265 Main Profile / Level 5.1",
);
/// **Stub descriptor:** HEVC/H.265 Main 10 Profile / Level 5.1
pub const HEVC_H265_MAIN_10_PROFILE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.4.108",
    "HEVC/H.265 Main 10 Profile / Level 5.1",
);
/// **Stub descriptor:** SMPTE ST 2110-20 Uncompressed Progressive Active Video
pub const SMPTE_ST_2110_20_UNCOMPRESSED_PROGRESSIVE: Ts = create_ts_stub(
    "1.2.840.10008.1.2.7.1",
    "SMPTE ST 2110-20 Uncompressed Progressive Active Video",
);
/// **Stub descriptor:** SMPTE ST 2110-20 Uncompressed Interlaced Active Video
pub const SMPTE_ST_2110_20_UNCOMPRESSED_INTERLACED: Ts = create_ts_stub(
    "1.2.840.10008.1.2.7.2",
    "SMPTE ST 2110-20 Uncompressed Interlaced Active Video",
);
/// **Stub descriptor:** SMPTE ST 2110-30 PCM Digital Audio
pub const SMPTE_ST_2110_30_PCM: Ts = create_ts_stub(
    "1.2.840.10008.1.2.7.3",
    "SMPTE ST 2110-30 PCM Digital Audio",
);
<|endoftext|>


<commit_before>use super::schema::notes;
use rocket::{Request, Data};
use rocket::data::{self, FromData};
use rocket::http::Status;
use rocket::Outcome::*;
use serde_json;
use rocket_contrib::JSON;

#[derive(Queryable)]
#[derive(Serialize,Deserialize)]
pub struct Note {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub pinned: bool,
}

#[derive(Insertable, Deserialize, AsChangeset)]
#[table_name="notes"]
pub struct NoteData {
    pub title: String,
    pub body: String,
    pub pinned: bool,
}

impl FromData for NoteData {
    type Error = String;

    #[allow(unused_variables)]
    fn from_data(req: &Request, data: Data) -> data::Outcome<Self, String> {
        let reader = data.open();
        let json_data: JSON<NoteData> = match serde_json::from_reader(reader)
            .map(|val| JSON(val)) {
            Ok(value) => value,
            Err(e) => return Failure((Status::BadRequest, e.to_string())),
        };

        Success(NoteData {
            title: json_data.title.to_owned(),
            body: json_data.body.to_owned(),
            pinned: json_data.pinned,
        })
    }
}
<commit_msg>Simplified model<commit_after>use super::schema::notes;
use rocket::{Request, Data};
use rocket::data::{self, FromData};
use rocket::http::Status;
use rocket::Outcome::*;
use serde_json;
use rocket_contrib::JSON;

#[derive(Queryable)]
#[derive(Serialize,Deserialize)]
pub struct Note {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub pinned: bool,
}

#[derive(Insertable, Deserialize, AsChangeset)]
#[table_name="notes"]
pub struct NoteData {
    pub title: String,
    pub body: String,
    pub pinned: bool,
}

impl FromData for NoteData {
    type Error = String;

    #[allow(unused_variables)]
    fn from_data(req: &Request, data: Data) -> data::Outcome<Self, String> {
        let reader = data.open();
        match serde_json::from_reader(reader).map(|val| val) {
            Ok(value) => Success(value),
            Err(e) => Failure((Status::BadRequest, e.to_string()))
        }
    }
}
<|endoftext|>


<commit_before>use piston_window;
use gfx_device_gl::{Resources, Output, CommandBuffer};
use gfx_graphics::GfxGraphics;

use piston_window::Transformed;
use piston_window::ImageSize;

#[derive(Debug)]
pub struct Object {
    x: f64,
    y: f64,
    // TODO: Remove Option.
    sprite: Option<piston_window::Texture<Resources>>,
}

impl Object {
    pub fn new(sprite: Option<piston_window::Texture<Resources>>) -> Object {
        Object { x: 0., y: 0., sprite: sprite }
    }

    pub fn mov(&mut self, x: f64, y: f64) {
        self.x += x;
        self.y += y;
    }

    pub fn mov_to(&mut self, x: f64, y: f64) {
        self.x = x;
        self.y = y;
    }

    pub fn render(&self, graphic: &mut GfxGraphics<Resources, CommandBuffer<Resources>, Output>, view: &piston_window::math::Matrix2d) {
        if let Some(ref sprite) = self.sprite {
            let (x, y) = sprite.get_size();
            let (x, y) = (x / 2, y / 2);
            piston_window::image(sprite, view.trans(self.x, self.y).trans(-(x as f64), -(y as f64)), graphic);
        }
    }
}

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

    #[test]
    fn object_new() {
        let object = Object::new(None);
        assert_eq!(object.x, 0.0);
        assert_eq!(object.y, 0.0);
    }

    #[test]
    fn object_mov() {
        let mut object = Object::new(None);
        assert_eq!(object.x, 0.);
        assert_eq!(object.y, 0.);

        object.mov(0., 0.);
        assert_eq!(object.x, 0.);
        assert_eq!(object.y, 0.);

        object.mov(1., 1.);
        assert_eq!(object.x, 1.);
        assert_eq!(object.y, 1.);

        object.mov(-3., -3.);
        assert_eq!(object.x, -2.);
        assert_eq!(object.y, -2.);
    }

    #[test]
    fn object_mov_to() {
        let mut object = Object::new(None);
        assert_eq!(object.x, 0.);
        assert_eq!(object.y, 0.);

        object.mov_to(0., 0.);
        assert_eq!(object.x, 0.);
        assert_eq!(object.y, 0.);

        object.mov_to(10., 10.);
        assert_eq!(object.x, 10.);
        assert_eq!(object.y, 10.);

        object.mov_to(-30., -30.);
        assert_eq!(object.x, -30.);
        assert_eq!(object.y, -30.);
    }
}
<commit_msg>Object has been delated<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2015, Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.
//! This module provides stacks using the operating system's
//! anonymous memory mapping facility, usually `mmap`.
//! The stacks it provides come with a guard page, which is not included
//! in the stack limit.

extern crate std;
use core::prelude::*;
use self::std::io::Error as IoError;
use stack;
mod sys;

#[allow(raw_pointer_derive)]
#[derive(Debug)]
pub struct Stack {
  ptr: *mut u8,
  len: usize
}

unsafe impl Send for Stack {}

impl Stack {
  pub fn new(size: usize) -> Result<Stack, IoError> {
    let page_size = sys::page_size();

    // round the page size up,
    // using the fact that it is a power of two
    let len = (size + page_size - 1) & !(page_size - 1);

    let stack = unsafe {
      let ptr = try!(match sys::map_stack(size) {
        None => Err(IoError::last_os_error()),
        Some(ptr) => Ok(ptr)
      });

      Stack { ptr: ptr as *mut u8, len: len }
    };

    try!(unsafe {
      if sys::protect_stack(stack.ptr) { Ok(()) }
      else { Err(IoError::last_os_error()) }
    });

    Ok(stack)
  }
}

impl stack::Stack for Stack {
  fn top(&mut self) -> *mut u8 {
    unsafe {
      self.ptr.offset(self.len as isize)
    }
  }

  fn limit(&self) -> *const u8 {
    unsafe {
      self.ptr.offset(sys::page_size() as isize)
    }
  }
}

impl Drop for Stack {
  fn drop(&mut self) {
    unsafe {
      if !sys::unmap_stack(self.ptr, self.len) {
        panic!("munmap for stack {:p} of size {} failed: {}",
               self.ptr, self.len, IoError::last_os_error())
      }
    }
  }
}
<commit_msg>let os::Stack's docs shine through the facade<commit_after>// Copyright (c) 2015, Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.

extern crate std;
use core::prelude::*;
use self::std::io::Error as IoError;
use stack;
mod sys;

/// This object represents a stack from the operating system's
/// anonymous memory mapping facility, usually `mmap`.
/// The stack it provides comes with a guard page, which is not included
/// in the stack limit.
#[allow(raw_pointer_derive)]
#[derive(Debug)]
pub struct Stack {
  ptr: *mut u8,
  len: usize
}

unsafe impl Send for Stack {}

impl Stack {
  pub fn new(size: usize) -> Result<Stack, IoError> {
    let page_size = sys::page_size();

    // round the page size up,
    // using the fact that it is a power of two
    let len = (size + page_size - 1) & !(page_size - 1);

    let stack = unsafe {
      let ptr = try!(match sys::map_stack(size) {
        None => Err(IoError::last_os_error()),
        Some(ptr) => Ok(ptr)
      });

      Stack { ptr: ptr as *mut u8, len: len }
    };

    try!(unsafe {
      if sys::protect_stack(stack.ptr) { Ok(()) }
      else { Err(IoError::last_os_error()) }
    });

    Ok(stack)
  }
}

impl stack::Stack for Stack {
  fn top(&mut self) -> *mut u8 {
    unsafe {
      self.ptr.offset(self.len as isize)
    }
  }

  fn limit(&self) -> *const u8 {
    unsafe {
      self.ptr.offset(sys::page_size() as isize)
    }
  }
}

impl Drop for Stack {
  fn drop(&mut self) {
    unsafe {
      if !sys::unmap_stack(self.ptr, self.len) {
        panic!("munmap for stack {:p} of size {} failed: {}",
               self.ptr, self.len, IoError::last_os_error())
      }
    }
  }
}
<|endoftext|>


<commit_before>//! Syntactic analysis of programs.

use lexer::Token;

///
/// Instructions.
///
#[derive(Debug, PartialEq)]
pub enum Instruction {
    /// Move to the next cell (`>`).
    Next,
    /// Move to the previous cell (`<`
    Prev,
    /// Increment the current cell (`+`).
    Inc,
    /// Decrement the current cell (`-`).
    Dec,
    /// Read a byte from the input into the current cell (`,`).
    Read,
    /// Write a byte from the current cell into the output (`,`).
    Write,
    /// Start of a loop ending on the given index (`[`).
    LoopStart(usize),
    /// End of a loop starting on the given index (`[`).
    LoopEnd(usize),
}

///
/// Parses the given vector of tokens into a vector of instructions.
///
/// # Arguments
///
/// * `tokens` - Tokens representing a program.
///
pub fn parse(tokens: &Vec<Token>) -> Result<Vec<Instruction>, String> {
    let mut instructions = Vec::with_capacity(tokens.len());
    let mut loop_stack: Vec<usize> = Vec::new();
    for (i, token) in tokens.iter().enumerate() {
        match *token {
            Token::Next => instructions.push(Instruction::Next),
            Token::Prev => instructions.push(Instruction::Prev),
            Token::Inc => instructions.push(Instruction::Inc),
            Token::Dec => instructions.push(Instruction::Dec),
            Token::Read => instructions.push(Instruction::Read),
            Token::Write => instructions.push(Instruction::Write),
            Token::LoopStart => {
                instructions.push(Instruction::LoopStart(0));
                loop_stack.push(i);
            }
            Token::LoopEnd => {
                let target = match loop_stack.pop() {
                    Some(target) => target,
                    None => {
                        return Err(
                            format!("missing start of a loop ended at index {}", i)
                        );
                    }
                };
                instructions.push(Instruction::LoopEnd(target));
                instructions[target] = Instruction::LoopStart(i);
            }
        }
    }

    // All loops must have been ended by now.
    if !loop_stack.is_empty() {
        return Err(
            format!(
                "missing end of a loop started at index {}",
                loop_stack.last().unwrap()
            )
        );
    }

    Ok(instructions)
}

#[cfg(test)]
mod tests {
    use super::*;
    use lexer::Token;

    #[test]
    fn test_parse_returns_empty_vec_when_there_are_no_tokens() {
        assert_eq!(parse(&vec![]).unwrap(), vec![]);
    }

    #[test]
    fn test_parse_correctly_parses_infinite_loop() {
        // []
        let tokens = vec![
            Token::LoopStart,
            Token::LoopEnd,
        ];
        let expected_result = Ok(vec![
            Instruction::LoopStart(1),
            Instruction::LoopEnd(0),
        ]);
        assert_eq!(parse(&tokens), expected_result);
    }

    #[test]
    fn test_parse_correctly_parses_valid_program() {
        // [->+<,]
        let tokens = vec![
            Token::LoopStart,
            Token::Dec,
            Token::Next,
            Token::Inc,
            Token::Prev,
            Token::Read,
            Token::LoopEnd,
        ];
        let expected_result = Ok(vec![
            Instruction::LoopStart(6),
            Instruction::Dec,
            Instruction::Next,
            Instruction::Inc,
            Instruction::Prev,
            Instruction::Read,
            Instruction::LoopEnd(0),
        ]);
        assert_eq!(parse(&tokens), expected_result);
    }

    #[test]
    fn test_parse_returns_error_when_missing_loop_end() {
        assert_eq!(
            parse(&vec![Token::LoopStart]),
            Err("missing end of a loop started at index 0".to_string())
        );
    }

    #[test]
    fn test_parse_returns_error_when_missing_loop_start() {
        assert_eq!(
            parse(&vec![Token::LoopEnd]),
            Err("missing start of a loop ended at index 0".to_string())
        );
    }
}
<commit_msg>Refactor the parsing of tokens into instructions.<commit_after>//! Syntactic analysis of programs.

use lexer::Token;

///
/// Instructions.
///
#[derive(Debug, PartialEq)]
pub enum Instruction {
    /// Move to the next cell (`>`).
    Next,
    /// Move to the previous cell (`<`
    Prev,
    /// Increment the current cell (`+`).
    Inc,
    /// Decrement the current cell (`-`).
    Dec,
    /// Read a byte from the input into the current cell (`,`).
    Read,
    /// Write a byte from the current cell into the output (`,`).
    Write,
    /// Start of a loop ending on the given index (`[`).
    LoopStart(usize),
    /// End of a loop starting on the given index (`[`).
    LoopEnd(usize),
}

///
/// Parses the given vector of tokens into a vector of instructions.
///
/// # Arguments
///
/// * `tokens` - Tokens representing a program.
///
pub fn parse(tokens: &Vec<Token>) -> Result<Vec<Instruction>, String> {
    let mut instructions = Vec::with_capacity(tokens.len());
    let mut loop_stack: Vec<usize> = Vec::new();
    for (i, token) in tokens.iter().enumerate() {
        match *token {
            Token::Next => instructions.push(Instruction::Next),
            Token::Prev => instructions.push(Instruction::Prev),
            Token::Inc => instructions.push(Instruction::Inc),
            Token::Dec => instructions.push(Instruction::Dec),
            Token::Read => instructions.push(Instruction::Read),
            Token::Write => instructions.push(Instruction::Write),
            Token::LoopStart =>
                try!(handle_loop_start(&mut instructions, &mut loop_stack, i)),
            Token::LoopEnd =>
                try!(handle_loop_end(&mut instructions, &mut loop_stack, i)),
        }
    }
    try!(ensure_all_loops_have_ended(&loop_stack));
    Ok(instructions)
}

fn handle_loop_start(instructions: &mut Vec<Instruction>,
                     loop_stack: &mut Vec<usize>,
                     i: usize)
                     -> Result<(), String> {
    // We don't know the target yet, so pass 0. It will be updated later when
    // we reach the target.
    instructions.push(Instruction::LoopStart(0));
    loop_stack.push(i);
    Ok(())
}

fn handle_loop_end(instructions: &mut Vec<Instruction>,
                   loop_stack: &mut Vec<usize>,
                   i: usize)
                   -> Result<(), String> {
    let target = match loop_stack.pop() {
        Some(target) => target,
        None => {
            return Err(
                format!("missing start of a loop ended at index {}", i)
            );
        }
    };
    instructions.push(Instruction::LoopEnd(target));
    // Update the index of the target in the loop start because it was
    // initialized to zero.
    instructions[target] = Instruction::LoopStart(i);
    Ok(())
}

fn ensure_all_loops_have_ended(loop_stack: &Vec<usize>) -> Result<(), String> {
    if !loop_stack.is_empty() {
        return Err(
            format!(
                "missing end of a loop started at index {}",
                loop_stack.last().unwrap()
            )
        );
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use lexer::Token;

    #[test]
    fn test_parse_returns_empty_vec_when_there_are_no_tokens() {
        assert_eq!(parse(&vec![]).unwrap(), vec![]);
    }

    #[test]
    fn test_parse_correctly_parses_infinite_loop() {
        // []
        let tokens = vec![
            Token::LoopStart,
            Token::LoopEnd,
        ];
        let expected_result = Ok(vec![
            Instruction::LoopStart(1),
            Instruction::LoopEnd(0),
        ]);
        assert_eq!(parse(&tokens), expected_result);
    }

    #[test]
    fn test_parse_correctly_parses_valid_program() {
        // [->+<,]
        let tokens = vec![
            Token::LoopStart,
            Token::Dec,
            Token::Next,
            Token::Inc,
            Token::Prev,
            Token::Read,
            Token::LoopEnd,
        ];
        let expected_result = Ok(vec![
            Instruction::LoopStart(6),
            Instruction::Dec,
            Instruction::Next,
            Instruction::Inc,
            Instruction::Prev,
            Instruction::Read,
            Instruction::LoopEnd(0),
        ]);
        assert_eq!(parse(&tokens), expected_result);
    }

    #[test]
    fn test_parse_returns_error_when_missing_loop_end() {
        assert_eq!(
            parse(&vec![Token::LoopStart]),
            Err("missing end of a loop started at index 0".to_string())
        );
    }

    #[test]
    fn test_parse_returns_error_when_missing_loop_start() {
        assert_eq!(
            parse(&vec![Token::LoopEnd]),
            Err("missing start of a loop ended at index 0".to_string())
        );
    }
}
<|endoftext|>


<commit_before>use std::error::Error;

use {Ident, Value};

#[deriving(PartialEq, Show)]
/// Possible errors encountered when parsing EDN.
pub enum ParserError {
    /// The parser reached the end of the input unexpectedly.
    Eof,
    /// The parser read an unknown string escape
    InvalidEscape,
    /// The parser found a token invalid for this position.
    InvalidToken(char)
}

impl Error for ParserError {
    fn description(&self) -> &str { "EDN parser error" }
}

pub type ParserResult = Result<Value, ParserError>;

pub struct Parser<T: Iterator<char>> {
    inp: T,
    ch: Option<char>
}

impl<T: Iterator<char>> Parser<T> {
    pub fn new(mut inp: T) -> Parser<T> {
        let ch = inp.next();
        Parser {
            inp: inp,
            ch: ch
        }
    }

    fn is_eof(&self) -> bool {
        self.ch.is_none()
    }

    fn bump(&mut self) {
        self.ch = self.inp.next()
    }

    fn consume_ws(&mut self) {
        loop {
            if self.is_eof() { break }
            let ch = self.ch.unwrap();
            // The EDN "spec" is very vague about what constitutes whitespace, but
            // tools.reader.edn uses Java's Character.isWhitespace method which has
            // identical semantics to Rust's char::is_whitespace method (*cough*
            // hopefully).
            // FIXME: verify that ^^^
            if ch.is_whitespace() || ch == ',' {
                self.bump();
            } else {
                break
            }
        }
    }

    fn at_symbol(&self) -> bool {
        if let Some(ch) = self.ch {
            is_ident_start_ch(ch)
        } else {
            false
        }
    }

    fn at_keyword(&self) -> bool {
        if let Some(':') = self.ch { true } else { false }
    }

    fn parse_ident(&mut self) -> Result<Ident, ParserError> {
        if self.is_eof() { return Err(ParserError::Eof) }

        let mut ident = String::with_capacity(16);
        let mut prefix = None;
        let ch = self.ch.unwrap();
        // It's important that parse_symbol respects the symbol starting character
        // restrictions itself, because parse_ident is also needed for parsing
        // keywords (which don't have those restrictions).
        if !is_ident_ch(ch) { return Err(ParserError::InvalidToken(ch)) }

        loop {
            if self.is_eof() { break; }
            let ch = self.ch.unwrap();
            if ch == '/' {
                prefix = Some(ident);
                ident = String::with_capacity(16);
                self.bump();
                continue;
            }
            if !is_ident_ch(ch) { break; }
            ident.push(self.ch.unwrap());
            self.bump();
        }
        if ident.len() == 0 { return Err(ParserError::InvalidToken('/')) }
        Ok(Ident {
            name: ident,
            prefix: prefix
        })
    }

    fn parse_string_escape(&mut self) -> Result<char, ParserError> {
        self.bump();
        if self.is_eof() { return Err(ParserError::Eof) }
        let ch = self.ch.unwrap();
        match ch {
            't' => Ok('\t'),
            'r' => Ok('\r'),
            'n' => Ok('\n'),
            '\\' => Ok('\\'),
            '"' => Ok('"'),
            _ => Err(ParserError::InvalidEscape)
        }
    }

    fn parse_string(&mut self) -> ParserResult {
        let mut out = String::with_capacity(32);
        loop {
            self.bump();
            if self.is_eof() { return Err(ParserError::Eof) }
            let ch = self.ch.unwrap();
            if ch == '"' { break }
            if ch == '\\' {
                out.push(try!(self.parse_string_escape()));
                continue;
            }
            out.push(self.ch.unwrap())
        }
        Ok(Value::String(out))
    }

    fn parse_symbol(&mut self) -> ParserResult {
        let ident = try!(self.parse_ident());
        if ident.prefix.is_none() {
            Ok(match &*ident.name {
                "nil" => Value::Nil,
                "true" => Value::Bool(true),
                "false" => Value::Bool(false),
                _ => Value::Symbol(ident)
            })
        } else {
            Ok(Value::Symbol(ident))
        }
    }

    fn parse_keyword(&mut self) -> ParserResult {
        self.bump();
        Ok(Value::Keyword(try!(self.parse_ident())))
    }

    pub fn parse_value(&mut self) -> ParserResult {
        self.consume_ws();

        if self.is_eof() { return Err(ParserError::Eof) }
        let ch = self.ch.unwrap();
        if ch == '"' { return self.parse_string() }
        if self.at_symbol() { return self.parse_symbol() }
        if self.at_keyword() { return self.parse_keyword() }

        unimplemented!()
    }
}

fn is_ident_start_ch(ch: char) -> bool {
    match ch {
        'a'...'z' | 'A'...'Z' => true,
        '*' | '!' | '_' | '?' | '$' | '%' | '&' | '=' | '<' | '>' => true,
        '-' | '+' | '.' => true, // can also start a number literal, watch out!
        _ => false
    }
}

fn is_ident_ch(ch: char) -> bool {
    is_ident_start_ch(ch) || ch == ':' || ch == '#' || (ch >= '0' && ch <= '9')
}

#[cfg(test)]
mod test {
    use {Ident, Value};
    use super::*;

    macro_rules! assert_val {
        ($str:expr, $val:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert_eq!(parser.parse_value(), Ok($val))
        })
    }

    macro_rules! assert_err {
        ($str:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert!(parser.parse_value().is_err())
        });
        ($str:expr, $val:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert_eq!(parser.parse_value(), Err($val))
        })
    }

    #[test]
    fn test_parse_eof() {
        assert_err!("", ParserError::Eof);
        assert_err!("    ", ParserError::Eof);
        assert_err!(",", ParserError::Eof);
    }

    #[test]
    fn test_parse_nil() {
        assert_val!("nil", Value::Nil);
        assert_val!("nil ", Value::Nil);
    }

    #[test]
    fn test_parse_bool() {
        assert_val!("true", Value::Bool(true));
        assert_val!("false", Value::Bool(false));
        assert_val!("false,", Value::Bool(false));
    }

    #[test]
    fn test_parse_str() {
        assert_err!(r#" "foo "#, ParserError::Eof);
        assert_val!(r#" "" "#, Value::String("".into_string()));
        assert_val!(r#" "foo" "#, Value::String("foo".into_string()));
        assert_val!(r#" "\n" "#, Value::String("\n".into_string()));
        assert_val!(r#" "\"" "#, Value::String("\"".into_string()));
        // multi-line
        assert_val!(" \"foo\nbar\" ", Value::String("foo\nbar".into_string()));
    }

    #[test]
    fn test_parse_symbol() {
        assert_val!("foo", Value::Symbol(Ident::simple("foo")));
        assert_val!("foo#", Value::Symbol(Ident::simple("foo#")));
        assert_val!("foo9", Value::Symbol(Ident::simple("foo9")));
        assert_val!("-foo", Value::Symbol(Ident::simple("-foo")));
        assert_val!("foo/bar", Value::Symbol(Ident::prefixed("bar", "foo")));
        assert_err!("foo/", ParserError::InvalidToken('/'));
        // FIXME: the parser doesn't handle this correctly right now
        // assert_err!("/bar", ParserError::InvalidToken('/'));

        // tools.reader.edn parses this as a symbol
        // assert_val!("ᛰ", Value::Symbol(Ident::simple("ᛰ")));
    }

    #[test]
    fn test_parse_keyword() {
        assert_err!(":", ParserError::Eof);
        assert_err!(": foo", ParserError::InvalidToken(' '));
        assert_val!(":foo", Value::Keyword(Ident::simple("foo")));
        assert_val!(":-foo", Value::Keyword(Ident::simple("-foo")));
        assert_val!(":1234", Value::Keyword(Ident::simple("1234")));
        assert_val!(":12aaa", Value::Keyword(Ident::simple("12aaa")));
    }
}
<commit_msg>Start work on parse_char<commit_after>use std::error::Error;

use {Ident, Value};

#[deriving(PartialEq, Show)]
/// Possible errors encountered when parsing EDN.
pub enum ParserError {
    /// The parser reached the end of the input unexpectedly.
    Eof,
    /// The parser read an unknown string escape
    InvalidEscape,
    /// The parser found a token invalid for this position.
    InvalidToken(char)
}

impl Error for ParserError {
    fn description(&self) -> &str { "EDN parser error" }
}

pub type ParserResult = Result<Value, ParserError>;

pub struct Parser<T: Iterator<char>> {
    inp: T,
    ch: Option<char>
}

impl<T: Iterator<char>> Parser<T> {
    pub fn new(mut inp: T) -> Parser<T> {
        let ch = inp.next();
        Parser {
            inp: inp,
            ch: ch
        }
    }

    fn is_eof(&self) -> bool {
        self.ch.is_none()
    }

    fn bump(&mut self) {
        self.ch = self.inp.next()
    }

    fn consume_ws(&mut self) {
        while self.at_whitespace() {
            self.bump();
        }
    }

    fn at_whitespace(&self) -> bool {
        // The EDN "spec" is very vague about what constitutes whitespace, but
        // tools.reader.edn uses Java's Character.isWhitespace method which has
        // identical semantics to Rust's char::is_whitespace method (*cough*
        // hopefully).
        // FIXME: verify that ^^^
        match self.ch {
            Some(ch) => ch.is_whitespace() || ch == ',',
            None => false
        }
    }

    fn at_symbol(&self) -> bool {
        if let Some(ch) = self.ch {
            is_ident_start_ch(ch)
        } else {
            false
        }
    }

    fn at_keyword(&self) -> bool {
        if let Some(':') = self.ch { true } else { false }
    }

    fn parse_ident(&mut self) -> Result<Ident, ParserError> {
        if self.is_eof() { return Err(ParserError::Eof) }

        let mut ident = String::with_capacity(16);
        let mut prefix = None;
        let ch = self.ch.unwrap();
        // It's important that parse_symbol respects the symbol starting character
        // restrictions itself, because parse_ident is also needed for parsing
        // keywords (which don't have those restrictions).
        if !is_ident_ch(ch) { return Err(ParserError::InvalidToken(ch)) }

        loop {
            if self.is_eof() { break; }
            let ch = self.ch.unwrap();
            if ch == '/' {
                prefix = Some(ident);
                ident = String::with_capacity(16);
                self.bump();
                continue;
            }
            if !is_ident_ch(ch) { break; }
            ident.push(self.ch.unwrap());
            self.bump();
        }
        if ident.len() == 0 { return Err(ParserError::InvalidToken('/')) }
        Ok(Ident {
            name: ident,
            prefix: prefix
        })
    }

    fn parse_string_escape(&mut self) -> Result<char, ParserError> {
        self.bump();
        if self.is_eof() { return Err(ParserError::Eof) }
        let ch = self.ch.unwrap();
        match ch {
            't' => Ok('\t'),
            'r' => Ok('\r'),
            'n' => Ok('\n'),
            '\\' => Ok('\\'),
            '"' => Ok('"'),
            _ => Err(ParserError::InvalidEscape)
        }
    }

    fn parse_string(&mut self) -> ParserResult {
        let mut out = String::with_capacity(32);
        loop {
            self.bump();
            if self.is_eof() { return Err(ParserError::Eof) }
            let ch = self.ch.unwrap();
            if ch == '"' { break }
            if ch == '\\' {
                out.push(try!(self.parse_string_escape()));
                continue;
            }
            out.push(self.ch.unwrap())
        }
        Ok(Value::String(out))
    }

    fn parse_char(&mut self) -> ParserResult {
        self.bump();
        if self.is_eof() || self.at_whitespace() {
            return Ok(Value::Symbol(Ident { name: "\\".into_string(), prefix: None }))
        }
        unimplemented!()
    }

    fn parse_symbol(&mut self) -> ParserResult {
        let ident = try!(self.parse_ident());
        if ident.prefix.is_none() {
            Ok(match &*ident.name {
                "nil" => Value::Nil,
                "true" => Value::Bool(true),
                "false" => Value::Bool(false),
                _ => Value::Symbol(ident)
            })
        } else {
            Ok(Value::Symbol(ident))
        }
    }

    fn parse_keyword(&mut self) -> ParserResult {
        self.bump();
        Ok(Value::Keyword(try!(self.parse_ident())))
    }

    pub fn parse_value(&mut self) -> ParserResult {
        self.consume_ws();
        if self.is_eof() { return Err(ParserError::Eof) }

        let ch = self.ch.unwrap();
        if ch == '"' { return self.parse_string() }
        if ch == '\\' { return self.parse_char() }
        if self.at_symbol() { return self.parse_symbol() }
        if self.at_keyword() { return self.parse_keyword() }

        unimplemented!()
    }
}

fn is_ident_start_ch(ch: char) -> bool {
    match ch {
        'a'...'z' | 'A'...'Z' => true,
        '*' | '!' | '_' | '?' | '$' | '%' | '&' | '=' | '<' | '>' => true,
        '-' | '+' | '.' => true, // can also start a number literal, watch out!
        _ => false
    }
}

fn is_ident_ch(ch: char) -> bool {
    is_ident_start_ch(ch) || ch == ':' || ch == '#' || (ch >= '0' && ch <= '9')
}

#[cfg(test)]
mod test {
    use {Ident, Value};
    use super::*;

    macro_rules! assert_val {
        ($str:expr, $val:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert_eq!(parser.parse_value(), Ok($val))
        })
    }

    macro_rules! assert_err {
        ($str:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert!(parser.parse_value().is_err())
        });
        ($str:expr, $val:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert_eq!(parser.parse_value(), Err($val))
        })
    }

    #[test]
    fn test_parse_eof() {
        assert_err!("", ParserError::Eof);
        assert_err!("    ", ParserError::Eof);
        assert_err!(",", ParserError::Eof);
    }

    #[test]
    fn test_parse_nil() {
        assert_val!("nil", Value::Nil);
        assert_val!("nil ", Value::Nil);
    }

    #[test]
    fn test_parse_bool() {
        assert_val!("true", Value::Bool(true));
        assert_val!("false", Value::Bool(false));
        assert_val!("false,", Value::Bool(false));
    }

    #[test]
    fn test_parse_str() {
        assert_err!(r#" "foo "#, ParserError::Eof);
        assert_val!(r#" "" "#, Value::String("".into_string()));
        assert_val!(r#" "foo" "#, Value::String("foo".into_string()));
        assert_val!(r#" "\n" "#, Value::String("\n".into_string()));
        assert_val!(r#" "\"" "#, Value::String("\"".into_string()));
        // multi-line
        assert_val!(" \"foo\nbar\" ", Value::String("foo\nbar".into_string()));
    }

    #[test]
    fn test_parse_char() {
    }

    #[test]
    fn test_parse_symbol() {
        assert_val!("foo", Value::Symbol(Ident::simple("foo")));
        assert_val!("foo#", Value::Symbol(Ident::simple("foo#")));
        assert_val!("foo9", Value::Symbol(Ident::simple("foo9")));
        assert_val!("-foo", Value::Symbol(Ident::simple("-foo")));
        assert_val!("foo/bar", Value::Symbol(Ident::prefixed("bar", "foo")));
        assert_err!("foo/", ParserError::InvalidToken('/'));
        // FIXME: the parser doesn't handle this correctly right now
        // assert_err!("/bar", ParserError::InvalidToken('/'));

        assert_val!(r#" \ "#, Value::Symbol(Ident::simple("\\")));

        // tools.reader.edn parses this as a symbol
        // assert_val!("ᛰ", Value::Symbol(Ident::simple("ᛰ")));
    }

    #[test]
    fn test_parse_keyword() {
        assert_err!(":", ParserError::Eof);
        assert_err!(": foo", ParserError::InvalidToken(' '));
        assert_val!(":foo", Value::Keyword(Ident::simple("foo")));
        assert_val!(":-foo", Value::Keyword(Ident::simple("-foo")));
        assert_val!(":1234", Value::Keyword(Ident::simple("1234")));
        assert_val!(":12aaa", Value::Keyword(Ident::simple("12aaa")));
    }
}
<|endoftext|>


<commit_before>use std::io;

use features::Features;
use token::{Sentence, Token, EMPTY_TOKEN};
use error::{ErrorKind, Result, ResultExt};

/// A trait for objects that can read CoNLL-X `Sentence`s
pub trait ReadSentence {
    /// Read a `Sentence` from this object.
    ///
    /// # Errors
    ///
    /// A call to `read_sentence` may generate an error to indicate that
    /// the operation could not be completed.
    fn read_sentence(&mut self) -> Result<Option<Sentence>>;
}

/// A reader for CoNLL-X sentences.
pub struct Reader<R> {
    read: R,
}

impl<R: io::BufRead> Reader<R> {
    /// Construct a new reader from an object that implements the
    /// `io::BufRead` trait.
    pub fn new(read: R) -> Reader<R> {
        Reader { read: read }
    }

    /// Get an iterator over the `Sentence`s in this reader.
    pub fn sentences(self) -> Sentences<R> {
        Sentences { reader: self }
    }
}

impl<R: io::BufRead> IntoIterator for Reader<R> {
    type Item = Result<Sentence>;
    type IntoIter = Sentences<R>;

    fn into_iter(self) -> Self::IntoIter {
        self.sentences()
    }
}

impl<R: io::BufRead> ReadSentence for Reader<R> {
    fn read_sentence(&mut self) -> Result<Option<Sentence>> {
        let mut line = String::new();
        let mut tokens = Vec::new();

        loop {
            line.clear();

            // End of reader.
            if self.read.read_line(&mut line)? == 0 {
                if tokens.is_empty() {
                    return Ok(None);
                }

                return Ok(Some(Sentence::new(tokens)));
            }

            // The blank line is a sentence separator. We want to be robust
            // in the case a CoNLL file is malformed and has two newlines as
            // a separator.
            if line.trim().is_empty() {
                if tokens.is_empty() {
                    continue;
                }

                return Ok(Some(Sentence::new(tokens)));
            }

            let mut iter = line.trim().split_terminator('\t');

            parse_numeric_field(iter.next())?;

            let mut token = Token::new();
            token.set_form(parse_string_field(iter.next()));
            token.set_lemma(parse_string_field(iter.next()));
            token.set_cpos(parse_string_field(iter.next()));
            token.set_pos(parse_string_field(iter.next()));
            token.set_features(parse_string_field(iter.next()).map(Features::from_string));
            token.set_head(parse_numeric_field(iter.next())?);
            token.set_head_rel(parse_string_field(iter.next()));
            token.set_p_head(parse_numeric_field(iter.next())?);
            token.set_p_head_rel(parse_string_field(iter.next()));

            tokens.push(token);
        }
    }
}

/// An iterator over the sentences in a `Reader`.
pub struct Sentences<R> {
    reader: Reader<R>,
}

impl<R: io::BufRead> Iterator for Sentences<R> {
    type Item = Result<Sentence>;

    fn next(&mut self) -> Option<Result<Sentence>> {
        match self.reader.read_sentence() {
            Ok(None) => None,
            Ok(Some(sent)) => Some(Ok(sent)),
            Err(e) => Some(Err(e)),
        }
    }
}

fn parse_string_field(field: Option<&str>) -> Option<String> {
    field.and_then(|s| {
        if s == EMPTY_TOKEN {
            None
        } else {
            Some(s.to_string())
        }
    })
}

fn parse_numeric_field(field: Option<&str>) -> Result<Option<usize>> {
    match field {
        None => Ok(None),
        Some(s) => {
            if s == EMPTY_TOKEN {
                Ok(None)
            } else {
                Ok(Some(s.parse().chain_err(|| ErrorKind::ParseIntFieldError(s.to_owned()))?))
            }
        }
    }
}
<commit_msg>Sentences should work with any SentenceRead.<commit_after>use std::io;

use features::Features;
use token::{Sentence, Token, EMPTY_TOKEN};
use error::{ErrorKind, Result, ResultExt};

/// A trait for objects that can read CoNLL-X `Sentence`s
pub trait ReadSentence {
    /// Read a `Sentence` from this object.
    ///
    /// # Errors
    ///
    /// A call to `read_sentence` may generate an error to indicate that
    /// the operation could not be completed.
    fn read_sentence(&mut self) -> Result<Option<Sentence>>;
}

/// A reader for CoNLL-X sentences.
pub struct Reader<R> {
    read: R,
}

impl<R: io::BufRead> Reader<R> {
    /// Construct a new reader from an object that implements the
    /// `io::BufRead` trait.
    pub fn new(read: R) -> Reader<R> {
        Reader { read: read }
    }

    /// Get an iterator over the `Sentence`s in this reader.
    pub fn sentences(self) -> Sentences<Reader<R>> {
        Sentences { reader: self }
    }
}

impl<R: io::BufRead> IntoIterator for Reader<R> {
    type Item = Result<Sentence>;
    type IntoIter = Sentences<Reader<R>>;

    fn into_iter(self) -> Self::IntoIter {
        self.sentences()
    }
}

impl<R: io::BufRead> ReadSentence for Reader<R> {
    fn read_sentence(&mut self) -> Result<Option<Sentence>> {
        let mut line = String::new();
        let mut tokens = Vec::new();

        loop {
            line.clear();

            // End of reader.
            if self.read.read_line(&mut line)? == 0 {
                if tokens.is_empty() {
                    return Ok(None);
                }

                return Ok(Some(Sentence::new(tokens)));
            }

            // The blank line is a sentence separator. We want to be robust
            // in the case a CoNLL file is malformed and has two newlines as
            // a separator.
            if line.trim().is_empty() {
                if tokens.is_empty() {
                    continue;
                }

                return Ok(Some(Sentence::new(tokens)));
            }

            let mut iter = line.trim().split_terminator('\t');

            parse_numeric_field(iter.next())?;

            let mut token = Token::new();
            token.set_form(parse_string_field(iter.next()));
            token.set_lemma(parse_string_field(iter.next()));
            token.set_cpos(parse_string_field(iter.next()));
            token.set_pos(parse_string_field(iter.next()));
            token.set_features(parse_string_field(iter.next()).map(Features::from_string));
            token.set_head(parse_numeric_field(iter.next())?);
            token.set_head_rel(parse_string_field(iter.next()));
            token.set_p_head(parse_numeric_field(iter.next())?);
            token.set_p_head_rel(parse_string_field(iter.next()));

            tokens.push(token);
        }
    }
}

/// An iterator over the sentences in a `Reader`.
pub struct Sentences<R> where R: ReadSentence {
    reader: R,
}

impl<R> Iterator for Sentences<R> where R: ReadSentence {
    type Item = Result<Sentence>;

    fn next(&mut self) -> Option<Result<Sentence>> {
        match self.reader.read_sentence() {
            Ok(None) => None,
            Ok(Some(sent)) => Some(Ok(sent)),
            Err(e) => Some(Err(e)),
        }
    }
}

fn parse_string_field(field: Option<&str>) -> Option<String> {
    field.and_then(|s| {
        if s == EMPTY_TOKEN {
            None
        } else {
            Some(s.to_string())
        }
    })
}

fn parse_numeric_field(field: Option<&str>) -> Result<Option<usize>> {
    match field {
        None => Ok(None),
        Some(s) => {
            if s == EMPTY_TOKEN {
                Ok(None)
            } else {
                Ok(Some(s.parse().chain_err(|| ErrorKind::ParseIntFieldError(s.to_owned()))?))
            }
        }
    }
}
<|endoftext|>