<commit_before>use Event;
use std::sync::atomic::AtomicBool;

#[cfg(feature = "window")]
use WindowBuilder;

#[cfg(feature = "headless")]
use HeadlessRendererBuilder;

use cocoa::base::{id, NSUInteger, nil};
use cocoa::appkit::*;

use core_foundation::base::TCFType;
use core_foundation::string::CFString;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};

use std::c_str::CString;
use {MouseInput, Pressed, Released, LeftMouseButton, RightMouseButton, MouseMoved, ReceivedCharacter,
     KeyboardInput};

mod event;

pub struct Window {
    view: id,
    context: id,
    is_closed: AtomicBool,
}

pub struct HeadlessContext(Window);

impl Deref<Window> for HeadlessContext {
    fn deref(&self) -> &Window {
        &self.0
    }
}

pub struct MonitorID;

pub fn get_available_monitors() -> Vec<MonitorID> {
    unimplemented!()
}

pub fn get_primary_monitor() -> MonitorID {
    unimplemented!()
}

impl MonitorID {
    pub fn get_name(&self) -> Option<String> {
        unimplemented!()
    }

    pub fn get_dimensions(&self) -> (uint, uint) {
        unimplemented!()
    }
}

#[cfg(feature = "window")]
impl Window {
    pub fn new(builder: WindowBuilder) -> Result<Window, String> {
        Window::new_impl(builder.dimensions, builder.title.as_slice(), true)
    }
}

#[cfg(feature = "headless")]
impl HeadlessContext {
    pub fn new(builder: HeadlessRendererBuilder) -> Result<HeadlessContext, String> {
        Window::new_impl(Some(builder.dimensions), "", false)
            .map(|w| HeadlessContext(w))
    }
}

impl Window {
    fn new_impl(dimensions: Option<(uint, uint)>, title: &str, visible: bool) -> Result<Window, String> {
        let app = match Window::create_app() {
            Some(app) => app,
            None      => { return Err(format!("Couldn't create NSApplication")); },
        };
        let window = match Window::create_window(dimensions.unwrap_or((800, 600)), title) {
            Some(window) => window,
            None         => { return Err(format!("Couldn't create NSWindow")); },
        };
        let view = match Window::create_view(window) {
            Some(view) => view,
            None       => { return Err(format!("Couldn't create NSView")); },
        };

        let context = match Window::create_context(view) {
            Some(context) => context,
            None          => { return Err(format!("Couldn't create OpenGL context")); },
        };

        unsafe {
            app.activateIgnoringOtherApps_(true);
            window.makeKeyAndOrderFront_(nil);
        }

        let window = Window {
            view: view,
            context: context,
            is_closed: AtomicBool::new(false),
        };

        Ok(window)
    }

    fn create_app() -> Option<id> {
        unsafe {
            let app = NSApp();
            if app == nil {
                None
            } else {
                app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
                app.finishLaunching();
                Some(app)
            }
        }
    }

    fn create_window(dimensions: (uint, uint), title: &str) -> Option<id> {
        unsafe {
            let (width, height) = dimensions;
            let scr_frame = NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64));

            let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
                scr_frame,
                NSTitledWindowMask as NSUInteger | NSClosableWindowMask as NSUInteger | NSMiniaturizableWindowMask as NSUInteger,
                NSBackingStoreBuffered,
                false
            );

            if window == nil {
                None
            } else {
                let title = NSString::alloc(nil).init_str(title);
                window.setTitle_(title);
                window.center();
                window.setAcceptsMouseMovedEvents_(true);
                Some(window)
            }
        }
    }

    fn create_view(window: id) -> Option<id> {
        unsafe {
            let view = NSView::alloc(nil).init();
            if view == nil {
                None
            } else {
                view.setWantsBestResolutionOpenGLSurface_(true);
                window.setContentView_(view);
                Some(view)
            }
        }
    }

    fn create_context(view: id) -> Option<id> {
        unsafe {
            let attributes = [
                NSOpenGLPFADoubleBuffer as uint,
                NSOpenGLPFAClosestPolicy as uint,
                NSOpenGLPFAColorSize as uint, 24,
                NSOpenGLPFAAlphaSize as uint, 8,
                NSOpenGLPFADepthSize as uint, 24,
                NSOpenGLPFAStencilSize as uint, 8,
                0
            ];

            let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(attributes);
            if pixelformat == nil {
                return None;
            }

            let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
            if context == nil {
                None
            } else {
                context.setView_(view);
                Some(context)
            }
        }
    }

    pub fn is_closed(&self) -> bool {
        use std::sync::atomic::Relaxed;
        self.is_closed.load(Relaxed)
    }

    pub fn set_title(&self, _title: &str) {
        unimplemented!()
    }

    pub fn get_position(&self) -> Option<(int, int)> {
        unimplemented!()
    }

    pub fn set_position(&self, _x: int, _y: int) {
        unimplemented!()
    }

    pub fn get_inner_size(&self) -> Option<(uint, uint)> {
        unimplemented!()
    }

    pub fn get_outer_size(&self) -> Option<(uint, uint)> {
        unimplemented!()
    }

    pub fn set_inner_size(&self, _x: uint, _y: uint) {
        unimplemented!()
    }

    pub fn poll_events(&self) -> Vec<Event> {
        let mut events = Vec::new();

        loop {
            unsafe {
                let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                    NSAnyEventMask as u64,
                    NSDate::distantPast(nil),
                    NSDefaultRunLoopMode,
                    true);
                if event == nil { break; }
                NSApp().sendEvent_(event);

                match event.get_type() {
                    NSLeftMouseDown         => { events.push(MouseInput(Pressed, LeftMouseButton)); },
                    NSLeftMouseUp           => { events.push(MouseInput(Released, LeftMouseButton)); },
                    NSRightMouseDown        => { events.push(MouseInput(Pressed, RightMouseButton)); },
                    NSRightMouseUp          => { events.push(MouseInput(Released, RightMouseButton)); },
                    NSMouseMoved            => {
                        let window_point = event.locationInWindow();
                        let view_point = self.view.convertPoint_fromView_(window_point, nil);
                        events.push(MouseMoved((view_point.x as int, view_point.y as int)));
                    },
                    NSKeyDown               => {
                        let received_str = CString::new(event.characters().UTF8String(), false);
                        for received_char in received_str.as_str().unwrap().chars() {
                            if received_char.is_ascii() {
                                events.push(ReceivedCharacter(received_char));
                            }
                        }

                        let vkey =  event::vkeycode_to_element(event.keycode());
                        let modifiers = event::modifierflag_to_element(event.modifierFlags());
                        events.push(KeyboardInput(Pressed, event.keycode() as u8, vkey, modifiers));
                    },
                    NSKeyUp                 => {
                        let vkey =  event::vkeycode_to_element(event.keycode());
                        let modifiers = event::modifierflag_to_element(event.modifierFlags());
                        events.push(KeyboardInput(Released, event.keycode() as u8, vkey, modifiers));
                    },
                    NSFlagsChanged          => {
                        println!("Modifiers: {}", event.modifierFlags());
                        // Need to keep an array of the modified flags
                    },
                    NSScrollWheel           => { },
                    NSOtherMouseDown        => { },
                    NSOtherMouseUp          => { },
                    NSOtherMouseDragged     => { },
                    _                       => { },
                }
            }
        }
        events
    }

    pub fn wait_events(&self) -> Vec<Event> {
        unsafe {
            let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                NSAnyEventMask as u64,
                NSDate::distantFuture(nil),
                NSDefaultRunLoopMode,
                false);
            NSApp().sendEvent_(event);

            self.poll_events()
        }
    }

    pub unsafe fn make_current(&self) {
        self.context.makeCurrentContext();
    }

    pub fn get_proc_address(&self, _addr: &str) -> *const () {
        let symbol_name: CFString = from_str(_addr).unwrap();
        let framework_name: CFString = from_str("com.apple.opengl").unwrap();
        let framework = unsafe {
            CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
        };
        let symbol = unsafe {
            CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
        };
        symbol as *const ()
    }

    pub fn swap_buffers(&self) {
        unsafe { self.context.flushBuffer(); }
    }
}
<commit_msg>Added the modifiers key as input<commit_after>use Event;
use std::sync::atomic::AtomicBool;

#[cfg(feature = "window")]
use WindowBuilder;

#[cfg(feature = "headless")]
use HeadlessRendererBuilder;

use cocoa::base::{id, NSUInteger, nil};
use cocoa::appkit;
use cocoa::appkit::*;

use core_foundation::base::TCFType;
use core_foundation::string::CFString;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};

use std::c_str::CString;
use {MouseInput, Pressed, Released, LeftMouseButton, RightMouseButton, MouseMoved, ReceivedCharacter,
     KeyboardInput, KeyModifiers};

use events;

mod event;

static mut shift_pressed: bool = false;
static mut ctrl_pressed: bool = false;
static mut win_pressed: bool = false;

pub struct Window {
    view: id,
    context: id,
    is_closed: AtomicBool,
}

pub struct HeadlessContext(Window);

impl Deref<Window> for HeadlessContext {
    fn deref(&self) -> &Window {
        &self.0
    }
}

pub struct MonitorID;

pub fn get_available_monitors() -> Vec<MonitorID> {
    unimplemented!()
}

pub fn get_primary_monitor() -> MonitorID {
    unimplemented!()
}

impl MonitorID {
    pub fn get_name(&self) -> Option<String> {
        unimplemented!()
    }

    pub fn get_dimensions(&self) -> (uint, uint) {
        unimplemented!()
    }
}

#[cfg(feature = "window")]
impl Window {
    pub fn new(builder: WindowBuilder) -> Result<Window, String> {
        Window::new_impl(builder.dimensions, builder.title.as_slice(), true)
    }
}

#[cfg(feature = "headless")]
impl HeadlessContext {
    pub fn new(builder: HeadlessRendererBuilder) -> Result<HeadlessContext, String> {
        Window::new_impl(Some(builder.dimensions), "", false)
            .map(|w| HeadlessContext(w))
    }
}

impl Window {
    fn new_impl(dimensions: Option<(uint, uint)>, title: &str, visible: bool) -> Result<Window, String> {
        let app = match Window::create_app() {
            Some(app) => app,
            None      => { return Err(format!("Couldn't create NSApplication")); },
        };
        let window = match Window::create_window(dimensions.unwrap_or((800, 600)), title) {
            Some(window) => window,
            None         => { return Err(format!("Couldn't create NSWindow")); },
        };
        let view = match Window::create_view(window) {
            Some(view) => view,
            None       => { return Err(format!("Couldn't create NSView")); },
        };

        let context = match Window::create_context(view) {
            Some(context) => context,
            None          => { return Err(format!("Couldn't create OpenGL context")); },
        };

        unsafe {
            app.activateIgnoringOtherApps_(true);
            window.makeKeyAndOrderFront_(nil);
        }

        let window = Window {
            view: view,
            context: context,
            is_closed: AtomicBool::new(false),
        };

        Ok(window)
    }

    fn create_app() -> Option<id> {
        unsafe {
            let app = NSApp();
            if app == nil {
                None
            } else {
                app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
                app.finishLaunching();
                Some(app)
            }
        }
    }

    fn create_window(dimensions: (uint, uint), title: &str) -> Option<id> {
        unsafe {
            let (width, height) = dimensions;
            let scr_frame = NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64));

            let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
                scr_frame,
                NSTitledWindowMask as NSUInteger | NSClosableWindowMask as NSUInteger | NSMiniaturizableWindowMask as NSUInteger,
                NSBackingStoreBuffered,
                false
            );

            if window == nil {
                None
            } else {
                let title = NSString::alloc(nil).init_str(title);
                window.setTitle_(title);
                window.center();
                window.setAcceptsMouseMovedEvents_(true);
                Some(window)
            }
        }
    }

    fn create_view(window: id) -> Option<id> {
        unsafe {
            let view = NSView::alloc(nil).init();
            if view == nil {
                None
            } else {
                view.setWantsBestResolutionOpenGLSurface_(true);
                window.setContentView_(view);
                Some(view)
            }
        }
    }

    fn create_context(view: id) -> Option<id> {
        unsafe {
            let attributes = [
                NSOpenGLPFADoubleBuffer as uint,
                NSOpenGLPFAClosestPolicy as uint,
                NSOpenGLPFAColorSize as uint, 24,
                NSOpenGLPFAAlphaSize as uint, 8,
                NSOpenGLPFADepthSize as uint, 24,
                NSOpenGLPFAStencilSize as uint, 8,
                0
            ];

            let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(attributes);
            if pixelformat == nil {
                return None;
            }

            let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
            if context == nil {
                None
            } else {
                context.setView_(view);
                Some(context)
            }
        }
    }

    pub fn is_closed(&self) -> bool {
        use std::sync::atomic::Relaxed;
        self.is_closed.load(Relaxed)
    }

    pub fn set_title(&self, _title: &str) {
        unimplemented!()
    }

    pub fn get_position(&self) -> Option<(int, int)> {
        unimplemented!()
    }

    pub fn set_position(&self, _x: int, _y: int) {
        unimplemented!()
    }

    pub fn get_inner_size(&self) -> Option<(uint, uint)> {
        unimplemented!()
    }

    pub fn get_outer_size(&self) -> Option<(uint, uint)> {
        unimplemented!()
    }

    pub fn set_inner_size(&self, _x: uint, _y: uint) {
        unimplemented!()
    }

    pub fn poll_events(&self) -> Vec<Event> {
        let mut events = Vec::new();

        loop {
            unsafe {
                let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                    NSAnyEventMask as u64,
                    NSDate::distantPast(nil),
                    NSDefaultRunLoopMode,
                    true);
                if event == nil { break; }
                NSApp().sendEvent_(event);

                match event.get_type() {
                    NSLeftMouseDown         => { events.push(MouseInput(Pressed, LeftMouseButton)); },
                    NSLeftMouseUp           => { events.push(MouseInput(Released, LeftMouseButton)); },
                    NSRightMouseDown        => { events.push(MouseInput(Pressed, RightMouseButton)); },
                    NSRightMouseUp          => { events.push(MouseInput(Released, RightMouseButton)); },
                    NSMouseMoved            => {
                        let window_point = event.locationInWindow();
                        let view_point = self.view.convertPoint_fromView_(window_point, nil);
                        events.push(MouseMoved((view_point.x as int, view_point.y as int)));
                    },
                    NSKeyDown               => {
                        let received_str = CString::new(event.characters().UTF8String(), false);
                        for received_char in received_str.as_str().unwrap().chars() {
                            if received_char.is_ascii() {
                                events.push(ReceivedCharacter(received_char));
                            }
                        }

                        let vkey =  event::vkeycode_to_element(event.keycode());
                        let modifiers = event::modifierflag_to_element(event.modifierFlags());
                        events.push(KeyboardInput(Pressed, event.keycode() as u8, vkey, modifiers));
                    },
                    NSKeyUp                 => {
                        let vkey =  event::vkeycode_to_element(event.keycode());
                        let modifiers = event::modifierflag_to_element(event.modifierFlags());
                        events.push(KeyboardInput(Released, event.keycode() as u8, vkey, modifiers));
                    },
                    NSFlagsChanged          => {
                        let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask as u64, events::LShift, shift_pressed);
                        if shift_modifier.is_some() {
                            shift_pressed = !shift_pressed;
                            events.push(shift_modifier.unwrap());
                        }
                        let ctrl_modifier = Window::modifier_event(event, appkit::NSControlKeyMask as u64, events::LControl, ctrl_pressed);
                        if ctrl_modifier.is_some() {
                            ctrl_pressed = !ctrl_pressed;
                            events.push(ctrl_modifier.unwrap());
                        }
                        let win_modifier = Window::modifier_event(event, appkit::NSCommandKeyMask as u64, events::LWin, win_pressed);
                        if win_modifier.is_some() {
                            win_pressed = !win_pressed;
                            events.push(win_modifier.unwrap());
                        }
                    },
                    NSScrollWheel           => { },
                    NSOtherMouseDown        => { },
                    NSOtherMouseUp          => { },
                    NSOtherMouseDragged     => { },
                    _                       => { },
                }
            }
        }
        events
    }

    unsafe fn modifier_event(event: id, keymask: u64, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
        if !key_pressed && Window::modifier_key_pressed(event, keymask) {
            return Some(KeyboardInput(Pressed, event.keycode() as u8, Some(key), KeyModifiers::empty()));
        }
        else if key_pressed && !Window::modifier_key_pressed(event, keymask) {
            return Some(KeyboardInput(Released, event.keycode() as u8, Some(key), KeyModifiers::empty()));
        }

        return None;
    }

    unsafe fn modifier_key_pressed(event: id, modifier: u64) -> bool {
        event.modifierFlags() & modifier != 0
    }

    pub fn wait_events(&self) -> Vec<Event> {
        unsafe {
            let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                NSAnyEventMask as u64,
                NSDate::distantFuture(nil),
                NSDefaultRunLoopMode,
                false);
            NSApp().sendEvent_(event);

            self.poll_events()
        }
    }

    pub unsafe fn make_current(&self) {
        self.context.makeCurrentContext();
    }

    pub fn get_proc_address(&self, _addr: &str) -> *const () {
        let symbol_name: CFString = from_str(_addr).unwrap();
        let framework_name: CFString = from_str("com.apple.opengl").unwrap();
        let framework = unsafe {
            CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
        };
        let symbol = unsafe {
            CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
        };
        symbol as *const ()
    }

    pub fn swap_buffers(&self) {
        unsafe { self.context.flushBuffer(); }
    }
}
<|endoftext|>


<commit_before>//! Physics related constants

// taken from: https://en.wikipedia.org/wiki/Physical_constant

pub const planck_length: f64 = 1.61619997e-35; // [m]
pub const planck_mass: f64 = 2.1765113e-8; // [kg]
pub const planck_time: f64 = 5.3910632e-44; // [s]
pub const planck_charge: f64 = 1.87554595641e-18; // [C]
pub const planck_temperature: f64 = 1.41683385e32; // [K]

pub const speed_of_light_vac: f64 = 299792458.0; // [m/s]

// Electromagnetic constants
pub const magnetic_const_vac: f64 = 1.256637061e-6; // [N*A^(-2)]
pub const electric_const_vac: f64 = 8.854187817e-12; // [F*m^(-1)]
pub const coulombs_const_vac: f64 = 8.9875517873681764e9; // [N*m²*C^(-2)]
pub const elementary_charge: f64 = 1.602 176 620898e-19; // [C]
pub const bohr_magneton: f64 = 9.27400999457e-24; // [J*T^(-1)]
pub const conductance_quantum: f64 = 7.748091731018e-5; // [S]
pub const inverse_conductance_quantum: f64 = 12906.403727829; // [Ohm]
pub const josephson_const: f64 = 4.83597852530e14; // [Hz * V^(-1)]
pub const magnetic_flux_quantum: f64 = 2.06783383113e-15; // [Wb]
pub const nuclear_magneton: f64 = 5.050 783 69931e-27; // [J*T^(-1)]
pub const von_klitzing_const: f64 = 25812.807455559; // [Ohm]

// Atomic and nuclear constants
pub const bohr_radius: f64 = 5.291772106712e-11; // [m]
pub const classical_electron_radius: f64 = 2.817940322719e-15; // [m]
pub const electron_mass: f64 = 9.1093835611e-31; // [kg]
pub const fermi_coupling_const: f64 = 1.16637876e-5; // [GeV^(−2)]
pub const fine_structure_const: f64 = 7.297352566417e-3	; // []
pub const hartree_energy: f64 = 4.35974465054e-18; // [J]
pub const proton_mass: f64 = 1.67262189821e-27; // [Kg]
pub const quantum_of_circulation: f64 = 3.636947548617e-4; // [m² * s^(-1)]
pub const rydberg_const: f64 = 10973731.56850865; // [m^(-1)]
pub const thompson_cross_section: f64 = 6.652458715891e-29; // [m²]
pub const weak_mixing_angle: f64 = 0.222321; // []
pub const efimov_factor: f64 = 22.7; // []
<commit_msg>Fix constants<commit_after>//! Physics related constants

// taken from: https://en.wikipedia.org/wiki/Physical_constant

pub const planck_length: f64 = 1.61619997e-35; // [m]
pub const planck_mass: f64 = 2.1765113e-8; // [kg]
pub const planck_time: f64 = 5.3910632e-44; // [s]
pub const planck_charge: f64 = 1.87554595641e-18; // [C]
pub const planck_temperature: f64 = 1.41683385e32; // [K]

pub const speed_of_light_vac: f64 = 299792458.0; // [m/s]

// Electromagnetic constants
pub const magnetic_const_vac: f64 = 1.256637061e-6; // [N*A^(-2)]
pub const electric_const_vac: f64 = 8.854187817e-12; // [F*m^(-1)]
pub const coulombs_const_vac: f64 = 8.9875517873681764e9; // [N*m²*C^(-2)]
pub const elementary_charge: f64 = 1.602176620898e-19; // [C]
pub const bohr_magneton: f64 = 9.27400999457e-24; // [J*T^(-1)]
pub const conductance_quantum: f64 = 7.748091731018e-5; // [S]
pub const inverse_conductance_quantum: f64 = 12906.403727829; // [Ohm]
pub const josephson_const: f64 = 4.83597852530e14; // [Hz * V^(-1)]
pub const magnetic_flux_quantum: f64 = 2.06783383113e-15; // [Wb]
pub const nuclear_magneton: f64 = 5.05078369931e-27; // [J*T^(-1)]
pub const von_klitzing_const: f64 = 25812.807455559; // [Ohm]

// Atomic and nuclear constants
pub const bohr_radius: f64 = 5.291772106712e-11; // [m]
pub const classical_electron_radius: f64 = 2.817940322719e-15; // [m]
pub const electron_mass: f64 = 9.1093835611e-31; // [kg]
pub const fermi_coupling_const: f64 = 1.16637876e-5; // [GeV^(−2)]
pub const fine_structure_const: f64 = 7.297352566417e-3	; // []
pub const hartree_energy: f64 = 4.35974465054e-18; // [J]
pub const proton_mass: f64 = 1.67262189821e-27; // [Kg]
pub const quantum_of_circulation: f64 = 3.636947548617e-4; // [m² * s^(-1)]
pub const rydberg_const: f64 = 10973731.56850865; // [m^(-1)]
pub const thompson_cross_section: f64 = 6.652458715891e-29; // [m²]
pub const weak_mixing_angle: f64 = 0.222321; // []
pub const efimov_factor: f64 = 22.7; // []
<|endoftext|>


<commit_before>//! Commonly used imports, conveniently grouped.
//!
//! To easily import a bunch of commonly-used definitions, import this bundle:
//!
//! ```
//! use cursive::prelude::*;
//! ```

pub use {Cursive, Printer, With};
pub use event::{Event, Key};
pub use view::{Boxable, Identifiable, Selector, View};
pub use views::{BoxView, Button, Checkbox, Dialog, EditView, IdView,
                KeyEventView, LinearLayout, ListView, Panel, ProgressBar,
                SelectView, SliderView, TextArea, TextView};
pub use vec::Vec2;
pub use menu::MenuTree;
<commit_msg>Add DummyView to prelude<commit_after>//! Commonly used imports, conveniently grouped.
//!
//! To easily import a bunch of commonly-used definitions, import this bundle:
//!
//! ```
//! use cursive::prelude::*;
//! ```

pub use {Cursive, Printer, With};
pub use event::{Event, Key};
pub use view::{Boxable, Identifiable, Selector, View};
pub use views::{BoxView, Button, Checkbox, Dialog, DummyView, EditView,
                IdView, KeyEventView, LinearLayout, ListView, Panel,
                ProgressBar, SelectView, SliderView, TextArea, TextView};
pub use vec::Vec2;
pub use menu::MenuTree;
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # Prepare
//!
//! If a pattern needs to be matched against many different things, it can be prepared in order to generate an object that can
//! be used many times without the delay of generating a DFA.
//!
//! ```
//! # use ndfa::*;
//! let match_abcs      = "abc".prepare_to_match();
//! let match_many_abcs = "abc".repeat_forever(1).prepare_to_match();
//!
//! if match("abcabc", match_many_abcs).is_some() { /* ... */ }
//! # assert!(match("abc", match_many_abcs).is_some());
//! ```
//!

use super::countable::*;
use super::symbol_range::*;
use super::state_machine::*;
use super::regular_pattern::*;
use super::symbol_range_dfa::*;
use super::dfa_compiler::*;

///
/// Can be applied to patterns and other objects in order to match them
///
pub trait PrepareToMatch<As> where As: Sized {
    fn prepare_to_match(self) -> As;
}

impl<InputSymbol: Clone+PartialOrd+Countable, OutputSymbol: Ord+Clone> PrepareToMatch<SymbolRangeDfa<InputSymbol, OutputSymbol>>
for Box<StateMachine<SymbolRange<InputSymbol>, OutputSymbol>> {
    #[inline]
    fn prepare_to_match(self) -> SymbolRangeDfa<InputSymbol, OutputSymbol> {
        let builder       = SymbolRangeDfaBuilder::new();
        let state_machine = DfaCompiler::build(self, builder);

        state_machine
    }
}

impl<InputSymbol: Clone+PartialOrd+Countable+'static> PrepareToMatch<SymbolRangeDfa<InputSymbol, bool>>
for Pattern<InputSymbol> {
    #[inline]
    fn prepare_to_match(self) -> SymbolRangeDfa<InputSymbol, bool> {
        let ndfa = self.to_ndfa(true);

        ndfa.prepare_to_match()
    }
}

impl<'a, InputSymbol: Clone+PartialOrd+Countable+'static> PrepareToMatch<SymbolRangeDfa<InputSymbol, bool>>
for &'a ToPattern<InputSymbol> {
    #[inline]
    fn prepare_to_match(self) -> SymbolRangeDfa<InputSymbol, bool> {
        let pattern = self.to_pattern();

        pattern.prepare_to_match()
    }
}

impl<InputSymbol: Clone+PartialOrd+Countable, OutputSymbol> PrepareToMatch<SymbolRangeDfa<InputSymbol, OutputSymbol>> for SymbolRangeDfa<InputSymbol, OutputSymbol> {
    #[inline]
    fn prepare_to_match(self) -> SymbolRangeDfa<InputSymbol, OutputSymbol> {
        self
    }
}

impl<'a> PrepareToMatch<SymbolRangeDfa<char, bool>>
for &'a str {
    #[inline]
    fn prepare_to_match(self) -> SymbolRangeDfa<char, bool> {
        let pattern = self.to_pattern();

        pattern.prepare_to_match()
    }
}
<commit_msg>Fix example a bit (changes failure type)<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # Prepare
//!
//! If a pattern needs to be matched against many different things, it can be prepared in order to generate an object that can
//! be used many times without the delay of generating a DFA.
//!
//! ```
//! # use ndfa::*;
//! let match_abcs      = "abc".prepare_to_match();
//! let match_many_abcs = "abc".repeat_forever(1).prepare_to_match();
//!
//! if matches("abcabc", match_many_abcs).is_some() { /* ... */ }
//! # assert!(matches("abc", match_many_abcs).is_some());
//! ```
//!

use super::countable::*;
use super::symbol_range::*;
use super::state_machine::*;
use super::regular_pattern::*;
use super::symbol_range_dfa::*;
use super::dfa_compiler::*;

///
/// Can be applied to patterns and other objects in order to match them
///
pub trait PrepareToMatch<As> where As: Sized {
    fn prepare_to_match(self) -> As;
}

impl<InputSymbol: Clone+PartialOrd+Countable, OutputSymbol: Ord+Clone> PrepareToMatch<SymbolRangeDfa<InputSymbol, OutputSymbol>>
for Box<StateMachine<SymbolRange<InputSymbol>, OutputSymbol>> {
    #[inline]
    fn prepare_to_match(self) -> SymbolRangeDfa<InputSymbol, OutputSymbol> {
        let builder       = SymbolRangeDfaBuilder::new();
        let state_machine = DfaCompiler::build(self, builder);

        state_machine
    }
}

impl<InputSymbol: Clone+PartialOrd+Countable+'static> PrepareToMatch<SymbolRangeDfa<InputSymbol, bool>>
for Pattern<InputSymbol> {
    #[inline]
    fn prepare_to_match(self) -> SymbolRangeDfa<InputSymbol, bool> {
        let ndfa = self.to_ndfa(true);

        ndfa.prepare_to_match()
    }
}

impl<'a, InputSymbol: Clone+PartialOrd+Countable+'static> PrepareToMatch<SymbolRangeDfa<InputSymbol, bool>>
for &'a ToPattern<InputSymbol> {
    #[inline]
    fn prepare_to_match(self) -> SymbolRangeDfa<InputSymbol, bool> {
        let pattern = self.to_pattern();

        pattern.prepare_to_match()
    }
}

impl<InputSymbol: Clone+PartialOrd+Countable, OutputSymbol> PrepareToMatch<SymbolRangeDfa<InputSymbol, OutputSymbol>> for SymbolRangeDfa<InputSymbol, OutputSymbol> {
    #[inline]
    fn prepare_to_match(self) -> SymbolRangeDfa<InputSymbol, OutputSymbol> {
        self
    }
}

impl<'a> PrepareToMatch<SymbolRangeDfa<char, bool>>
for &'a str {
    #[inline]
    fn prepare_to_match(self) -> SymbolRangeDfa<char, bool> {
        let pattern = self.to_pattern();

        pattern.prepare_to_match()
    }
}
<|endoftext|>


<commit_before>//
// Copyright 2022 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Simple I/O driver for communications between the guest and the host via shared memory.

#![no_std]
extern crate alloc;

use alloc::{collections::VecDeque, vec, vec::Vec};
use x86_64::instructions::port::{PortReadOnly, PortWriteOnly};

/// The default I/O port to use for the most significant bytes of the output buffer guest-physical
/// address.
pub const DEFAULT_OUTPUT_BUFFER_MSB_PORT: u16 = 0x6421;
/// The default I/O port to use for the least significant bytes of the output buffer guest-physical
/// address.
pub const DEFAULT_OUTPUT_BUFFER_LSB_PORT: u16 = 0x6422;
/// The default I/O port to use for the length of output messages.
pub const DEFAULT_OUTPUT_LENGTH_PORT: u16 = 0x6423;

/// The default I/O port to use for the most significant bytes of the input buffer guest-physical
/// address.
pub const DEFAULT_INPUT_BUFFER_MSB_PORT: u16 = 0x6424;
/// The default I/O port to use for the least significant bytes of the input buffer guest-physical
/// address.
pub const DEFAULT_INPUT_BUFFER_LSB_PORT: u16 = 0x6425;
/// The default I/O port to use for the length of input messages.
pub const DEFAULT_INPUT_LENGTH_PORT: u16 = 0x6426;

/// The length of the buffer that will be used for output messages.
pub const OUTPUT_BUFFER_LEGNTH: usize = 4096;
/// The length of the buffer that will be used for input messages.
pub const INPUT_BUFFER_LEGNTH: usize = 4096;

/// The simple I/O channel driver implementation.
pub struct SimpleIo {
    output_buffer: Vec<u8>,
    input_buffer: Vec<u8>,
    output_length_port: PortWriteOnly<u32>,
    input_length_port: PortReadOnly<u32>,
}

impl SimpleIo {
    pub fn new(
        output_buffer_msb_port: u16,
        output_buffer_lsb_port: u16,
        output_length_port: u16,
        input_buffer_msb_port: u16,
        input_buffer_lsb_port: u16,
        input_length_port: u16,
    ) -> Self {
        let output_buffer = vec![0; OUTPUT_BUFFER_LEGNTH];
        let input_buffer = vec![0; INPUT_BUFFER_LEGNTH];
        let output_length_port = PortWriteOnly::new(output_length_port);
        let input_length_port = PortReadOnly::new(input_length_port);

        write_address(
            output_buffer.as_ptr(),
            output_buffer_msb_port,
            output_buffer_lsb_port,
        );
        write_address(
            input_buffer.as_ptr(),
            input_buffer_msb_port,
            input_buffer_lsb_port,
        );

        Self {
            output_buffer,
            input_buffer,
            output_length_port,
            input_length_port,
        }
    }

    /// Reads the next available bytes from the input buffer, if any are available.
    pub fn read_bytes(&mut self) -> Option<VecDeque<u8>> {
        // Safety: we read the value as a u32 and validate it before using it.
        let length = unsafe { self.input_length_port.read() } as usize;

        // Use a memory fence to ensure the read from the device happens before the read from the
        // buffer.
        core::sync::atomic::fence(core::sync::atomic::Ordering::Acquire);

        if length == 0 {
            return None;
        }

        // A length larger than the buffer size indicates a corrupt or malicious VMM device
        // implementation. This is probably not recoverable, so panic.
        assert!(
            length <= INPUT_BUFFER_LEGNTH,
            "Invalid simple IO input message length."
        );
        let mut result = VecDeque::with_capacity(length);
        result.extend(&self.input_buffer[..length]);

        Some(result)
    }

    /// Writes the data to the output buffer and notifies the host.
    ///
    /// Returns the number of bytes written, if any.
    pub fn write_bytes(&mut self, data: &[u8]) -> Option<usize> {
        if data.is_empty() {
            return None;
        }

        let length = core::cmp::min(OUTPUT_BUFFER_LEGNTH, data.len());
        self.output_buffer.copy_from_slice(&data[..length]);

        // Use a memory fence to ensure that the data is written to the buffer before we notify the
        // VMM.
        core::sync::atomic::fence(core::sync::atomic::Ordering::Release);

        // Safety: this usage is safe, as we as only write an uninterpreted u32 value to the port.
        unsafe {
            self.output_length_port.write(length as u32);
        }

        Some(length)
    }
}

impl Default for SimpleIo {
    fn default() -> Self {
        Self::new(
            DEFAULT_OUTPUT_BUFFER_MSB_PORT,
            DEFAULT_OUTPUT_BUFFER_LSB_PORT,
            DEFAULT_OUTPUT_LENGTH_PORT,
            DEFAULT_INPUT_BUFFER_MSB_PORT,
            DEFAULT_INPUT_BUFFER_LSB_PORT,
            DEFAULT_INPUT_LENGTH_PORT,
        )
    }
}

fn write_address(buffer_pointer: *const u8, msb_port: u16, lsb_port: u16) {
    // Split the 64-bit address into its least- and most significant bytes.
    let address = get_guest_physiscal_address(buffer_pointer) as u64;
    let address_msb = (address >> 32) as u32;
    let address_lsb = address as u32;
    // Safety: this usage is safe, as we as only write uninterpreted u32 values to the ports.
    unsafe {
        PortWriteOnly::new(msb_port).write(address_msb);
        PortWriteOnly::new(lsb_port).write(address_lsb);
    }
}

fn get_guest_physiscal_address(pointer: *const u8) -> usize {
    // Assume identity mapping for now.
    pointer as usize
}
<commit_msg>Fix mismatched buffer length in Simple IO (#3095)<commit_after>//
// Copyright 2022 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Simple I/O driver for communications between the guest and the host via shared memory.

#![no_std]
extern crate alloc;

use alloc::{collections::VecDeque, vec, vec::Vec};
use x86_64::instructions::port::{PortReadOnly, PortWriteOnly};

/// The default I/O port to use for the most significant bytes of the output buffer guest-physical
/// address.
pub const DEFAULT_OUTPUT_BUFFER_MSB_PORT: u16 = 0x6421;
/// The default I/O port to use for the least significant bytes of the output buffer guest-physical
/// address.
pub const DEFAULT_OUTPUT_BUFFER_LSB_PORT: u16 = 0x6422;
/// The default I/O port to use for the length of output messages.
pub const DEFAULT_OUTPUT_LENGTH_PORT: u16 = 0x6423;

/// The default I/O port to use for the most significant bytes of the input buffer guest-physical
/// address.
pub const DEFAULT_INPUT_BUFFER_MSB_PORT: u16 = 0x6424;
/// The default I/O port to use for the least significant bytes of the input buffer guest-physical
/// address.
pub const DEFAULT_INPUT_BUFFER_LSB_PORT: u16 = 0x6425;
/// The default I/O port to use for the length of input messages.
pub const DEFAULT_INPUT_LENGTH_PORT: u16 = 0x6426;

/// The length of the buffer that will be used for output messages.
pub const OUTPUT_BUFFER_LEGNTH: usize = 4096;
/// The length of the buffer that will be used for input messages.
pub const INPUT_BUFFER_LEGNTH: usize = 4096;

/// The simple I/O channel driver implementation.
pub struct SimpleIo {
    output_buffer: Vec<u8>,
    input_buffer: Vec<u8>,
    output_length_port: PortWriteOnly<u32>,
    input_length_port: PortReadOnly<u32>,
}

impl SimpleIo {
    pub fn new(
        output_buffer_msb_port: u16,
        output_buffer_lsb_port: u16,
        output_length_port: u16,
        input_buffer_msb_port: u16,
        input_buffer_lsb_port: u16,
        input_length_port: u16,
    ) -> Self {
        let output_buffer = vec![0; OUTPUT_BUFFER_LEGNTH];
        let input_buffer = vec![0; INPUT_BUFFER_LEGNTH];
        let output_length_port = PortWriteOnly::new(output_length_port);
        let input_length_port = PortReadOnly::new(input_length_port);

        write_address(
            output_buffer.as_ptr(),
            output_buffer_msb_port,
            output_buffer_lsb_port,
        );
        write_address(
            input_buffer.as_ptr(),
            input_buffer_msb_port,
            input_buffer_lsb_port,
        );

        Self {
            output_buffer,
            input_buffer,
            output_length_port,
            input_length_port,
        }
    }

    /// Reads the next available bytes from the input buffer, if any are available.
    pub fn read_bytes(&mut self) -> Option<VecDeque<u8>> {
        // Safety: we read the value as a u32 and validate it before using it.
        let length = unsafe { self.input_length_port.read() } as usize;

        // Use a memory fence to ensure the read from the device happens before the read from the
        // buffer.
        core::sync::atomic::fence(core::sync::atomic::Ordering::Acquire);

        if length == 0 {
            return None;
        }

        // A length larger than the buffer size indicates a corrupt or malicious VMM device
        // implementation. This is probably not recoverable, so panic.
        assert!(
            length <= INPUT_BUFFER_LEGNTH,
            "Invalid simple IO input message length."
        );
        let mut result = VecDeque::with_capacity(length);
        result.extend(&self.input_buffer[..length]);

        Some(result)
    }

    /// Writes the data to the output buffer and notifies the host.
    ///
    /// Returns the number of bytes written, if any.
    pub fn write_bytes(&mut self, data: &[u8]) -> Option<usize> {
        if data.is_empty() {
            return None;
        }

        let length = core::cmp::min(OUTPUT_BUFFER_LEGNTH, data.len());
        self.output_buffer[..length].copy_from_slice(&data[..length]);

        // Use a memory fence to ensure that the data is written to the buffer before we notify the
        // VMM.
        core::sync::atomic::fence(core::sync::atomic::Ordering::Release);

        // Safety: this usage is safe, as we as only write an uninterpreted u32 value to the port.
        unsafe {
            self.output_length_port.write(length as u32);
        }

        Some(length)
    }
}

impl Default for SimpleIo {
    fn default() -> Self {
        Self::new(
            DEFAULT_OUTPUT_BUFFER_MSB_PORT,
            DEFAULT_OUTPUT_BUFFER_LSB_PORT,
            DEFAULT_OUTPUT_LENGTH_PORT,
            DEFAULT_INPUT_BUFFER_MSB_PORT,
            DEFAULT_INPUT_BUFFER_LSB_PORT,
            DEFAULT_INPUT_LENGTH_PORT,
        )
    }
}

fn write_address(buffer_pointer: *const u8, msb_port: u16, lsb_port: u16) {
    // Split the 64-bit address into its least- and most significant bytes.
    let address = get_guest_physiscal_address(buffer_pointer) as u64;
    let address_msb = (address >> 32) as u32;
    let address_lsb = address as u32;
    // Safety: this usage is safe, as we as only write uninterpreted u32 values to the ports.
    unsafe {
        PortWriteOnly::new(msb_port).write(address_msb);
        PortWriteOnly::new(lsb_port).write(address_lsb);
    }
}

fn get_guest_physiscal_address(pointer: *const u8) -> usize {
    // Assume identity mapping for now.
    pointer as usize
}
<|endoftext|>


<commit_before>use {
    crate::future::{CatchUnwind, FutureExt},
    futures_channel::oneshot::{self, Sender, Receiver},
    futures_core::{
        future::Future,
        task::{Context, Poll},
    },
    std::{
        any::Any,
        fmt,
        panic::{self, AssertUnwindSafe},
        pin::Pin,
        sync::{
            Arc,
            atomic::{AtomicBool, Ordering},
        },
        thread,
    },
    pin_project::pin_project,
};

/// The handle to a remote future returned by
/// [`remote_handle`](crate::future::FutureExt::remote_handle). When you drop this,
/// the remote future will be woken up to be dropped by the executor.
///
/// ## Unwind safety
///
/// When the remote future panics, [Remote] will catch the unwind and transfer it to
/// the thread where `RemoteHandle` is being awaited. This is good for the common
/// case where [Remote] is spawned on a threadpool. It is unlikely that other code
/// in the executor working thread shares mutable data with the spawned future and we
/// preserve the executor from losing its working threads.
///
/// If you run the future locally and send the handle of to be awaited elsewhere, you
/// must be careful with regard to unwind safety because the thread in which the future
/// is polled will keep running after the panic and the thread running the [RemoteHandle]
/// will unwind.
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
#[cfg_attr(docsrs, doc(cfg(feature = "channel")))]
pub struct RemoteHandle<T> {
    rx: Receiver<thread::Result<T>>,
    keep_running: Arc<AtomicBool>,
}

impl<T> RemoteHandle<T> {
    /// Drops this handle *without* canceling the underlying future.
    ///
    /// This method can be used if you want to drop the handle, but let the
    /// execution continue.
    pub fn forget(self) {
        self.keep_running.store(true, Ordering::SeqCst);
    }
}

impl<T: 'static> Future for RemoteHandle<T> {
    type Output = T;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
        match ready!(self.rx.poll_unpin(cx)) {
            Ok(Ok(output)) => Poll::Ready(output),
            // the remote future panicked.
            Ok(Err(e)) => panic::resume_unwind(e),
            // The oneshot sender was dropped.
            Err(e) => panic::resume_unwind(Box::new(e)),
        }
    }
}

type SendMsg<Fut> = Result<<Fut as Future>::Output, Box<(dyn Any + Send + 'static)>>;

/// A future which sends its output to the corresponding `RemoteHandle`.
/// Created by [`remote_handle`](crate::future::FutureExt::remote_handle).
#[pin_project]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[cfg_attr(docsrs, doc(cfg(feature = "channel")))]
pub struct Remote<Fut: Future> {
    tx: Option<Sender<SendMsg<Fut>>>,
    keep_running: Arc<AtomicBool>,
    #[pin]
    future: CatchUnwind<AssertUnwindSafe<Fut>>,
}

impl<Fut: Future + fmt::Debug> fmt::Debug for Remote<Fut> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("Remote")
            .field(&self.future)
            .finish()
    }
}

impl<Fut: Future> Future for Remote<Fut> {
    type Output = ();

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
        let this = self.project();

        if let Poll::Ready(_) = this.tx.as_mut().unwrap().poll_canceled(cx) {
            if !this.keep_running.load(Ordering::SeqCst) {
                // Cancelled, bail out
                return Poll::Ready(())
            }
        }

        let output = ready!(this.future.poll(cx));

        // if the receiving end has gone away then that's ok, we just ignore the
        // send error here.
        drop(this.tx.take().unwrap().send(output));
        Poll::Ready(())
    }
}

pub(super) fn remote_handle<Fut: Future>(future: Fut) -> (Remote<Fut>, RemoteHandle<Fut::Output>) {
    let (tx, rx) = oneshot::channel();
    let keep_running = Arc::new(AtomicBool::new(false));

    // Unwind Safety: See the docs for RemoteHandle.
    let wrapped = Remote {
        future: AssertUnwindSafe(future).catch_unwind(),
        tx: Some(tx),
        keep_running: keep_running.clone(),
    };

    (wrapped, RemoteHandle { rx, keep_running })
}
<commit_msg>Fix clippy::redundant_pattern_matching warning<commit_after>use {
    crate::future::{CatchUnwind, FutureExt},
    futures_channel::oneshot::{self, Sender, Receiver},
    futures_core::{
        future::Future,
        task::{Context, Poll},
    },
    std::{
        any::Any,
        fmt,
        panic::{self, AssertUnwindSafe},
        pin::Pin,
        sync::{
            Arc,
            atomic::{AtomicBool, Ordering},
        },
        thread,
    },
    pin_project::pin_project,
};

/// The handle to a remote future returned by
/// [`remote_handle`](crate::future::FutureExt::remote_handle). When you drop this,
/// the remote future will be woken up to be dropped by the executor.
///
/// ## Unwind safety
///
/// When the remote future panics, [Remote] will catch the unwind and transfer it to
/// the thread where `RemoteHandle` is being awaited. This is good for the common
/// case where [Remote] is spawned on a threadpool. It is unlikely that other code
/// in the executor working thread shares mutable data with the spawned future and we
/// preserve the executor from losing its working threads.
///
/// If you run the future locally and send the handle of to be awaited elsewhere, you
/// must be careful with regard to unwind safety because the thread in which the future
/// is polled will keep running after the panic and the thread running the [RemoteHandle]
/// will unwind.
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
#[cfg_attr(docsrs, doc(cfg(feature = "channel")))]
pub struct RemoteHandle<T> {
    rx: Receiver<thread::Result<T>>,
    keep_running: Arc<AtomicBool>,
}

impl<T> RemoteHandle<T> {
    /// Drops this handle *without* canceling the underlying future.
    ///
    /// This method can be used if you want to drop the handle, but let the
    /// execution continue.
    pub fn forget(self) {
        self.keep_running.store(true, Ordering::SeqCst);
    }
}

impl<T: 'static> Future for RemoteHandle<T> {
    type Output = T;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
        match ready!(self.rx.poll_unpin(cx)) {
            Ok(Ok(output)) => Poll::Ready(output),
            // the remote future panicked.
            Ok(Err(e)) => panic::resume_unwind(e),
            // The oneshot sender was dropped.
            Err(e) => panic::resume_unwind(Box::new(e)),
        }
    }
}

type SendMsg<Fut> = Result<<Fut as Future>::Output, Box<(dyn Any + Send + 'static)>>;

/// A future which sends its output to the corresponding `RemoteHandle`.
/// Created by [`remote_handle`](crate::future::FutureExt::remote_handle).
#[pin_project]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[cfg_attr(docsrs, doc(cfg(feature = "channel")))]
pub struct Remote<Fut: Future> {
    tx: Option<Sender<SendMsg<Fut>>>,
    keep_running: Arc<AtomicBool>,
    #[pin]
    future: CatchUnwind<AssertUnwindSafe<Fut>>,
}

impl<Fut: Future + fmt::Debug> fmt::Debug for Remote<Fut> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("Remote")
            .field(&self.future)
            .finish()
    }
}

impl<Fut: Future> Future for Remote<Fut> {
    type Output = ();

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
        let this = self.project();

        if this.tx.as_mut().unwrap().poll_canceled(cx).is_ready()
            && !this.keep_running.load(Ordering::SeqCst)
        {
            // Cancelled, bail out
            return Poll::Ready(());
        }

        let output = ready!(this.future.poll(cx));

        // if the receiving end has gone away then that's ok, we just ignore the
        // send error here.
        drop(this.tx.take().unwrap().send(output));
        Poll::Ready(())
    }
}

pub(super) fn remote_handle<Fut: Future>(future: Fut) -> (Remote<Fut>, RemoteHandle<Fut::Output>) {
    let (tx, rx) = oneshot::channel();
    let keep_running = Arc::new(AtomicBool::new(false));

    // Unwind Safety: See the docs for RemoteHandle.
    let wrapped = Remote {
        future: AssertUnwindSafe(future).catch_unwind(),
        tx: Some(tx),
        keep_running: keep_running.clone(),
    };

    (wrapped, RemoteHandle { rx, keep_running })
}
<|endoftext|>


<commit_before>extern crate log;

pub use cli::Config;

use std::io::stderr;
use std::io::Write;
use log::{LogRecord, LogLevel, LogLevelFilter, LogMetadata, SetLoggerError};

pub struct ImagLogger {
    lvl: LogLevel,
}

impl ImagLogger {

    pub fn new(lvl: LogLevel) -> ImagLogger {
        ImagLogger {
            lvl: lvl,
        }
    }

    pub fn early() -> Result<(), SetLoggerError> {
        ImagLogger::init_logger(LogLevelFilter::Error)
    }

    pub fn init(config: &Config) -> Result<(), SetLoggerError> {
        if config.is_debugging() {
            ImagLogger::init_logger(LogLevelFilter::Debug)
        } else if config.is_verbose() {
            ImagLogger::init_logger(LogLevelFilter::Info)
        } else {
            ImagLogger::init_logger(LogLevelFilter::Error)
        }

    }

    fn init_logger(lvlflt : LogLevelFilter) -> Result<(), SetLoggerError> {
        log::set_logger(|max_log_lvl| {
            max_log_lvl.set(lvlflt);
            Box::new(ImagLogger::new(lvlflt.to_log_level().unwrap()))
        })
    }

}

impl log::Log for ImagLogger {

    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.lvl
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            println!("[{}]: {}", record.level(), record.args());
        }
    }
}

pub struct Runtime<'a> {
    pub config : Config<'a>,
}

impl<'a> Runtime<'a> {

    pub fn new(config : Config<'a>) -> Runtime<'a> {
        Runtime {
            config: config,
        }
    }

    pub fn debug(&self, string : &'static str) {
        if self.config.is_debugging() {
            println!("{}", string);
        }
    }

    pub fn print(&self, string : &'static str) {
        if self.config.is_verbose() || self.config.is_debugging() {
            println!("{}", string);
        }
    }

    pub fn trace(string : &'static str) {
        // writeln!(&mut stderr, "{}", string);
    }

    pub fn is_verbose(&self) -> bool {
        self.config.is_verbose()
    }

    pub fn is_debugging(&self) -> bool {
        self.config.is_debugging()
    }

}
<commit_msg>Remove old logging functions<commit_after>extern crate log;

pub use cli::Config;

use std::io::stderr;
use std::io::Write;
use log::{LogRecord, LogLevel, LogLevelFilter, LogMetadata, SetLoggerError};

pub struct ImagLogger {
    lvl: LogLevel,
}

impl ImagLogger {

    pub fn new(lvl: LogLevel) -> ImagLogger {
        ImagLogger {
            lvl: lvl,
        }
    }

    pub fn early() -> Result<(), SetLoggerError> {
        ImagLogger::init_logger(LogLevelFilter::Error)
    }

    pub fn init(config: &Config) -> Result<(), SetLoggerError> {
        if config.is_debugging() {
            ImagLogger::init_logger(LogLevelFilter::Debug)
        } else if config.is_verbose() {
            ImagLogger::init_logger(LogLevelFilter::Info)
        } else {
            ImagLogger::init_logger(LogLevelFilter::Error)
        }

    }

    fn init_logger(lvlflt : LogLevelFilter) -> Result<(), SetLoggerError> {
        log::set_logger(|max_log_lvl| {
            max_log_lvl.set(lvlflt);
            Box::new(ImagLogger::new(lvlflt.to_log_level().unwrap()))
        })
    }

}

impl log::Log for ImagLogger {

    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.lvl
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            println!("[{}]: {}", record.level(), record.args());
        }
    }
}

pub struct Runtime<'a> {
    pub config : Config<'a>,
}

impl<'a> Runtime<'a> {

    pub fn new(config : Config<'a>) -> Runtime<'a> {
        Runtime {
            config: config,
        }
    }

    pub fn is_verbose(&self) -> bool {
        self.config.is_verbose()
    }

    pub fn is_debugging(&self) -> bool {
        self.config.is_debugging()
    }

}
<|endoftext|>


<commit_before>// Copyright 2013 The SAX-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[comment = "Wrapper for libxml2's SAX parser."];
#[crate_id = "github.com/bjz/sax-rs#sax:0.1"];

#[crate_type = "lib"];

#[feature(globs)];

extern crate sync;

use std::cast;
use std::comm::{Receiver, channel};
use std::libc::{c_char, c_int};
use std::str;
use std::io::{File, IoResult};
use std::fmt;
use std::vec_ng::Vec;
// use std::task;

use error::ErrorData;

pub mod error;
pub mod ffi;
mod extfn;

/// Events to be sent by the parser.
#[deriving(Eq, Clone)]
pub enum ParseEvent {
    /// The document has begun to be processed.
    StartDocument,
    /// The document processing has finished.
    EndDocument,
    /// An opening tag has was parsed.
    StartElement(~str, Attributes),
    /// A closing tag was parsed.
    EndElement(~str),
    /// Some characters between tags have been recived.
    Characters(~str),
    /// A comment tag was parsed.
    Comment(~str),
    /// A `CDATA` block was parsed.
    CdataBlock(~str),
}

impl fmt::Show for ParseEvent {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StartDocument => write!(fmt.buf, "START DOCUMENT"),
            EndDocument => write!(fmt.buf, "END DOCUMENT"),
            StartElement(ref name, ref atts) => write!(fmt.buf, "<{}{}>", *name, atts),
            EndElement(ref name) => write!(fmt.buf, "</{}>", *name),
            Characters(ref ch) => write!(fmt.buf, "{}", ch.clone()),
            Comment(ref value) => write!(fmt.buf, "", *value),
            CdataBlock(ref value) => write!(fmt.buf, "<![CDATA[{}]]>", *value),
        }
    }
}

#[deriving(Eq, Clone)]
pub struct Attribute {
    name: ~str,
    value: ~str,
}

/// A list of attributes
#[deriving(Eq, Clone)]
pub struct Attributes(Vec<Attribute>);

impl Attributes {
    unsafe fn from_buf(atts: **ffi::xmlChar) -> Attributes {
        let mut ret = Vec::new();
        let mut ptr = atts as **c_char;
        while !ptr.is_null() && !(*ptr).is_null() {
            ret.push(
                Attribute {
                    name: str::raw::from_c_str(*ptr),
                    value: str::raw::from_c_str(*ptr.offset(1)),
                }
            );
            ptr = ptr.offset(2);
        }
        Attributes(ret)
    }

    pub fn find<'a>(&'a self, name: &str) -> Option<&'a str> {
        let Attributes(ref s) = *self;
        s.iter()
         .find(|att| name == att.name)
         .map(|att| att.value.as_slice())
    }

    pub fn get<'a>(&'a self, name: &str) -> &'a str {
        self.find(name).expect(format!("Could not find an attribute with the name \"{}\"", name))
    }

    pub fn find_clone(&self, name: &str) -> Option<~str> {
        self.find(name).map(|v| v.to_owned())
    }

    pub fn get_clone(&self, name: &str) -> ~str {
        self.get(name).to_owned()
    }
}

impl fmt::Show for Attributes {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let Attributes(ref s) = *self;
        for att in s.iter() {
            try!(write!(fmt.buf, " {}=\"{}\"", att.name, att.value));
        }
        Ok(())
    }
}

/// Either a parse event wrapped in `Ok` or some Error data wrapped in `Err`.
pub type ParseResult = Result<ParseEvent, ErrorData>;

/// Parses the entire XML string.
///
/// # Returns
///
/// A receiver that recieves parse results.
///
/// # Example
///
/// ~~~rust
/// let parser = parse_str("<yo>hullo!</yo>");
/// for result in parser.iter() {
///     match result {
///         Ok(StartDocument) => (),
///         Ok(EndDocument) => break,
///         Ok(event) => println!("{}", event.to_str()),
///         Err(err) => println!("{}", err.to_str()),
///     }
/// }
/// ~~~
#[inline(never)]
pub fn parse_str(src: &str) -> Receiver<ParseResult> {
    // ensure that the xml library is ready for use
    use sync::one::{Once, ONCE_INIT};
    static mut INIT: Once = ONCE_INIT;
    unsafe {
        INIT.doit(|| {
            ffi::xmlInitParser();
            std::rt::at_exit(proc() ffi::xmlCleanupParser());
        })
    }

    let len = src.len() as c_int;
    src.to_c_str().with_ref(|c_str| {
        let (sender, receiver) = channel();
        // do task::spawn {
            unsafe {
                ffi::xmlSAXUserParseMemory(&extfn::new_handler(),
                                           cast::transmute(&sender),
                                           c_str, len);
            }
        // }
        receiver
    })
}

pub fn parse_file(path: &Path) -> IoResult<Receiver<ParseResult> > {
  File::open(path)
    .and_then( |mut file| {
      file.read_to_str()
    })
    .and_then( |contents| {
      Ok(parse_str(contents))
    })
}

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

    fn get_mock_atts() -> Attributes {
        Attributes(Vec::from_slice([
            Attribute { name: ~"foo", value: ~"0" },
            Attribute { name: ~"bar", value: ~"1" },
            Attribute { name: ~"baz", value: ~"2" }
        ]))
    }

    #[test]
    fn test_att_get() {
        let atts = get_mock_atts();
        assert_eq!(atts.get("foo"), "0");
        assert_eq!(atts.get("bar"), "1");
        assert_eq!(atts.get("baz"), "2");
    }

    #[test]
    fn test_att_find() {
        let atts = get_mock_atts();
        assert_eq!(atts.find("foo"), Some("0"));
        assert_eq!(atts.find("bar"), Some("1"));
        assert_eq!(atts.find("baz"), Some("2"));
    }

    #[test]
    fn test() {
        let sax = parse_str(
            "<hello><this />test</hello>"
        );
        loop {
            match sax.recv() {
                Ok(StartDocument) => (),
                Ok(EndDocument) => break,
                Ok(event) => println!("{}", event.to_str()),
                Err(err) => println!("{}", err.to_str()),
            }
        }
    }
}
<commit_msg>Remove commented out code<commit_after>// Copyright 2013 The SAX-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[comment = "Wrapper for libxml2's SAX parser."];
#[crate_id = "github.com/bjz/sax-rs#sax:0.1"];

#[crate_type = "lib"];

#[feature(globs)];

extern crate sync;

use std::cast;
use std::comm::{Receiver, channel};
use std::libc::{c_char, c_int};
use std::str;
use std::io::{File, IoResult};
use std::fmt;
use std::vec_ng::Vec;

use error::ErrorData;

pub mod error;
pub mod ffi;
mod extfn;

/// Events to be sent by the parser.
#[deriving(Eq, Clone)]
pub enum ParseEvent {
    /// The document has begun to be processed.
    StartDocument,
    /// The document processing has finished.
    EndDocument,
    /// An opening tag has was parsed.
    StartElement(~str, Attributes),
    /// A closing tag was parsed.
    EndElement(~str),
    /// Some characters between tags have been recived.
    Characters(~str),
    /// A comment tag was parsed.
    Comment(~str),
    /// A `CDATA` block was parsed.
    CdataBlock(~str),
}

impl fmt::Show for ParseEvent {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StartDocument => write!(fmt.buf, "START DOCUMENT"),
            EndDocument => write!(fmt.buf, "END DOCUMENT"),
            StartElement(ref name, ref atts) => write!(fmt.buf, "<{}{}>", *name, atts),
            EndElement(ref name) => write!(fmt.buf, "</{}>", *name),
            Characters(ref ch) => write!(fmt.buf, "{}", ch.clone()),
            Comment(ref value) => write!(fmt.buf, "", *value),
            CdataBlock(ref value) => write!(fmt.buf, "<![CDATA[{}]]>", *value),
        }
    }
}

#[deriving(Eq, Clone)]
pub struct Attribute {
    name: ~str,
    value: ~str,
}

/// A list of attributes
#[deriving(Eq, Clone)]
pub struct Attributes(Vec<Attribute>);

impl Attributes {
    unsafe fn from_buf(atts: **ffi::xmlChar) -> Attributes {
        let mut ret = Vec::new();
        let mut ptr = atts as **c_char;
        while !ptr.is_null() && !(*ptr).is_null() {
            ret.push(
                Attribute {
                    name: str::raw::from_c_str(*ptr),
                    value: str::raw::from_c_str(*ptr.offset(1)),
                }
            );
            ptr = ptr.offset(2);
        }
        Attributes(ret)
    }

    pub fn find<'a>(&'a self, name: &str) -> Option<&'a str> {
        let Attributes(ref s) = *self;
        s.iter()
         .find(|att| name == att.name)
         .map(|att| att.value.as_slice())
    }

    pub fn get<'a>(&'a self, name: &str) -> &'a str {
        self.find(name).expect(format!("Could not find an attribute with the name \"{}\"", name))
    }

    pub fn find_clone(&self, name: &str) -> Option<~str> {
        self.find(name).map(|v| v.to_owned())
    }

    pub fn get_clone(&self, name: &str) -> ~str {
        self.get(name).to_owned()
    }
}

impl fmt::Show for Attributes {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let Attributes(ref s) = *self;
        for att in s.iter() {
            try!(write!(fmt.buf, " {}=\"{}\"", att.name, att.value));
        }
        Ok(())
    }
}

/// Either a parse event wrapped in `Ok` or some Error data wrapped in `Err`.
pub type ParseResult = Result<ParseEvent, ErrorData>;

/// Parses the entire XML string.
///
/// # Returns
///
/// A receiver that recieves parse results.
///
/// # Example
///
/// ~~~rust
/// let parser = parse_str("<yo>hullo!</yo>");
/// for result in parser.iter() {
///     match result {
///         Ok(StartDocument) => (),
///         Ok(EndDocument) => break,
///         Ok(event) => println!("{}", event.to_str()),
///         Err(err) => println!("{}", err.to_str()),
///     }
/// }
/// ~~~
#[inline(never)]
pub fn parse_str(src: &str) -> Receiver<ParseResult> {
    // ensure that the xml library is ready for use
    use sync::one::{Once, ONCE_INIT};
    static mut INIT: Once = ONCE_INIT;
    unsafe {
        INIT.doit(|| {
            ffi::xmlInitParser();
            std::rt::at_exit(proc() ffi::xmlCleanupParser());
        })
    }

    let len = src.len() as c_int;
    src.to_c_str().with_ref(|c_str| {
        let (sender, receiver) = channel();
        unsafe {
            ffi::xmlSAXUserParseMemory(&extfn::new_handler(),
                                       cast::transmute(&sender),
                                       c_str, len);
        }
        receiver
    })
}

pub fn parse_file(path: &Path) -> IoResult<Receiver<ParseResult> > {
  File::open(path)
    .and_then( |mut file| {
      file.read_to_str()
    })
    .and_then( |contents| {
      Ok(parse_str(contents))
    })
}

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

    fn get_mock_atts() -> Attributes {
        Attributes(Vec::from_slice([
            Attribute { name: ~"foo", value: ~"0" },
            Attribute { name: ~"bar", value: ~"1" },
            Attribute { name: ~"baz", value: ~"2" }
        ]))
    }

    #[test]
    fn test_att_get() {
        let atts = get_mock_atts();
        assert_eq!(atts.get("foo"), "0");
        assert_eq!(atts.get("bar"), "1");
        assert_eq!(atts.get("baz"), "2");
    }

    #[test]
    fn test_att_find() {
        let atts = get_mock_atts();
        assert_eq!(atts.find("foo"), Some("0"));
        assert_eq!(atts.find("bar"), Some("1"));
        assert_eq!(atts.find("baz"), Some("2"));
    }

    #[test]
    fn test() {
        let sax = parse_str(
            "<hello><this />test</hello>"
        );
        loop {
            match sax.recv() {
                Ok(StartDocument) => (),
                Ok(EndDocument) => break,
                Ok(event) => println!("{}", event.to_str()),
                Err(err) => println!("{}", err.to_str()),
            }
        }
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Support for the 8259 Programmable Interrupt Controller.
//!
//! The 8259 PIC controls all of our IO IRQs. The PIC recieves IRQ requests
//! and feeds them to the CPU in order. An x86 system typically has two PICs,
//! PIC1 and PIC2, each of which provides 8 IRQs. Two PICs provide us with 15
//! unique IRQs, because one interrupt on the leader PIC is linked to interrupts
//! on the follower PIC.
//!
//! Mistakes were made, and Intel boneheadedly decided that it was a good idea
//! to map the vector offset of PIC1 to 8, so that it maps to interrupts
//! 8 ... 15 in the IDT. This conflicts with some of the interrupt numbers
//! used by CPU exceptions. Therefore, we must remap the PIC vectors so that
//! PIC1 starts at 32 and PIC2 at 40.

use ::io::Write;
use super::Port;
use spin::Mutex;
use core::mem::transmute;

/// Starting offset for PIC1
const OFFSET: u8 = 0x20;

/// Commands to send to the PIC
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
enum Command { Mode8086 = 0x01
             , Init     = 0x11
             , EndIRQ   = 0x20
             , ReadIRR  = 0x0a
             , ReadISR  = 0x0b
             }

/// List of IRQs on the x86.
///
/// See here for more info:
/// https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interrupt_Controller
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
pub enum IRQ { /// System timer IRQ
               Timer        = 0 + OFFSET
             , /// PS/2 keyboard controller
               PS2Keyboard  = 1 + OFFSET
             , /// PIC2 cascade IRQ
               Cascade      = 2 + OFFSET
             , /// COM2 serial port
               COM2         = 3 + OFFSET
             , /// COM1 serial port
               COM1         = 4 + OFFSET
             , /// Line printer 2
               LPT2         = 5 + OFFSET
             , /// Floppy disc controller
               Floppy       = 6 + OFFSET
             , /// Line printer 1
               LPT1         = 7 + OFFSET
             , /// CMOS clock
               RTCTimer     = 8 + OFFSET
             , /// PS/2 mouse controller
               PS2Mouse     = 12 + OFFSET
             , /// Floating-point Coprocessor
               FPU          = 13 + OFFSET
             , /// ATA channel 1
               PrimaryATA   = 14 + OFFSET
             , /// ATA channel 2
               SecondaryATA = 15 + OFFSET
             }

struct PIC {
    /// The base offset to which interrupts on this PIC are mapped
    offset: u8
  , /// The port on the CPU that sends commands to this PIC.
    command_port: Port
  , /// The port that sends and recieves data from the PIC
    data_port: Port
}

impl PIC {

    const fn leader() -> PIC {
        unsafe {
            PIC { offset: OFFSET
                , command_port: Port::new(0x20)
                , data_port: Port::new(0x21)
                }
        }
    }

    const fn follower() -> PIC {
        unsafe {
            PIC { offset: OFFSET + 8
                , command_port: Port::new(0xA0)
                , data_port: Port::new(0xA1)
                }
        }
    }

    #[inline]
    fn is_leader(&self) -> bool {
        self.offset == OFFSET
    }

    #[inline]
    fn send_command(&self, command: Command) {
        unsafe {
            self.command_port
                .out8(command as u8)
            }
    }

    #[inline]
    fn initialize(&self) {
        self.send_command(Command::Init)
    }

    #[inline]
    fn read_ISR(&self) -> u8 {
        self.send_command(Command::ReadISR);
        unsafe { self.data_port.in8() }
    }

    #[inline]
    fn read_IRR(&self) -> u8 {
        self.send_command(Command::ReadIRR);
        unsafe { self.data_port.in8() }
    }

}

trait IRQHandler {
    /// Returns whether or not this handler handles the given IRQ
    fn handles(&self, irq: IRQ) -> bool;
    /// End an interrupt request
    fn end_interrupt(&self, irq: IRQ);
}

impl IRQHandler for PIC {

    fn handles(&self, irq: IRQ) -> bool {
        self.offset <= (irq as u8) && (irq as u8) < self.offset + 8
    }

    fn end_interrupt(&self, irq: IRQ) {
        self.send_command(Command::EndIRQ)
    }
}

/// A pair of PICs in cascade mode.
///
/// This is the standard configuration on all modern x86 systems.
struct PICs (PIC, PIC);

impl PICs {
    const fn new() -> Self {
        PICs (PIC::leader(), PIC::follower())
    }

    /// Initialize the system's PICs.
    fn initialize(&mut self) {
        // Read the default interrupt masks from PIC1 and PIC2
        let (saved_mask1, saved_mask2)
            = unsafe { (self.0.data_port.in8(), self.1.data_port.in8()) };

        // Send both PICs the 'initialize' command.
        self.0.initialize();
        self.1.initialize();

        // Each PIC then expects us to send it the following:
        self.0.data_port
            .write(&[ self.0.offset     // 1. the PIC's new vector offset
                    , 0x04              // 2. number to configure PIC cascading
                    , Command::Mode8086 as u8 // 3. command for 8086 mode
                    , saved_mask1       // 4. finally, the mask we saved earlier
                    ]);

        self.1.data_port
            .write(&[ self.1.offset
                    , 0x02              // PIC2 gets 0x02 to set it as follower
                    , Command::Mode8086 as u8
                    , saved_mask2
                    ]);
    }
}

impl IRQHandler for PICs {

    fn handles(&self, irq: IRQ) -> bool {
        self.0.handles(irq) ||
        self.1.handles(irq)
    }

    fn end_interrupt(&self, irq: IRQ) {
        if self.1.handles(irq) {
            self.1.end_interrupt(irq);
        }
        self.0.end_interrupt(irq);
    }

}

/// Global PIC instance and mutex
static PICS: Mutex<PICs> = Mutex::new(PICs::new());

/// Initialize the system's Programmable Interrupt Controller
pub fn initialize() {
    PICS.lock()
        .initialize()
}

/// If an interrupt is being handled by the PICs, end that interrupt.
///
/// This is called by the interrupt handler at the end of all interrupts.
/// If the interrupt is not a PIC interrupt, it silently does nothing.
pub unsafe fn end_pic_interrupt(interrupt_id: u8) {
    let pics = PICS.lock();
    let irq: IRQ = transmute(interrupt_id);

    if pics.handles(irq) {
        pics.end_interrupt(irq)
    }
}
<commit_msg>Fix misaimed import in PICs<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Support for the 8259 Programmable Interrupt Controller.
//!
//! The 8259 PIC controls all of our IO IRQs. The PIC recieves IRQ requests
//! and feeds them to the CPU in order. An x86 system typically has two PICs,
//! PIC1 and PIC2, each of which provides 8 IRQs. Two PICs provide us with 15
//! unique IRQs, because one interrupt on the leader PIC is linked to interrupts
//! on the follower PIC.
//!
//! Mistakes were made, and Intel boneheadedly decided that it was a good idea
//! to map the vector offset of PIC1 to 8, so that it maps to interrupts
//! 8 ... 15 in the IDT. This conflicts with some of the interrupt numbers
//! used by CPU exceptions. Therefore, we must remap the PIC vectors so that
//! PIC1 starts at 32 and PIC2 at 40.

use ::io::Write;
use super::super::Port;
use spin::Mutex;
use core::mem::transmute;

/// Starting offset for PIC1
const OFFSET: u8 = 0x20;

/// Commands to send to the PIC
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
enum Command { Mode8086 = 0x01
             , Init     = 0x11
             , EndIRQ   = 0x20
             , ReadIRR  = 0x0a
             , ReadISR  = 0x0b
             }

/// List of IRQs on the x86.
///
/// See here for more info:
/// https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interrupt_Controller
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
pub enum IRQ { /// System timer IRQ
               Timer        = 0 + OFFSET
             , /// PS/2 keyboard controller
               PS2Keyboard  = 1 + OFFSET
             , /// PIC2 cascade IRQ
               Cascade      = 2 + OFFSET
             , /// COM2 serial port
               COM2         = 3 + OFFSET
             , /// COM1 serial port
               COM1         = 4 + OFFSET
             , /// Line printer 2
               LPT2         = 5 + OFFSET
             , /// Floppy disc controller
               Floppy       = 6 + OFFSET
             , /// Line printer 1
               LPT1         = 7 + OFFSET
             , /// CMOS clock
               RTCTimer     = 8 + OFFSET
             , /// PS/2 mouse controller
               PS2Mouse     = 12 + OFFSET
             , /// Floating-point Coprocessor
               FPU          = 13 + OFFSET
             , /// ATA channel 1
               PrimaryATA   = 14 + OFFSET
             , /// ATA channel 2
               SecondaryATA = 15 + OFFSET
             }

struct PIC {
    /// The base offset to which interrupts on this PIC are mapped
    offset: u8
  , /// The port on the CPU that sends commands to this PIC.
    command_port: Port
  , /// The port that sends and recieves data from the PIC
    data_port: Port
}

impl PIC {

    const fn leader() -> PIC {
        unsafe {
            PIC { offset: OFFSET
                , command_port: Port::new(0x20)
                , data_port: Port::new(0x21)
                }
        }
    }

    const fn follower() -> PIC {
        unsafe {
            PIC { offset: OFFSET + 8
                , command_port: Port::new(0xA0)
                , data_port: Port::new(0xA1)
                }
        }
    }

    #[inline]
    fn is_leader(&self) -> bool {
        self.offset == OFFSET
    }

    #[inline]
    fn send_command(&self, command: Command) {
        unsafe {
            self.command_port
                .out8(command as u8)
            }
    }

    #[inline]
    fn initialize(&self) {
        self.send_command(Command::Init)
    }

    #[inline]
    fn read_ISR(&self) -> u8 {
        self.send_command(Command::ReadISR);
        unsafe { self.data_port.in8() }
    }

    #[inline]
    fn read_IRR(&self) -> u8 {
        self.send_command(Command::ReadIRR);
        unsafe { self.data_port.in8() }
    }

}

trait IRQHandler {
    /// Returns whether or not this handler handles the given IRQ
    fn handles(&self, irq: IRQ) -> bool;
    /// End an interrupt request
    fn end_interrupt(&self, irq: IRQ);
}

impl IRQHandler for PIC {

    fn handles(&self, irq: IRQ) -> bool {
        self.offset <= (irq as u8) && (irq as u8) < self.offset + 8
    }

    fn end_interrupt(&self, irq: IRQ) {
        self.send_command(Command::EndIRQ)
    }
}

/// A pair of PICs in cascade mode.
///
/// This is the standard configuration on all modern x86 systems.
struct PICs (PIC, PIC);

impl PICs {
    const fn new() -> Self {
        PICs (PIC::leader(), PIC::follower())
    }

    /// Initialize the system's PICs.
    fn initialize(&mut self) {
        // Read the default interrupt masks from PIC1 and PIC2
        let (saved_mask1, saved_mask2)
            = unsafe { (self.0.data_port.in8(), self.1.data_port.in8()) };

        // Send both PICs the 'initialize' command.
        self.0.initialize();
        self.1.initialize();

        // Each PIC then expects us to send it the following:
        self.0.data_port
            .write(&[ self.0.offset     // 1. the PIC's new vector offset
                    , 0x04              // 2. number to configure PIC cascading
                    , Command::Mode8086 as u8 // 3. command for 8086 mode
                    , saved_mask1       // 4. finally, the mask we saved earlier
                    ]);

        self.1.data_port
            .write(&[ self.1.offset
                    , 0x02              // PIC2 gets 0x02 to set it as follower
                    , Command::Mode8086 as u8
                    , saved_mask2
                    ]);
    }
}

impl IRQHandler for PICs {

    fn handles(&self, irq: IRQ) -> bool {
        self.0.handles(irq) ||
        self.1.handles(irq)
    }

    fn end_interrupt(&self, irq: IRQ) {
        if self.1.handles(irq) {
            self.1.end_interrupt(irq);
        }
        self.0.end_interrupt(irq);
    }

}

/// Global PIC instance and mutex
static PICS: Mutex<PICs> = Mutex::new(PICs::new());

/// Initialize the system's Programmable Interrupt Controller
pub fn initialize() {
    PICS.lock()
        .initialize()
}

/// If an interrupt is being handled by the PICs, end that interrupt.
///
/// This is called by the interrupt handler at the end of all interrupts.
/// If the interrupt is not a PIC interrupt, it silently does nothing.
pub unsafe fn end_pic_interrupt(interrupt_id: u8) {
    let pics = PICS.lock();
    let irq: IRQ = transmute(interrupt_id);

    if pics.handles(irq) {
        pics.end_interrupt(irq)
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).

#![deny(warnings)]
// Enable all clippy lints except for many of the pedantic ones. It's a shame this needs to be copied and pasted across crates, but there doesn't appear to be a way to include inner attributes from a common source.
#![deny(
  clippy::all,
  clippy::default_trait_access,
  clippy::expl_impl_clone_on_copy,
  clippy::if_not_else,
  clippy::needless_continue,
  clippy::unseparated_literal_suffix,
  // TODO: Falsely triggers for async/await:
  //   see https://github.com/rust-lang/rust-clippy/issues/5360
  // clippy::used_underscore_binding
)]
// It is often more clear to show that nothing is being moved.
#![allow(clippy::match_ref_pats)]
// Subjective style.
#![allow(
  clippy::len_without_is_empty,
  clippy::redundant_field_names,
  clippy::too_many_arguments
)]
// Default isn't as big a deal as people seem to think it is.
#![allow(clippy::new_without_default, clippy::new_ret_no_self)]
// Arc<Mutex> can be more clear than needing to grok Orderings:
#![allow(clippy::mutex_atomic)]

use clap::{App, Arg};
use mock::StubCAS;
use std::io;
use std::io::Read;

fn main() -> Result<(), String> {
  env_logger::init();
  let mut stdin = io::stdin();

  let matches = &App::new("local_cas")
    .about("An in-memory implementation of a CAS, to test remote execution utilities.")
    .arg(
      Arg::with_name("port")
        .long("port")
        .short("p")
        .required(false)
        .takes_value(true)
        .help("Port that the CAS should listen to.")
        .default_value("0"),
    )
    .get_matches();

  let cas = StubCAS::builder()
    .port(
      matches
        .value_of("port")
        .unwrap()
        .parse::<u16>()
        .expect("port must be a non-negative number"),
    )
    .build();
  println!("Started CAS at address: {}", cas.address());
  println!("Press enter to exit.");
  let _ = stdin.read(&mut [0_u8]).unwrap();
  Ok(())
}
<commit_msg>local_cas supports an instance-name (#10225)<commit_after>// Copyright 2018 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).

#![deny(warnings)]
// Enable all clippy lints except for many of the pedantic ones. It's a shame this needs to be copied and pasted across crates, but there doesn't appear to be a way to include inner attributes from a common source.
#![deny(
  clippy::all,
  clippy::default_trait_access,
  clippy::expl_impl_clone_on_copy,
  clippy::if_not_else,
  clippy::needless_continue,
  clippy::unseparated_literal_suffix,
  // TODO: Falsely triggers for async/await:
  //   see https://github.com/rust-lang/rust-clippy/issues/5360
  // clippy::used_underscore_binding
)]
// It is often more clear to show that nothing is being moved.
#![allow(clippy::match_ref_pats)]
// Subjective style.
#![allow(
  clippy::len_without_is_empty,
  clippy::redundant_field_names,
  clippy::too_many_arguments
)]
// Default isn't as big a deal as people seem to think it is.
#![allow(clippy::new_without_default, clippy::new_ret_no_self)]
// Arc<Mutex> can be more clear than needing to grok Orderings:
#![allow(clippy::mutex_atomic)]

use clap::{App, Arg};
use mock::StubCAS;
use std::io;
use std::io::Read;

fn main() -> Result<(), String> {
  env_logger::init();
  let mut stdin = io::stdin();

  let matches = &App::new("local_cas")
    .about("An in-memory implementation of a CAS, to test remote execution utilities.")
    .arg(
      Arg::with_name("port")
        .long("port")
        .short("p")
        .required(false)
        .takes_value(true)
        .help("Port that the CAS should listen to.")
        .default_value("0"),
    )
    .arg(
      Arg::with_name("instance-name")
        .long("instance-name")
        .short("i")
        .required(false)
        .takes_value(true)
        .default_value(""),
    )
    .get_matches();

  let cas = StubCAS::builder()
    .port(
      matches
        .value_of("port")
        .unwrap()
        .parse::<u16>()
        .expect("port must be a non-negative number"),
    )
    .instance_name(matches.value_of("instance-name").unwrap().to_owned())
    .build();
  println!("Started CAS at address: {}", cas.address());
  println!("Press enter to exit.");
  let _ = stdin.read(&mut [0_u8]).unwrap();
  Ok(())
}
<|endoftext|>