<commit_before>//! A screen as reported by the compositor.
//!
//! Note that there isn't a one-to-one mapping between number of outputs,
//! screens, and the outputs as reported by Way Cooler.

use std::default::Default;

use rlua::{self, AnyUserData, Lua, MetaMethod, Table, ToLua, UserData,
           UserDataMethods, Value};
use wlroots::{Area, Origin, Size};

use common::{class::{self, Class, ClassBuilder},
             signal::emit_object_signal,
             object::{self, Object},
             property::Property};
use wayland_obj::Output;

pub const SCREENS_HANDLE: &'static str = "__screens";

pub type Screen<'lua> = Object<'lua, ScreenState>;

#[derive(Clone)]
pub struct ScreenState {
    // Is this screen still valid and may be used
    pub valid: bool,
    // Screen geometry
    pub geometry: Area,
    // Screen workarea
    pub workarea: Area,
    // The screen outputs information
    pub outputs: Vec<Output>,
    // Some XID identifying this screen
    pub xid: u32
}

unsafe impl Send for ScreenState {}

impl PartialEq for ScreenState {
    fn eq(&self, other: &ScreenState) -> bool {
        self.valid == other.valid &&
            self.geometry == other.geometry &&
            self.workarea == other.workarea &&
            self.xid == other.xid &&
            self.outputs == other.outputs
    }
}

impl Eq for ScreenState {}

impl Default for ScreenState {
    fn default() -> Self {
        ScreenState { valid: true,
                      geometry: Area::default(),
                      workarea: Area::default(),
                      outputs: vec![],
                      xid: 0 }
    }
}

impl UserData for ScreenState {
    fn add_methods(methods: &mut UserDataMethods<Self>) {
        object::default_add_methods(methods);
        methods.add_meta_function(MetaMethod::Index, index);
    }
}

impl<'lua> Screen<'lua> {
    pub fn new(lua: &Lua) -> rlua::Result<Screen> {
        let class = class::class_setup(lua, "screen")?;
        Ok(Screen::allocate(lua, class)?.build())
    }

    pub fn init_screens(&mut self,
                    output: Output,
                    outputs: Vec<Output>)
                    -> rlua::Result<()> {
        let mut state = self.state_mut()?;
        let (width, height) = output.resolution();
        let resolution = Size { width, height };
        state.outputs = outputs;
        state.geometry = state.geometry.with_size(resolution);
        state.workarea = state.workarea.with_size(resolution);
        Ok(())
    }

    pub fn set_geometry(&mut self, lua: &Lua, geometry: Area)
                        -> rlua::Result<()> {
        let obj_clone = self.clone();
        let mut state = self.state_mut()?;
        if state.geometry != geometry {
            let old_area = lua.create_table()?;
            old_area.set("x", state.geometry.origin.x)?;
            old_area.set("y", state.geometry.origin.y)?;
            old_area.set("width", state.geometry.size.width)?;
            old_area.set("height", state.geometry.size.height)?;
            state.geometry = geometry;
            emit_object_signal(lua, obj_clone.into(), "property::geometry".into(), old_area)?;
        }
        Ok(())
    }

    pub fn set_workarea(&mut self, lua: &Lua, geometry: Area)
                    -> rlua::Result<()> {
        let obj_clone = self.clone();
        let mut state = self.state_mut()?;
        if state.workarea != geometry {
            let old_area = lua.create_table()?;
            old_area.set("x", state.geometry.origin.x)?;
            old_area.set("y", state.geometry.origin.y)?;
            old_area.set("width", state.geometry.size.width)?;
            old_area.set("height", state.geometry.size.height)?;
            state.geometry = geometry;
            emit_object_signal(lua, obj_clone.into(), "property::workarea".into(), old_area)?;
        }
        state.workarea = geometry;
        Ok(())
    }

    pub fn get_geometry(&self, lua: &'lua Lua) -> rlua::Result<Table<'lua>> {
        let state = self.state()?;
        let Origin { x, y } = state.geometry.origin;
        let Size { width, height } = state.geometry.size;
        let table = lua.create_table()?;
        table.set("x", x)?;
        table.set("y", y)?;
        table.set("width", width)?;
        table.set("height", height)?;
        Ok(table)
    }

    pub fn get_workarea(&self, lua: &'lua Lua) -> rlua::Result<Table<'lua>> {
        let state = self.state()?;
        let Origin { x, y } = state.workarea.origin;
        let Size { width, height } = state.workarea.size;
        let table = lua.create_table()?;
        table.set("x", x)?;
        table.set("y", y)?;
        table.set("width", width)?;
        table.set("height", height)?;
        Ok(table)
    }
}

/// Adds a screen to the list of screens.
pub fn add_screen(lua: &Lua, screen: Screen) -> rlua::Result<()> {
    let mut screens = lua.named_registry_value::<Vec<AnyUserData>>(SCREENS_HANDLE)?;
    screens.push(screen.into());
    lua.set_named_registry_value(SCREENS_HANDLE, screens.to_lua(lua)?)?;
    Ok(())
}

/// Find a screen based on the output.
pub fn get_screen(lua: &Lua, output: Output) -> rlua::Result<Screen> {
    lua.named_registry_value::<Vec<AnyUserData>>(SCREENS_HANDLE)?
        .into_iter()
        .map(|obj| Screen::cast(obj.into()).unwrap())
        // TODO Can there be multiple screens the output is associated with?
        // Will need to handle that case
        .find(|screen| {
            let state = screen.state().expect("Could not get screen state");
            state.outputs.iter().any(|cur_output| *cur_output == output)
        })
        .ok_or(rlua::Error::RuntimeError(format!("No screen with output {:?}", output)))
}

pub fn init<'lua>(lua: &'lua Lua) -> rlua::Result<Class<ScreenState>> {
    let builder = Class::builder(lua, "screen", None)?;
    let res = property_setup(lua, method_setup(lua, builder)?)?.save_class("screen")?
                                                               .build()?;
    let screens: &mut Vec<Screen> = &mut vec![];
    // TODO Get the list of outputs from Way Cooler
    //for output in server.outputs.iter() {
    //    let mut screen = Screen::new(lua)?;
    //    screen.init_screens(output.clone(), vec![output.clone()])?;
    //    // TODO Move to Screen impl like the others
    //    screens.push(screen);
    //}

    // If no screens exist, fake one.
    if screens.is_empty() {
        let mut screen = Screen::new(lua)?;
        {
            let mut obj = screen.state_mut()?;
            obj.geometry = Size::new(1024, 768).into();
            obj.workarea = obj.geometry;
        }
        screens.push(screen);
    }

    lua.set_named_registry_value(SCREENS_HANDLE, screens.clone().to_lua(lua)?)?;
    Ok(res)
}

fn method_setup<'lua>(lua: &'lua Lua,
                      builder: ClassBuilder<'lua, ScreenState>)
                      -> rlua::Result<ClassBuilder<'lua, ScreenState>> {
    // TODO Do properly
    use super::dummy;
    builder.method("connect_signal".into(), lua.create_function(dummy)?)?
           .method("count".into(), lua.create_function(count)?)?
           .method("__call".into(), lua.create_function(iterate_over_screens)?)?
           .method("__index".into(), lua.create_function(index)?)
}

fn property_setup<'lua>(lua: &'lua Lua,
                        builder: ClassBuilder<'lua, ScreenState>)
                        -> rlua::Result<ClassBuilder<'lua, ScreenState>> {
    builder.property(Property::new("geometry".into(),
                                   None,
                                   Some(lua.create_function(get_geometry)?),
                                   None))?
           .property(Property::new("workarea".into(),
                                   None,
                                   Some(lua.create_function(get_workarea)?),
                                   None))
}

fn get_geometry<'lua>(lua: &'lua Lua, screen: Screen<'lua>) -> rlua::Result<Table<'lua>> {
    screen.get_geometry(lua)
}

fn get_workarea<'lua>(lua: &'lua Lua, screen: Screen<'lua>) -> rlua::Result<Table<'lua>> {
    screen.get_workarea(lua)
}

fn count<'lua>(lua: &'lua Lua, _: ()) -> rlua::Result<Value<'lua>> {
    let screens = lua.named_registry_value::<Vec<Screen>>(SCREENS_HANDLE)?;
    Ok(Value::Integer(screens.len() as _))
}

/// Ok this requires some explanation...
/// Lua gives us the previous value in the loop, with the first one being nil
/// since there was nothing there before.
///
/// To ensure we loop over everything, we take the index of that value in our
/// list, increment it by 1 (starting at 0 if it's the start) and then once it
/// falls outside the bounds it will stop by returning nil.
fn iterate_over_screens<'lua>(lua: &'lua Lua,
                              (_, prev): (Value<'lua>, Value<'lua>))
                              -> rlua::Result<Value<'lua>> {
    let mut screens = lua.named_registry_value::<Vec<Screen>>(SCREENS_HANDLE)?;

    let index = match prev {
        Value::Nil => 0,
        Value::UserData(ref object) => {
            if let Ok(screen) = Screen::cast(object.clone().into()) {
                screens.iter()
                       .position(|t| *t.state().unwrap() == *screen.state().unwrap())
                       .unwrap_or(screens.len()) + 1
            } else {
                panic!("Unexpected non-screen table in loop");
            }
        }
        _ => panic!("Unexpected non-screen or nil value in screens loop")
    };
    if index < screens.len() {
        screens.remove(index).to_lua(lua)
    } else {
        Ok(Value::Nil)
    }
}

fn index<'lua>(lua: &'lua Lua,
               (obj, index): (Screen<'lua>, Value<'lua>))
               -> rlua::Result<Value<'lua>> {
    let screens: Vec<Screen> = lua.named_registry_value(SCREENS_HANDLE)?;
    match index {
        Value::String(ref string) => {
            let string = string.to_str()?;
            if string == "primary" {
                // TODO Emit primary changed signal
                if screens.len() > 0 {
                    return screens[0].clone().to_lua(lua)
                }
            }
            for screen in screens.iter() {
                let mut screen_state = screen.state()?;
                for output in &screen_state.outputs {
                    if output.name() == string {
                        return screen.clone().to_lua(lua)
                    }
                }
            }
        }
        // TODO Might need to do Number instead
        Value::Integer(screen_index) => {
            if screen_index < 1 || screen_index as usize > screens.len() {
                return Err(rlua::Error::RuntimeError(format!("invalid screen \
                                                              number: {} (of {} \
                                                              existing)",
                                                             screen_index,
                                                             screens.len())))
            }
            return screens[(screen_index - 1) as usize].clone().to_lua(lua)
        }
        Value::UserData(ref obj) => {
            // If this is a screen, just return it
            if let Ok(screen) = Screen::cast(obj.clone().into()) {
                return screen.to_lua(lua)
            }
        }
        // TODO This checke user data like in luaA_toudata in awesome
        _ => {}
    }
    // TODO checkudata
    let meta = obj.get_metatable()?.expect("screen had no metatable");
    match meta.get(index.clone()) {
        Err(_) | Ok(Value::Nil) => object::default_index(lua, (obj, index)),
        Ok(value) => Ok(value)
    }
}
<commit_msg>Only hold the refmut as long as necessary<commit_after>//! A screen as reported by the compositor.
//!
//! Note that there isn't a one-to-one mapping between number of outputs,
//! screens, and the outputs as reported by Way Cooler.

use std::default::Default;

use rlua::{self, AnyUserData, Lua, MetaMethod, Table, ToLua, UserData,
           UserDataMethods, Value};
use wlroots::{Area, Origin, Size};

use common::{class::{self, Class, ClassBuilder},
             signal::emit_object_signal,
             object::{self, Object},
             property::Property};
use wayland_obj::Output;

pub const SCREENS_HANDLE: &'static str = "__screens";

pub type Screen<'lua> = Object<'lua, ScreenState>;

#[derive(Clone)]
pub struct ScreenState {
    // Is this screen still valid and may be used
    pub valid: bool,
    // Screen geometry
    pub geometry: Area,
    // Screen workarea
    pub workarea: Area,
    // The screen outputs information
    pub outputs: Vec<Output>,
    // Some XID identifying this screen
    pub xid: u32
}

unsafe impl Send for ScreenState {}

impl PartialEq for ScreenState {
    fn eq(&self, other: &ScreenState) -> bool {
        self.valid == other.valid &&
            self.geometry == other.geometry &&
            self.workarea == other.workarea &&
            self.xid == other.xid &&
            self.outputs == other.outputs
    }
}

impl Eq for ScreenState {}

impl Default for ScreenState {
    fn default() -> Self {
        ScreenState { valid: true,
                      geometry: Area::default(),
                      workarea: Area::default(),
                      outputs: vec![],
                      xid: 0 }
    }
}

impl UserData for ScreenState {
    fn add_methods(methods: &mut UserDataMethods<Self>) {
        object::default_add_methods(methods);
        methods.add_meta_function(MetaMethod::Index, index);
    }
}

impl<'lua> Screen<'lua> {
    pub fn new(lua: &Lua) -> rlua::Result<Screen> {
        let class = class::class_setup(lua, "screen")?;
        Ok(Screen::allocate(lua, class)?.build())
    }

    pub fn init_screens(&mut self,
                    output: Output,
                    outputs: Vec<Output>)
                    -> rlua::Result<()> {
        let mut state = self.state_mut()?;
        let (width, height) = output.resolution();
        let resolution = Size { width, height };
        state.outputs = outputs;
        state.geometry = state.geometry.with_size(resolution);
        state.workarea = state.workarea.with_size(resolution);
        Ok(())
    }

    pub fn set_geometry(&mut self, lua: &Lua, geometry: Area)
                        -> rlua::Result<()> {
        let obj_clone = self.clone();
        if self.state()?.geometry != geometry {
            let geometry = self.state()?.geometry;
            let old_area = lua.create_table()?;
            old_area.set("x", geometry.origin.x)?;
            old_area.set("y", geometry.origin.y)?;
            old_area.set("width", geometry.size.width)?;
            old_area.set("height", geometry.size.height)?;
            self.state_mut()?.geometry = geometry;
            emit_object_signal(lua, self.clone().into(), "property::geometry".into(), old_area)?;
        }
        Ok(())
    }

    pub fn set_workarea(&mut self, lua: &Lua, geometry: Area)
                    -> rlua::Result<()> {
        let obj_clone = self.clone();
        if self.state()?.workarea != geometry {
            let geometry = self.state()?.geometry;
            let old_area = lua.create_table()?;
            old_area.set("x", geometry.origin.x)?;
            old_area.set("y", geometry.origin.y)?;
            old_area.set("width", geometry.size.width)?;
            old_area.set("height", geometry.size.height)?;
            self.state_mut()?.workarea = geometry;
            emit_object_signal(lua, self.clone().into(), "property::workarea".into(), old_area)?;
        }
        Ok(())
    }

    pub fn get_geometry(&self, lua: &'lua Lua) -> rlua::Result<Table<'lua>> {
        let state = self.state()?;
        let Origin { x, y } = state.geometry.origin;
        let Size { width, height } = state.geometry.size;
        let table = lua.create_table()?;
        table.set("x", x)?;
        table.set("y", y)?;
        table.set("width", width)?;
        table.set("height", height)?;
        Ok(table)
    }

    pub fn get_workarea(&self, lua: &'lua Lua) -> rlua::Result<Table<'lua>> {
        let state = self.state()?;
        let Origin { x, y } = state.workarea.origin;
        let Size { width, height } = state.workarea.size;
        let table = lua.create_table()?;
        table.set("x", x)?;
        table.set("y", y)?;
        table.set("width", width)?;
        table.set("height", height)?;
        Ok(table)
    }
}

/// Adds a screen to the list of screens.
pub fn add_screen(lua: &Lua, screen: Screen) -> rlua::Result<()> {
    let mut screens = lua.named_registry_value::<Vec<AnyUserData>>(SCREENS_HANDLE)?;
    screens.push(screen.into());
    lua.set_named_registry_value(SCREENS_HANDLE, screens.to_lua(lua)?)?;
    Ok(())
}

/// Find a screen based on the output.
pub fn get_screen(lua: &Lua, output: Output) -> rlua::Result<Screen> {
    lua.named_registry_value::<Vec<AnyUserData>>(SCREENS_HANDLE)?
        .into_iter()
        .map(|obj| Screen::cast(obj.into()).unwrap())
        // TODO Can there be multiple screens the output is associated with?
        // Will need to handle that case
        .find(|screen| {
            let state = screen.state().expect("Could not get screen state");
            state.outputs.iter().any(|cur_output| *cur_output == output)
        })
        .ok_or(rlua::Error::RuntimeError(format!("No screen with output {:?}", output)))
}

pub fn init<'lua>(lua: &'lua Lua) -> rlua::Result<Class<ScreenState>> {
    let builder = Class::builder(lua, "screen", None)?;
    let res = property_setup(lua, method_setup(lua, builder)?)?.save_class("screen")?
                                                               .build()?;
    let screens: &mut Vec<Screen> = &mut vec![];
    // TODO Get the list of outputs from Way Cooler
    //for output in server.outputs.iter() {
    //    let mut screen = Screen::new(lua)?;
    //    screen.init_screens(output.clone(), vec![output.clone()])?;
    //    // TODO Move to Screen impl like the others
    //    screens.push(screen);
    //}

    // If no screens exist, fake one.
    if screens.is_empty() {
        let mut screen = Screen::new(lua)?;
        {
            let mut obj = screen.state_mut()?;
            obj.geometry = Size::new(1024, 768).into();
            obj.workarea = obj.geometry;
        }
        screens.push(screen);
    }

    lua.set_named_registry_value(SCREENS_HANDLE, screens.clone().to_lua(lua)?)?;
    Ok(res)
}

fn method_setup<'lua>(lua: &'lua Lua,
                      builder: ClassBuilder<'lua, ScreenState>)
                      -> rlua::Result<ClassBuilder<'lua, ScreenState>> {
    // TODO Do properly
    use super::dummy;
    builder.method("connect_signal".into(), lua.create_function(dummy)?)?
           .method("count".into(), lua.create_function(count)?)?
           .method("__call".into(), lua.create_function(iterate_over_screens)?)?
           .method("__index".into(), lua.create_function(index)?)
}

fn property_setup<'lua>(lua: &'lua Lua,
                        builder: ClassBuilder<'lua, ScreenState>)
                        -> rlua::Result<ClassBuilder<'lua, ScreenState>> {
    builder.property(Property::new("geometry".into(),
                                   None,
                                   Some(lua.create_function(get_geometry)?),
                                   None))?
           .property(Property::new("workarea".into(),
                                   None,
                                   Some(lua.create_function(get_workarea)?),
                                   None))
}

fn get_geometry<'lua>(lua: &'lua Lua, screen: Screen<'lua>) -> rlua::Result<Table<'lua>> {
    screen.get_geometry(lua)
}

fn get_workarea<'lua>(lua: &'lua Lua, screen: Screen<'lua>) -> rlua::Result<Table<'lua>> {
    screen.get_workarea(lua)
}

fn count<'lua>(lua: &'lua Lua, _: ()) -> rlua::Result<Value<'lua>> {
    let screens = lua.named_registry_value::<Vec<Screen>>(SCREENS_HANDLE)?;
    Ok(Value::Integer(screens.len() as _))
}

/// Ok this requires some explanation...
/// Lua gives us the previous value in the loop, with the first one being nil
/// since there was nothing there before.
///
/// To ensure we loop over everything, we take the index of that value in our
/// list, increment it by 1 (starting at 0 if it's the start) and then once it
/// falls outside the bounds it will stop by returning nil.
fn iterate_over_screens<'lua>(lua: &'lua Lua,
                              (_, prev): (Value<'lua>, Value<'lua>))
                              -> rlua::Result<Value<'lua>> {
    let mut screens = lua.named_registry_value::<Vec<Screen>>(SCREENS_HANDLE)?;

    let index = match prev {
        Value::Nil => 0,
        Value::UserData(ref object) => {
            if let Ok(screen) = Screen::cast(object.clone().into()) {
                screens.iter()
                       .position(|t| *t.state().unwrap() == *screen.state().unwrap())
                       .unwrap_or(screens.len()) + 1
            } else {
                panic!("Unexpected non-screen table in loop");
            }
        }
        _ => panic!("Unexpected non-screen or nil value in screens loop")
    };
    if index < screens.len() {
        screens.remove(index).to_lua(lua)
    } else {
        Ok(Value::Nil)
    }
}

fn index<'lua>(lua: &'lua Lua,
               (obj, index): (Screen<'lua>, Value<'lua>))
               -> rlua::Result<Value<'lua>> {
    let screens: Vec<Screen> = lua.named_registry_value(SCREENS_HANDLE)?;
    match index {
        Value::String(ref string) => {
            let string = string.to_str()?;
            if string == "primary" {
                // TODO Emit primary changed signal
                if screens.len() > 0 {
                    return screens[0].clone().to_lua(lua)
                }
            }
            for screen in screens.iter() {
                let mut screen_state = screen.state()?;
                for output in &screen_state.outputs {
                    if output.name() == string {
                        return screen.clone().to_lua(lua)
                    }
                }
            }
        }
        // TODO Might need to do Number instead
        Value::Integer(screen_index) => {
            if screen_index < 1 || screen_index as usize > screens.len() {
                return Err(rlua::Error::RuntimeError(format!("invalid screen \
                                                              number: {} (of {} \
                                                              existing)",
                                                             screen_index,
                                                             screens.len())))
            }
            return screens[(screen_index - 1) as usize].clone().to_lua(lua)
        }
        Value::UserData(ref obj) => {
            // If this is a screen, just return it
            if let Ok(screen) = Screen::cast(obj.clone().into()) {
                return screen.to_lua(lua)
            }
        }
        // TODO This checke user data like in luaA_toudata in awesome
        _ => {}
    }
    // TODO checkudata
    let meta = obj.get_metatable()?.expect("screen had no metatable");
    match meta.get(index.clone()) {
        Err(_) | Ok(Value::Nil) => object::default_index(lua, (obj, index)),
        Ok(value) => Ok(value)
    }
}
<|endoftext|>


<commit_before>use memory::MemSegment;

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum AddrByte {
    High,
    Low,
}

pub struct PPUCtrl {
    bits: u8,
}
impl PPUCtrl {
    pub fn empty() -> PPUCtrl {
        PPUCtrl { bits: 0 }
    }

    pub fn new(bits: u8) -> PPUCtrl {
        PPUCtrl { bits: bits }
    }

    pub fn nametable_num(&self) -> u16 {
        (self.bits & 0b0000_0011) as u16
    }

    pub fn vram_addr_step(&self) -> u16 {
        if self.bits & 0b0000_0100 != 0 {
            32
        } else {
            1
        }
    }

    pub fn background_table(&self) -> u16 {
        if self.bits & 0b0001_0000 != 0 {
            0x1000
        } else {
            0x0000
        }
    }

    pub fn sprite_table(&self) -> u16 {
        if self.bits & 0b0010_0000 != 0 {
            0x1000
        } else {
            0x0000
        }
    }

    pub fn generate_vblank_nmi(&self) -> bool {
        self.bits & 0b1000_0000 != 0
    }
}

bitflags! {
    flags PPUMask : u8 {
        const GREY =    0b0000_0001, //Greyscale
        const S_BCK_L = 0b0000_0010, //Show background in the leftmost 8 pixels
        const S_SPR_L = 0b0000_0100, //Show sprites in the leftmost 8 pixels
        const S_BCK =   0b0000_1000, //Show background
        const S_SPR =   0b0001_0000, //Show sprites
        const EM_R =    0b0010_0000, //Emphasize Red
        const EM_G =    0b0100_0000, //Emphasize Green
        const EM_B =    0b1000_0000, //Emphasize Blue
    }
}

bitflags! {
    flags PPUStat : u8 {
        const VBLANK =          0b1000_0000, //Currently in the vertical blank interval
        const SPRITE_0 =        0b0100_0000, //Sprite 0 hit
        const SPRITE_OVERFLOW = 0b0010_0000, //Greater than 8 sprites on current scanline
    }
}

pub struct PPUReg {
    pub ppuctrl: PPUCtrl,
    pub ppumask: PPUMask,
    pub ppustat: PPUStat,
    pub oamaddr: u8,
    ppuscroll: u16,
    pub ppuaddr: u16,

    ///A fake dynamic latch representing the capacitance of the wires in the
    ///PPU that we have to emulate.
    dyn_latch: u8,

    ///The address registers are two bytes but we can only write one at a time.
    address_latch: AddrByte,
}

impl PPUReg {
    pub fn scroll_x(&self) -> u16 {
        (self.ppuscroll & 0xFF00) >> 8
    }

    pub fn scroll_x_fine(&self) -> u16 {
        self.scroll_x() & 0x07
    }

    pub fn scroll_x_coarse(&self) -> u16 {
        self.scroll_x() >> 3
    }

    pub fn scroll_y(&self) -> u16 {
        (self.ppuscroll & 0x00FF) >> 0
    }

    pub fn scroll_y_coarse(&self) -> u16 {
        self.scroll_y() >> 3
    }

    pub fn incr_ppuaddr(&mut self) {
        let incr_size = self.ppuctrl.vram_addr_step();
        self.ppuaddr = self.ppuaddr.wrapping_add(incr_size);
    }

    pub fn incr_oamaddr(&mut self) {
        self.oamaddr = self.oamaddr.wrapping_add(1);
    }
}

fn write_addr_byte(latch: &mut AddrByte, target: &mut u16, val: u8) {
    match *latch {
        AddrByte::High => {
            *target = (*target & 0x00FF) | ((val as u16) << 8);
            *latch = AddrByte::Low;
        }
        AddrByte::Low => {
            *target = (*target & 0xFF00) | ((val as u16) << 0);
            *latch = AddrByte::High;
        }
    }
}

impl Default for PPUReg {
    fn default() -> PPUReg {
        PPUReg {
            ppuctrl: PPUCtrl::empty(),
            ppumask: PPUMask::empty(),
            ppustat: PPUStat::empty(),
            oamaddr: 0,
            ppuscroll: 0,
            ppuaddr: 0,
            dyn_latch: 0,
            address_latch: AddrByte::High,
        }
    }
}

impl MemSegment for PPUReg {
    fn read(&mut self, idx: u16) -> u8 {
        match idx % 8 {
            0x0000 => self.dyn_latch,
            0x0001 => self.dyn_latch,
            0x0002 => {
                self.address_latch = AddrByte::High;
                let res = self.ppustat.bits | (self.dyn_latch & 0b0001_1111);
                self.ppustat.remove(VBLANK);
                res
            }
            0x0003 => self.dyn_latch,
            0x0005 => self.dyn_latch,
            0x0006 => self.dyn_latch,
            _ => invalid_address!(idx),
        }
    }

    fn write(&mut self, idx: u16, val: u8) {
        self.dyn_latch = val;
        match idx % 8 {
            0x0000 => self.ppuctrl = PPUCtrl::new(val),
            0x0001 => self.ppumask = PPUMask::from_bits_truncate(val),
            0x0002 => (),
            0x0003 => self.oamaddr = val,
            0x0005 => write_addr_byte(&mut self.address_latch, &mut self.ppuscroll, val),
            0x0006 => write_addr_byte(&mut self.address_latch, &mut self.ppuaddr, val),
            _ => invalid_address!(idx),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use memory::MemSegment;
    use ppu::PPU;
    use ppu::tests::*;

    fn assert_register_single_writable(idx: u16, getter: &Fn(&PPU) -> u8) {
        let mut ppu = create_test_ppu();
        ppu.write(idx, 12);
        assert_eq!(getter(&ppu), 12);
        ppu.write(idx, 125);
        assert_eq!(getter(&ppu), 125);
    }

    fn assert_register_double_writable(idx: u16, getter: &Fn(&PPU) -> u16) {
        let mut ppu = create_test_ppu();
        ppu.write(idx, 0xDE);
        assert_eq!(getter(&ppu), 0xDE00);
        assert_eq!(AddrByte::Low, ppu.reg.address_latch);
        ppu.write(idx, 0xAD);
        assert_eq!(getter(&ppu), 0xDEAD);
        assert_eq!(AddrByte::High, ppu.reg.address_latch);
    }

    fn assert_register_ignores_writes(idx: u16, getter: &Fn(&PPU) -> u8) {
        let mut ppu = create_test_ppu();
        ppu.write(idx, 12);
        assert_eq!(getter(&ppu), 0);
        ppu.write(idx, 125);
        assert_eq!(getter(&ppu), 0);
    }

    fn assert_writing_register_fills_latch(idx: u16) {
        let mut ppu = create_test_ppu();
        ppu.write(idx, 12);
        assert_eq!(ppu.reg.dyn_latch, 12);
        ppu.write(idx, 125);
        assert_eq!(ppu.reg.dyn_latch, 125);
    }

    fn assert_register_is_readable(idx: u16, setter: &Fn(&mut PPU, u8) -> ()) {
        let mut ppu = create_test_ppu();
        setter(&mut ppu, 12);
        assert_eq!(ppu.read(idx), 12);
        setter(&mut ppu, 125);
        assert_eq!(ppu.read(idx), 125);
    }

    fn assert_register_not_readable(idx: u16) {
        let mut ppu = create_test_ppu();
        ppu.reg.dyn_latch = 12;
        assert_eq!(ppu.read(idx), 12);
        ppu.reg.dyn_latch = 125;
        assert_eq!(ppu.read(idx), 125);
    }

    #[test]
    fn ppuctrl_is_write_only_register() {
        assert_register_single_writable(0x2000, &|ref ppu| ppu.reg.ppuctrl.bits);
        assert_writing_register_fills_latch(0x2000);
        assert_register_not_readable(0x2000);
    }

    #[test]
    fn ppu_mirrors_address() {
        assert_register_single_writable(0x2008, &|ref ppu| ppu.reg.ppuctrl.bits);
        assert_register_single_writable(0x2010, &|ref ppu| ppu.reg.ppuctrl.bits);
    }

    #[test]
    fn ppumask_is_write_only_register() {
        assert_register_single_writable(0x2001, &|ref ppu| ppu.reg.ppumask.bits());
        assert_writing_register_fills_latch(0x2001);
        assert_register_not_readable(0x2001);
    }

    #[test]
    fn ppustat_is_read_only_register() {
        assert_register_ignores_writes(0x2002, &|ref ppu| ppu.reg.ppustat.bits);
        assert_writing_register_fills_latch(0x2002);
        assert_register_is_readable(0x2002,
                                    &|ref mut ppu, val| {
                                        ppu.reg.ppustat = PPUStat::from_bits_truncate(val);
                                        ppu.reg.dyn_latch = val;
                                    });
    }

    #[test]
    fn reading_ppustat_returns_part_of_dynlatch() {
        let mut ppu = create_test_ppu();
        ppu.reg.dyn_latch = 0b0001_0101;
        ppu.reg.ppustat = PPUStat::from_bits_truncate(0b1010_0101);
        assert_eq!(ppu.read(0x2002), 0b1011_0101);
    }

    #[test]
    fn reading_ppustat_clears_addr_latch() {
        let mut ppu = create_test_ppu();
        ppu.reg.address_latch = AddrByte::Low;
        ppu.read(0x2002);
        assert_eq!(ppu.reg.address_latch, AddrByte::High);
    }

    #[test]
    fn oamaddr_is_write_only_register() {
        assert_register_single_writable(0x2003, &|ref ppu| ppu.reg.oamaddr);
        assert_writing_register_fills_latch(0x2003);
        assert_register_not_readable(0x2003);
    }

    #[test]
    fn ppuscroll_is_2x_write_only_register() {
        assert_register_double_writable(0x2005, &|ref ppu| ppu.reg.ppuscroll);
        assert_writing_register_fills_latch(0x2005);
        assert_register_not_readable(0x2005);
    }

    #[test]
    fn ppuaddr_is_2x_write_only_register() {
        assert_register_double_writable(0x2006, &|ref ppu| ppu.reg.ppuaddr);
        assert_writing_register_fills_latch(0x2006);
        assert_register_not_readable(0x2006);
    }
}
<commit_msg>Hacky and broken fix to SMB lockup.<commit_after>use memory::MemSegment;

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum AddrByte {
    High,
    Low,
}

pub struct PPUCtrl {
    bits: u8,
}
impl PPUCtrl {
    pub fn empty() -> PPUCtrl {
        PPUCtrl { bits: 0 }
    }

    pub fn new(bits: u8) -> PPUCtrl {
        PPUCtrl { bits: bits }
    }

    pub fn nametable_num(&self) -> u16 {
        (self.bits & 0b0000_0011) as u16
    }

    pub fn vram_addr_step(&self) -> u16 {
        if self.bits & 0b0000_0100 != 0 {
            32
        } else {
            1
        }
    }

    pub fn background_table(&self) -> u16 {
        if self.bits & 0b0001_0000 != 0 {
            0x1000
        } else {
            0x0000
        }
    }

    pub fn sprite_table(&self) -> u16 {
        if self.bits & 0b0010_0000 != 0 {
            0x1000
        } else {
            0x0000
        }
    }

    pub fn generate_vblank_nmi(&self) -> bool {
        self.bits & 0b1000_0000 != 0
    }
}

bitflags! {
    flags PPUMask : u8 {
        const GREY =    0b0000_0001, //Greyscale
        const S_BCK_L = 0b0000_0010, //Show background in the leftmost 8 pixels
        const S_SPR_L = 0b0000_0100, //Show sprites in the leftmost 8 pixels
        const S_BCK =   0b0000_1000, //Show background
        const S_SPR =   0b0001_0000, //Show sprites
        const EM_R =    0b0010_0000, //Emphasize Red
        const EM_G =    0b0100_0000, //Emphasize Green
        const EM_B =    0b1000_0000, //Emphasize Blue
    }
}

bitflags! {
    flags PPUStat : u8 {
        const VBLANK =          0b1000_0000, //Currently in the vertical blank interval
        const SPRITE_0 =        0b0100_0000, //Sprite 0 hit
        const SPRITE_OVERFLOW = 0b0010_0000, //Greater than 8 sprites on current scanline
    }
}

pub struct PPUReg {
    pub ppuctrl: PPUCtrl,
    pub ppumask: PPUMask,
    pub ppustat: PPUStat,
    pub oamaddr: u8,
    ppuscroll: u16,
    pub ppuaddr: u16,

    ///A fake dynamic latch representing the capacitance of the wires in the
    ///PPU that we have to emulate.
    dyn_latch: u8,

    ///The address registers are two bytes but we can only write one at a time.
    address_latch: AddrByte,
}

impl PPUReg {
    pub fn scroll_x(&self) -> u16 {
        (self.ppuscroll & 0xFF00) >> 8
    }

    pub fn scroll_x_fine(&self) -> u16 {
        self.scroll_x() & 0x07
    }

    pub fn scroll_x_coarse(&self) -> u16 {
        self.scroll_x() >> 3
    }

    pub fn scroll_y(&self) -> u16 {
        (self.ppuscroll & 0x00FF) >> 0
    }

    pub fn scroll_y_coarse(&self) -> u16 {
        self.scroll_y() >> 3
    }

    pub fn incr_ppuaddr(&mut self) {
        let incr_size = self.ppuctrl.vram_addr_step();
        self.ppuaddr = self.ppuaddr.wrapping_add(incr_size);
    }

    pub fn incr_oamaddr(&mut self) {
        self.oamaddr = self.oamaddr.wrapping_add(1);
    }
}

fn write_addr_byte(latch: &mut AddrByte, target: &mut u16, val: u8) {
    match *latch {
        AddrByte::High => {
            *target = (*target & 0x00FF) | ((val as u16) << 8);
            *latch = AddrByte::Low;
        }
        AddrByte::Low => {
            *target = (*target & 0xFF00) | ((val as u16) << 0);
            *latch = AddrByte::High;
        }
    }
}

impl Default for PPUReg {
    fn default() -> PPUReg {
        PPUReg {
            ppuctrl: PPUCtrl::empty(),
            ppumask: PPUMask::empty(),
            ppustat: PPUStat::empty(),
            oamaddr: 0,
            ppuscroll: 0,
            ppuaddr: 0,
            dyn_latch: 0,
            address_latch: AddrByte::High,
        }
    }
}

impl MemSegment for PPUReg {
    fn read(&mut self, idx: u16) -> u8 {
        match idx % 8 {
            0x0000 => self.dyn_latch,
            0x0001 => self.dyn_latch,
            0x0002 => {
                self.address_latch = AddrByte::High;
                let res = self.ppustat.bits | (self.dyn_latch & 0b0001_1111);
                self.ppustat.remove(VBLANK);
                res
            }
            0x0003 => self.dyn_latch,
            0x0005 => self.dyn_latch,
            0x0006 => self.dyn_latch,
            _ => invalid_address!(idx),
        }
    }

    fn write(&mut self, idx: u16, val: u8) {
        self.dyn_latch = val;
        match idx % 8 {
            0x0000 => self.ppuctrl = PPUCtrl::new(val),
            0x0001 => self.ppumask = PPUMask::from_bits_truncate(val),
            0x0002 => (),
            0x0003 => self.oamaddr = val,
            0x0005 => write_addr_byte(&mut self.address_latch, &mut self.ppuscroll, val),
            0x0006 => {
                if self.address_latch == AddrByte::High {
                    self.ppuctrl = PPUCtrl::new(self.ppuctrl.bits & 0b1111_1110);
                }
                write_addr_byte(&mut self.address_latch, &mut self.ppuaddr, val)
            }
            _ => invalid_address!(idx),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use memory::MemSegment;
    use ppu::PPU;
    use ppu::tests::*;

    fn assert_register_single_writable(idx: u16, getter: &Fn(&PPU) -> u8) {
        let mut ppu = create_test_ppu();
        ppu.write(idx, 12);
        assert_eq!(getter(&ppu), 12);
        ppu.write(idx, 125);
        assert_eq!(getter(&ppu), 125);
    }

    fn assert_register_double_writable(idx: u16, getter: &Fn(&PPU) -> u16) {
        let mut ppu = create_test_ppu();
        ppu.write(idx, 0xDE);
        assert_eq!(getter(&ppu), 0xDE00);
        assert_eq!(AddrByte::Low, ppu.reg.address_latch);
        ppu.write(idx, 0xAD);
        assert_eq!(getter(&ppu), 0xDEAD);
        assert_eq!(AddrByte::High, ppu.reg.address_latch);
    }

    fn assert_register_ignores_writes(idx: u16, getter: &Fn(&PPU) -> u8) {
        let mut ppu = create_test_ppu();
        ppu.write(idx, 12);
        assert_eq!(getter(&ppu), 0);
        ppu.write(idx, 125);
        assert_eq!(getter(&ppu), 0);
    }

    fn assert_writing_register_fills_latch(idx: u16) {
        let mut ppu = create_test_ppu();
        ppu.write(idx, 12);
        assert_eq!(ppu.reg.dyn_latch, 12);
        ppu.write(idx, 125);
        assert_eq!(ppu.reg.dyn_latch, 125);
    }

    fn assert_register_is_readable(idx: u16, setter: &Fn(&mut PPU, u8) -> ()) {
        let mut ppu = create_test_ppu();
        setter(&mut ppu, 12);
        assert_eq!(ppu.read(idx), 12);
        setter(&mut ppu, 125);
        assert_eq!(ppu.read(idx), 125);
    }

    fn assert_register_not_readable(idx: u16) {
        let mut ppu = create_test_ppu();
        ppu.reg.dyn_latch = 12;
        assert_eq!(ppu.read(idx), 12);
        ppu.reg.dyn_latch = 125;
        assert_eq!(ppu.read(idx), 125);
    }

    #[test]
    fn ppuctrl_is_write_only_register() {
        assert_register_single_writable(0x2000, &|ref ppu| ppu.reg.ppuctrl.bits);
        assert_writing_register_fills_latch(0x2000);
        assert_register_not_readable(0x2000);
    }

    #[test]
    fn ppu_mirrors_address() {
        assert_register_single_writable(0x2008, &|ref ppu| ppu.reg.ppuctrl.bits);
        assert_register_single_writable(0x2010, &|ref ppu| ppu.reg.ppuctrl.bits);
    }

    #[test]
    fn ppumask_is_write_only_register() {
        assert_register_single_writable(0x2001, &|ref ppu| ppu.reg.ppumask.bits());
        assert_writing_register_fills_latch(0x2001);
        assert_register_not_readable(0x2001);
    }

    #[test]
    fn ppustat_is_read_only_register() {
        assert_register_ignores_writes(0x2002, &|ref ppu| ppu.reg.ppustat.bits);
        assert_writing_register_fills_latch(0x2002);
        assert_register_is_readable(0x2002,
                                    &|ref mut ppu, val| {
                                        ppu.reg.ppustat = PPUStat::from_bits_truncate(val);
                                        ppu.reg.dyn_latch = val;
                                    });
    }

    #[test]
    fn reading_ppustat_returns_part_of_dynlatch() {
        let mut ppu = create_test_ppu();
        ppu.reg.dyn_latch = 0b0001_0101;
        ppu.reg.ppustat = PPUStat::from_bits_truncate(0b1010_0101);
        assert_eq!(ppu.read(0x2002), 0b1011_0101);
    }

    #[test]
    fn reading_ppustat_clears_addr_latch() {
        let mut ppu = create_test_ppu();
        ppu.reg.address_latch = AddrByte::Low;
        ppu.read(0x2002);
        assert_eq!(ppu.reg.address_latch, AddrByte::High);
    }

    #[test]
    fn oamaddr_is_write_only_register() {
        assert_register_single_writable(0x2003, &|ref ppu| ppu.reg.oamaddr);
        assert_writing_register_fills_latch(0x2003);
        assert_register_not_readable(0x2003);
    }

    #[test]
    fn ppuscroll_is_2x_write_only_register() {
        assert_register_double_writable(0x2005, &|ref ppu| ppu.reg.ppuscroll);
        assert_writing_register_fills_latch(0x2005);
        assert_register_not_readable(0x2005);
    }

    #[test]
    fn ppuaddr_is_2x_write_only_register() {
        assert_register_double_writable(0x2006, &|ref ppu| ppu.reg.ppuaddr);
        assert_writing_register_fills_latch(0x2006);
        assert_register_not_readable(0x2006);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use cloudabi as abi;
use core::{
    cell::Cell,
    mem,
    sync::atomic::{AtomicU32, Ordering},
};
use std::{convert::TryFrom, thread, time::Instant};

extern "C" {
    #[thread_local]
    static __pthread_thread_id: abi::tid;
}

struct Lock {
    lock: AtomicU32,
}

impl Lock {
    #[inline]
    pub fn new() -> Self {
        Lock {
            lock: AtomicU32::new(abi::LOCK_UNLOCKED.0),
        }
    }

    #[inline]
    unsafe fn try_lock(&self) -> bool {
        // Attempt to acquire the lock.
        if let Err(old) = self.lock.compare_exchange(
            abi::LOCK_UNLOCKED.0,
            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
            Ordering::Acquire,
            Ordering::Relaxed,
        ) {
            // Failure. Crash upon recursive acquisition.
            debug_assert_ne!(
                old & !abi::LOCK_KERNEL_MANAGED.0,
                __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
                "Attempted to recursive write-lock a lock",
            );
            false
        } else {
            true
        }
    }

    #[inline]
    pub unsafe fn lock(&self) {
        if !self.try_lock() {
            // Call into the kernel to acquire a write lock.
            let subscription = abi::subscription {
                type_: abi::eventtype::LOCK_WRLOCK,
                union: abi::subscription_union {
                    lock: abi::subscription_lock {
                        lock: self.ptr(),
                        lock_scope: abi::scope::PRIVATE,
                    },
                },
                ..mem::zeroed()
            };
            let mut event: abi::event = mem::uninitialized();
            let mut nevents: usize = mem::uninitialized();
            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
            debug_assert_eq!(ret, abi::errno::SUCCESS);
            debug_assert_eq!(event.error, abi::errno::SUCCESS);
        }
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        debug_assert_eq!(
            self.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
            "This lock is not write-locked by this thread"
        );

        if !self
            .lock
            .compare_exchange(
                __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
                abi::LOCK_UNLOCKED.0,
                Ordering::Release,
                Ordering::Relaxed,
            )
            .is_ok()
        {
            // Lock is managed by kernelspace. Call into the kernel
            // to unblock waiting threads.
            let ret = abi::lock_unlock(self.ptr(), abi::scope::PRIVATE);
            debug_assert_eq!(ret, abi::errno::SUCCESS);
        }
    }

    #[inline]
    fn ptr(&self) -> *mut abi::lock {
        &self.lock as *const AtomicU32 as *mut abi::lock
    }
}

struct Condvar {
    condvar: AtomicU32,
}

impl Condvar {
    #[inline]
    pub fn new() -> Self {
        Condvar {
            condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0),
        }
    }

    #[inline]
    pub unsafe fn wait(&self, lock: &Lock) {
        let subscription = abi::subscription {
            type_: abi::eventtype::CONDVAR,
            union: abi::subscription_union {
                condvar: abi::subscription_condvar {
                    condvar: self.ptr(),
                    condvar_scope: abi::scope::PRIVATE,
                    lock: lock.ptr(),
                    lock_scope: abi::scope::PRIVATE,
                },
            },
            ..mem::zeroed()
        };
        let mut event: abi::event = mem::uninitialized();
        let mut nevents: usize = mem::uninitialized();

        let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
        debug_assert_eq!(ret, abi::errno::SUCCESS);
        debug_assert_eq!(event.error, abi::errno::SUCCESS);
    }

    /// Waits for a signal on the condvar.
    /// Returns false if it times out before a signal was received.
    #[inline]
    pub unsafe fn wait_timeout(&self, lock: &Lock, timeout: abi::timestamp) -> bool {
        let subscriptions = [
            abi::subscription {
                type_: abi::eventtype::CONDVAR,
                union: abi::subscription_union {
                    condvar: abi::subscription_condvar {
                        condvar: self.ptr(),
                        condvar_scope: abi::scope::PRIVATE,
                        lock: lock.ptr(),
                        lock_scope: abi::scope::PRIVATE,
                    },
                },
                ..mem::zeroed()
            },
            abi::subscription {
                type_: abi::eventtype::CLOCK,
                union: abi::subscription_union {
                    clock: abi::subscription_clock {
                        clock_id: abi::clockid::MONOTONIC,
                        timeout,
                        ..mem::zeroed()
                    },
                },
                ..mem::zeroed()
            },
        ];
        let mut events: [abi::event; 2] = mem::uninitialized();
        let mut nevents: usize = mem::uninitialized();
        let ret = abi::poll(subscriptions.as_ptr(), events.as_mut_ptr(), 2, &mut nevents);
        debug_assert_eq!(ret, abi::errno::SUCCESS);
        for i in 0..nevents {
            debug_assert_eq!(events[i].error, abi::errno::SUCCESS);
            if events[i].type_ == abi::eventtype::CONDVAR {
                return true;
            }
        }
        false
    }

    #[inline]
    pub unsafe fn signal(&self) {
        let ret = abi::condvar_signal(self.ptr(), abi::scope::PRIVATE, 1);
        debug_assert_eq!(ret, abi::errno::SUCCESS);
    }

    #[inline]
    fn ptr(&self) -> *mut abi::condvar {
        &self.condvar as *const AtomicU32 as *mut abi::condvar
    }
}

// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
    should_park: Cell<bool>,
    lock: Lock,
    condvar: Condvar,
}

impl ThreadParker {
    pub const IS_CHEAP_TO_CONSTRUCT: bool = true;

    #[inline]
    pub fn new() -> ThreadParker {
        ThreadParker {
            should_park: Cell::new(false),
            lock: Lock::new(),
            condvar: Condvar::new(),
        }
    }

    // Prepares the parker. This should be called before adding it to the queue.
    #[inline]
    pub unsafe fn prepare_park(&self) {
        self.should_park.set(true);
    }

    // Checks if the park timed out. This should be called while holding the
    // queue lock after park_until has returned false.
    #[inline]
    pub unsafe fn timed_out(&self) -> bool {
        // We need to grab the lock here because another thread may be
        // concurrently executing UnparkHandle::unpark, which is done without
        // holding the queue lock.
        self.lock.lock();
        let should_park = self.should_park.get();
        self.lock.unlock();
        should_park
    }

    // Parks the thread until it is unparked. This should be called after it has
    // been added to the queue, after unlocking the queue.
    #[inline]
    pub unsafe fn park(&self) {
        self.lock.lock();
        while self.should_park.get() {
            self.condvar.wait(&self.lock);
        }
        self.lock.unlock();
    }

    // Parks the thread until it is unparked or the timeout is reached. This
    // should be called after it has been added to the queue, after unlocking
    // the queue. Returns true if we were unparked and false if we timed out.
    #[inline]
    pub unsafe fn park_until(&self, timeout: Instant) -> bool {
        self.lock.lock();
        while self.should_park.get() {
            if let Some(duration_left) = timeout.checked_duration_since(Instant::now()) {
                if let Ok(nanos_left) = abi::timestamp::try_from(duration_left.as_nanos()) {
                    self.condvar.wait_timeout(&self.lock, nanos_left);
                } else {
                    // remaining timeout overflows an abi::timestamp. Sleep indefinitely
                    self.condvar.wait(&self.lock);
                }
            } else {
                // We timed out
                self.lock.unlock();
                return false;
            }
        }
        self.lock.unlock();
        true
    }

    // Locks the parker to prevent the target thread from exiting. This is
    // necessary to ensure that thread-local ThreadData objects remain valid.
    // This should be called while holding the queue lock.
    #[inline]
    pub unsafe fn unpark_lock(&self) -> UnparkHandle {
        self.lock.lock();

        UnparkHandle {
            thread_parker: self,
        }
    }
}

// Handle for a thread that is about to be unparked. We need to mark the thread
// as unparked while holding the queue lock, but we delay the actual unparking
// until after the queue lock is released.
pub struct UnparkHandle {
    thread_parker: *const ThreadParker,
}

impl UnparkHandle {
    // Wakes up the parked thread. This should be called after the queue lock is
    // released to avoid blocking the queue for too long.
    #[inline]
    pub unsafe fn unpark(self) {
        (*self.thread_parker).should_park.set(false);

        // We notify while holding the lock here to avoid races with the target
        // thread. In particular, the thread could exit after we unlock the
        // mutex, which would make the condvar access invalid memory.
        (*self.thread_parker).condvar.signal();
        (*self.thread_parker).lock.unlock();
    }
}

#[inline]
pub fn thread_yield() {
    thread::yield_now();
}
<commit_msg>Introduce LockGuard and mark everything as safe<commit_after>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use cloudabi as abi;
use core::{
    cell::Cell,
    mem,
    sync::atomic::{AtomicU32, Ordering},
};
use std::{convert::TryFrom, thread, time::Instant};

extern "C" {
    #[thread_local]
    static __pthread_thread_id: abi::tid;
}

struct Lock {
    lock: AtomicU32,
}

impl Lock {
    #[inline]
    pub fn new() -> Self {
        Lock {
            lock: AtomicU32::new(abi::LOCK_UNLOCKED.0),
        }
    }

    #[inline]
    fn try_lock(&self) -> Option<LockGuard<'_>> {
        // Attempt to acquire the lock.
        if let Err(old) = self.lock.compare_exchange(
            abi::LOCK_UNLOCKED.0,
            unsafe { __pthread_thread_id.0 } | abi::LOCK_WRLOCKED.0,
            Ordering::Acquire,
            Ordering::Relaxed,
        ) {
            // Failure. Crash upon recursive acquisition.
            debug_assert_ne!(
                old & !abi::LOCK_KERNEL_MANAGED.0,
                unsafe { __pthread_thread_id.0 } | abi::LOCK_WRLOCKED.0,
                "Attempted to recursive write-lock a lock",
            );
            None
        } else {
            Some(LockGuard { inner: &self })
        }
    }

    #[inline]
    pub fn lock(&self) -> LockGuard<'_> {
        self.try_lock().unwrap_or_else(|| {
            // Call into the kernel to acquire a write lock.
            unsafe {
                let subscription = abi::subscription {
                    type_: abi::eventtype::LOCK_WRLOCK,
                    union: abi::subscription_union {
                        lock: abi::subscription_lock {
                            lock: self.ptr(),
                            lock_scope: abi::scope::PRIVATE,
                        },
                    },
                    ..mem::zeroed()
                };
                let mut event: abi::event = mem::uninitialized();
                let mut nevents: usize = mem::uninitialized();
                let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
                debug_assert_eq!(ret, abi::errno::SUCCESS);
                debug_assert_eq!(event.error, abi::errno::SUCCESS);
            }
            LockGuard { inner: &self }
        })
    }

    #[inline]
    fn ptr(&self) -> *mut abi::lock {
        &self.lock as *const AtomicU32 as *mut abi::lock
    }
}

struct LockGuard<'a> {
    inner: &'a Lock,
}

impl LockGuard<'_> {
    #[inline]
    fn ptr(&self) -> *mut abi::lock {
        &self.inner.lock as *const AtomicU32 as *mut abi::lock
    }
}

impl Drop for LockGuard<'_> {
    fn drop(&mut self) {
        debug_assert_eq!(
            self.inner.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
            unsafe { __pthread_thread_id.0 } | abi::LOCK_WRLOCKED.0,
            "This lock is not write-locked by this thread"
        );

        if !self
            .inner
            .lock
            .compare_exchange(
                unsafe { __pthread_thread_id.0 } | abi::LOCK_WRLOCKED.0,
                abi::LOCK_UNLOCKED.0,
                Ordering::Release,
                Ordering::Relaxed,
            )
            .is_ok()
        {
            // Lock is managed by kernelspace. Call into the kernel
            // to unblock waiting threads.
            let ret = unsafe { abi::lock_unlock(self.ptr(), abi::scope::PRIVATE) };
            debug_assert_eq!(ret, abi::errno::SUCCESS);
        }
    }
}

struct Condvar {
    condvar: AtomicU32,
}

impl Condvar {
    #[inline]
    pub fn new() -> Self {
        Condvar {
            condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0),
        }
    }

    #[inline]
    pub fn wait(&self, lock: &LockGuard<'_>) {
        unsafe {
            let subscription = abi::subscription {
                type_: abi::eventtype::CONDVAR,
                union: abi::subscription_union {
                    condvar: abi::subscription_condvar {
                        condvar: self.ptr(),
                        condvar_scope: abi::scope::PRIVATE,
                        lock: lock.ptr(),
                        lock_scope: abi::scope::PRIVATE,
                    },
                },
                ..mem::zeroed()
            };
            let mut event: abi::event = mem::uninitialized();
            let mut nevents: usize = mem::uninitialized();

            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
            debug_assert_eq!(ret, abi::errno::SUCCESS);
            debug_assert_eq!(event.error, abi::errno::SUCCESS);
        }
    }

    /// Waits for a signal on the condvar.
    /// Returns false if it times out before a signal was received.
    #[inline]
    pub fn wait_timeout(&self, lock: &LockGuard<'_>, timeout: abi::timestamp) -> bool {
        unsafe {
            let subscriptions = [
                abi::subscription {
                    type_: abi::eventtype::CONDVAR,
                    union: abi::subscription_union {
                        condvar: abi::subscription_condvar {
                            condvar: self.ptr(),
                            condvar_scope: abi::scope::PRIVATE,
                            lock: lock.ptr(),
                            lock_scope: abi::scope::PRIVATE,
                        },
                    },
                    ..mem::zeroed()
                },
                abi::subscription {
                    type_: abi::eventtype::CLOCK,
                    union: abi::subscription_union {
                        clock: abi::subscription_clock {
                            clock_id: abi::clockid::MONOTONIC,
                            timeout,
                            ..mem::zeroed()
                        },
                    },
                    ..mem::zeroed()
                },
            ];
            let mut events: [abi::event; 2] = mem::uninitialized();
            let mut nevents: usize = mem::uninitialized();

            let ret = abi::poll(subscriptions.as_ptr(), events.as_mut_ptr(), 2, &mut nevents);
            debug_assert_eq!(ret, abi::errno::SUCCESS);
            for i in 0..nevents {
                debug_assert_eq!(events[i].error, abi::errno::SUCCESS);
                if events[i].type_ == abi::eventtype::CONDVAR {
                    return true;
                }
            }
        }
        false
    }

    #[inline]
    pub fn signal(&self) {
        let ret = unsafe { abi::condvar_signal(self.ptr(), abi::scope::PRIVATE, 1) };
        debug_assert_eq!(ret, abi::errno::SUCCESS);
    }

    #[inline]
    fn ptr(&self) -> *mut abi::condvar {
        &self.condvar as *const AtomicU32 as *mut abi::condvar
    }
}

// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
    should_park: Cell<bool>,
    lock: Lock,
    condvar: Condvar,
}

impl ThreadParker {
    pub const IS_CHEAP_TO_CONSTRUCT: bool = true;

    #[inline]
    pub fn new() -> ThreadParker {
        ThreadParker {
            should_park: Cell::new(false),
            lock: Lock::new(),
            condvar: Condvar::new(),
        }
    }

    // Prepares the parker. This should be called before adding it to the queue.
    #[inline]
    pub fn prepare_park(&self) {
        self.should_park.set(true);
    }

    // Checks if the park timed out. This should be called while holding the
    // queue lock after park_until has returned false.
    #[inline]
    pub fn timed_out(&self) -> bool {
        // We need to grab the lock here because another thread may be
        // concurrently executing UnparkHandle::unpark, which is done without
        // holding the queue lock.
        let _guard = self.lock.lock();
        self.should_park.get()
    }

    // Parks the thread until it is unparked. This should be called after it has
    // been added to the queue, after unlocking the queue.
    #[inline]
    pub fn park(&self) {
        let guard = self.lock.lock();
        while self.should_park.get() {
            self.condvar.wait(&guard);
        }
    }

    // Parks the thread until it is unparked or the timeout is reached. This
    // should be called after it has been added to the queue, after unlocking
    // the queue. Returns true if we were unparked and false if we timed out.
    #[inline]
    pub fn park_until(&self, timeout: Instant) -> bool {
        let guard = self.lock.lock();
        while self.should_park.get() {
            if let Some(duration_left) = timeout.checked_duration_since(Instant::now()) {
                if let Ok(nanos_left) = abi::timestamp::try_from(duration_left.as_nanos()) {
                    self.condvar.wait_timeout(&guard, nanos_left);
                } else {
                    // remaining timeout overflows an abi::timestamp. Sleep indefinitely
                    self.condvar.wait(&guard);
                }
            } else {
                // We timed out
                return false;
            }
        }
        true
    }

    // Locks the parker to prevent the target thread from exiting. This is
    // necessary to ensure that thread-local ThreadData objects remain valid.
    // This should be called while holding the queue lock.
    #[inline]
    pub fn unpark_lock(&self) -> UnparkHandle<'_> {
        let _lock_guard = self.lock.lock();

        UnparkHandle {
            thread_parker: self,
            _lock_guard,
        }
    }
}

// Handle for a thread that is about to be unparked. We need to mark the thread
// as unparked while holding the queue lock, but we delay the actual unparking
// until after the queue lock is released.
pub struct UnparkHandle<'a> {
    thread_parker: *const ThreadParker,
    _lock_guard: LockGuard<'a>,
}

impl UnparkHandle<'_> {
    // Wakes up the parked thread. This should be called after the queue lock is
    // released to avoid blocking the queue for too long.
    #[inline]
    pub fn unpark(self) {
        unsafe {
            (*self.thread_parker).should_park.set(false);

            // We notify while holding the lock here to avoid races with the target
            // thread. In particular, the thread could exit after we unlock the
            // mutex, which would make the condvar access invalid memory.
            (*self.thread_parker).condvar.signal();
        }
    }
}

#[inline]
pub fn thread_yield() {
    thread::yield_now();
}
<|endoftext|>


<commit_before>#![crate_name = "process"]
#![crate_type = "rlib"]
#![no_std]
#![feature(core_intrinsics,raw,unique,nonzero)]

extern crate common;
extern crate support;

pub mod callback;
pub mod mem;
pub mod process;

pub use callback::{AppId, Callback};
pub use mem::{AppSlice, AppPtr, Private, Shared};
pub use process::{Process,State};

<commit_msg>Revert "Process lib - clone_from_slice stable"<commit_after>#![crate_name = "process"]
#![crate_type = "rlib"]
#![no_std]
#![feature(core_intrinsics,clone_from_slice,raw,unique,nonzero)]

extern crate common;
extern crate support;

pub mod callback;
pub mod mem;
pub mod process;

pub use callback::{AppId, Callback};
pub use mem::{AppSlice, AppPtr, Private, Shared};
pub use process::{Process,State};

<|endoftext|>


<commit_before>use std::path::Path;
use std::io::prelude::*;
use std::fs::File;
#[cfg(not(test))] use std::env::home_dir;
use yaml_rust::{YamlLoader, YamlEmitter, Yaml};

mod parser;

static MUXED_FOLDER: &'static str = "muxed";

pub fn open(project_name: String) -> Vec<Yaml> {
    YamlLoader::load_from_str(&read(path_string(project_name))).unwrap()
}

pub fn path_string(project_name: String) -> String {
    format!("{}/.{}/{}", homedir_string(), &MUXED_FOLDER.to_string(), project_name)
}

fn read(config_str: String) -> String {
    let path = Path::new(&config_str);
    let mut s = String::new();
    File::open(path).expect("Config Read error").read_to_string(&mut s);

    return s
}

fn parse_config() {
}

#[cfg(not(test))] fn homedir_string() -> String {
    match home_dir() {
        Some(dir) => format!("{}", dir.display()),
        None      => panic!("Impossible to get your home dir!")
    }
}

#[cfg(test)] fn homedir_string() -> String {
  String::from("/tmp")
}

#[test]
pub fn path_string_returns_muxed_inside_homedir() {
    let path = format!("{}", path_string("".to_string()));
    let new  = format!("{}", Path::new("/tmp/.muxed/").display());
    assert_eq!(path, new)
}
<commit_msg>Open the project instead of calling out to tmux directly.<commit_after>use std::path::Path;
use std::io::prelude::*;
use std::fs::File;
#[cfg(not(test))] use std::env::home_dir;
use yaml_rust::{YamlLoader, YamlEmitter, Yaml};

mod parser;

static MUXED_FOLDER: &'static str = "muxed";

pub fn open(project_name: String) -> Vec<Yaml> {
    let yaml = YamlLoader::load_from_str(&read(path_string(project_name))).unwrap();
    parser::main(&yaml);
    yaml
}

pub fn path_string(project_name: String) -> String {
    format!("{}/.{}/{}", homedir_string(), &MUXED_FOLDER.to_string(), project_name)
}

fn read(config_str: String) -> String {
    let path = Path::new(&config_str);
    let mut s = String::new();
    File::open(path).expect("Config Read error").read_to_string(&mut s);

    return s
}

fn parse_config() {
}

#[cfg(not(test))] fn homedir_string() -> String {
    match home_dir() {
        Some(dir) => format!("{}", dir.display()),
        None      => panic!("Impossible to get your home dir!")
    }
}

#[cfg(test)] fn homedir_string() -> String {
  String::from("/tmp")
}

#[test]
pub fn path_string_returns_muxed_inside_homedir() {
    let path = format!("{}", path_string("".to_string()));
    let new  = format!("{}", Path::new("/tmp/.muxed/").display());
    assert_eq!(path, new)
}
<|endoftext|>


<commit_before>use std::slice::Iter;
use std::vec::Vec;

use analysis::conversion_type::ConversionType;
use analysis::function_parameters::CParameter;
use analysis::functions::is_carray_with_direct_elements;
use analysis::imports::Imports;
use analysis::ref_mode::RefMode;
use analysis::return_value;
use analysis::rust_type::parameter_rust_type;
use config;
use env::Env;
use library::*;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Mode {
    None,
    Normal,
    Optional,
    Combined,
    //<use function return>
    Throws(bool),
}

impl Default for Mode {
    fn default() -> Mode {
        Mode::None
    }
}

#[derive(Debug, Default)]
pub struct Info {
    pub mode: Mode,
    pub params: Vec<Parameter>,
}

impl Info {
    pub fn is_empty(&self) -> bool {
        self.mode == Mode::None
    }

    pub fn iter(&self) -> Iter<Parameter> {
        self.params.iter()
    }
}

pub fn analyze(
    env: &Env,
    func: &Function,
    func_c_params: &[CParameter],
    func_ret: &return_value::Info,
    configured_functions: &[&config::functions::Function],
) -> (Info, bool) {
    let mut info: Info = Default::default();
    let mut unsupported_outs = false;

    let nullable_override = configured_functions
        .iter()
        .filter_map(|f| f.ret.nullable)
        .next();
    if func.throws {
        let use_ret = use_return_value_for_result(env, func_ret);
        info.mode = Mode::Throws(use_ret);
    } else if func.ret.typ == TypeId::tid_none() {
        info.mode = Mode::Normal;
    } else if func.ret.typ == TypeId::tid_bool() {
        if nullable_override == Some(Nullable(false)) {
            info.mode = Mode::Combined;
        } else {
            info.mode = Mode::Optional;
        }
    } else {
        info.mode = Mode::Combined;
    }

    for par in &func.parameters {
        if par.direction != ParameterDirection::Out {
            continue;
        }
        if can_as_return(env, par) {
            let mut par = par.clone();
            //TODO: temporary solution for string_type override
            if let Some(c_par) = func_c_params.iter().find(|c_par| c_par.name == par.name) {
                par.typ = c_par.typ;
            }
            info.params.push(par);
        } else {
            unsupported_outs = true;
        }
    }

    if info.params.is_empty() {
        info.mode = Mode::None;
    }
    if info.mode == Mode::Combined || info.mode == Mode::Throws(true) {
        let mut ret = func.ret.clone();
        //TODO: fully switch to use analyzed returns (it add too many Return<Option<>>)
        if let Some(ref par) = func_ret.parameter {
            ret.typ = par.typ;
        }
        if let Some(val) = nullable_override {
            ret.nullable = val;
        }
        info.params.insert(0, ret);
    }

    (info, unsupported_outs)
}

pub fn analyze_imports(env: &Env, func: &Function, imports: &mut Imports) {
    for par in &func.parameters {
        if par.direction == ParameterDirection::Out {
            match *env.library.type_(par.typ) {
                Type::Bitfield(..) | Type::Enumeration(..) => imports.add("std::mem", func.version),
                Type::Fundamental(fund)
                    if fund != Fundamental::Utf8
                        && fund != Fundamental::OsString
                        && fund != Fundamental::Filename =>
                {
                    imports.add("std::mem", func.version)
                }
                _ if !par.caller_allocates => imports.add("std::ptr", func.version),
                _ => (),
            }
        }
    }
}

pub fn can_as_return(env: &Env, par: &Parameter) -> bool {
    use super::conversion_type::ConversionType::*;
    match ConversionType::of(env, par.typ) {
        Direct => true,
        Scalar => true,
        Pointer => {
            // Disallow fundamental arrays without length
            if is_carray_with_direct_elements(env, par.typ) && par.array_length.is_none() {
                return false;
            }

            parameter_rust_type(
                env,
                par.typ,
                ParameterDirection::Out,
                Nullable(false),
                RefMode::None,
            ).is_ok()
        }
        Borrow => false,
        Unknown => false,
    }
}

pub fn use_return_value_for_result(env: &Env, ret: &return_value::Info) -> bool {
    if let Some(ref par) = ret.parameter {
        use_function_return_for_result(env, par.typ)
    } else {
        false
    }
}

pub fn use_function_return_for_result(env: &Env, typ: TypeId) -> bool {
    if typ == Default::default() {
        return false;
    }
    if typ.ns_id != INTERNAL_NAMESPACE {
        return true;
    }
    let type_ = env.type_(typ);
    match &*type_.get_name() {
        "UInt" => false,
        "Boolean" => false,
        _ => true,
    }
}
<commit_msg>Fix generating function body when out parameter has reserved name<commit_after>use std::slice::Iter;
use std::vec::Vec;

use analysis::conversion_type::ConversionType;
use analysis::function_parameters::CParameter;
use analysis::functions::is_carray_with_direct_elements;
use analysis::imports::Imports;
use analysis::ref_mode::RefMode;
use analysis::return_value;
use analysis::rust_type::parameter_rust_type;
use config;
use env::Env;
use library::*;
use nameutil;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Mode {
    None,
    Normal,
    Optional,
    Combined,
    //<use function return>
    Throws(bool),
}

impl Default for Mode {
    fn default() -> Mode {
        Mode::None
    }
}

#[derive(Debug, Default)]
pub struct Info {
    pub mode: Mode,
    pub params: Vec<Parameter>,
}

impl Info {
    pub fn is_empty(&self) -> bool {
        self.mode == Mode::None
    }

    pub fn iter(&self) -> Iter<Parameter> {
        self.params.iter()
    }
}

pub fn analyze(
    env: &Env,
    func: &Function,
    func_c_params: &[CParameter],
    func_ret: &return_value::Info,
    configured_functions: &[&config::functions::Function],
) -> (Info, bool) {
    let mut info: Info = Default::default();
    let mut unsupported_outs = false;

    let nullable_override = configured_functions
        .iter()
        .filter_map(|f| f.ret.nullable)
        .next();
    if func.throws {
        let use_ret = use_return_value_for_result(env, func_ret);
        info.mode = Mode::Throws(use_ret);
    } else if func.ret.typ == TypeId::tid_none() {
        info.mode = Mode::Normal;
    } else if func.ret.typ == TypeId::tid_bool() {
        if nullable_override == Some(Nullable(false)) {
            info.mode = Mode::Combined;
        } else {
            info.mode = Mode::Optional;
        }
    } else {
        info.mode = Mode::Combined;
    }

    for par in &func.parameters {
        if par.direction != ParameterDirection::Out {
            continue;
        }
        if can_as_return(env, par) {
            let mut par = par.clone();
            par.name = nameutil::mangle_keywords(&*par.name).into_owned();
            //TODO: temporary solution for string_type override
            if let Some(c_par) = func_c_params.iter().find(|c_par| c_par.name == par.name) {
                par.typ = c_par.typ;
            }
            info.params.push(par);
        } else {
            unsupported_outs = true;
        }
    }

    if info.params.is_empty() {
        info.mode = Mode::None;
    }
    if info.mode == Mode::Combined || info.mode == Mode::Throws(true) {
        let mut ret = func.ret.clone();
        //TODO: fully switch to use analyzed returns (it add too many Return<Option<>>)
        if let Some(ref par) = func_ret.parameter {
            ret.typ = par.typ;
        }
        if let Some(val) = nullable_override {
            ret.nullable = val;
        }
        info.params.insert(0, ret);
    }

    (info, unsupported_outs)
}

pub fn analyze_imports(env: &Env, func: &Function, imports: &mut Imports) {
    for par in &func.parameters {
        if par.direction == ParameterDirection::Out {
            match *env.library.type_(par.typ) {
                Type::Bitfield(..) | Type::Enumeration(..) => imports.add("std::mem", func.version),
                Type::Fundamental(fund)
                    if fund != Fundamental::Utf8
                        && fund != Fundamental::OsString
                        && fund != Fundamental::Filename =>
                {
                    imports.add("std::mem", func.version)
                }
                _ if !par.caller_allocates => imports.add("std::ptr", func.version),
                _ => (),
            }
        }
    }
}

pub fn can_as_return(env: &Env, par: &Parameter) -> bool {
    use super::conversion_type::ConversionType::*;
    match ConversionType::of(env, par.typ) {
        Direct => true,
        Scalar => true,
        Pointer => {
            // Disallow fundamental arrays without length
            if is_carray_with_direct_elements(env, par.typ) && par.array_length.is_none() {
                return false;
            }

            parameter_rust_type(
                env,
                par.typ,
                ParameterDirection::Out,
                Nullable(false),
                RefMode::None,
            ).is_ok()
        }
        Borrow => false,
        Unknown => false,
    }
}

pub fn use_return_value_for_result(env: &Env, ret: &return_value::Info) -> bool {
    if let Some(ref par) = ret.parameter {
        use_function_return_for_result(env, par.typ)
    } else {
        false
    }
}

pub fn use_function_return_for_result(env: &Env, typ: TypeId) -> bool {
    if typ == Default::default() {
        return false;
    }
    if typ.ns_id != INTERNAL_NAMESPACE {
        return true;
    }
    let type_ = env.type_(typ);
    match &*type_.get_name() {
        "UInt" => false,
        "Boolean" => false,
        _ => true,
    }
}
<|endoftext|>


<commit_before>#[derive(Debug, Clone)]
pub struct RequestURI {
    base: String,
    query: String,
}

impl RequestURI {
    /// Create RequestURI type resource.
    pub fn new(base: String, query: String) -> RequestURI {
        RequestURI {
            base: base,
            query: query,
        }
    }

    /// Construct requesting URL from RequestURI type resource.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruroonga_client;
    /// use ruroonga_client::builtin::command_query::CommandQuery;
    /// let uri_base = ruroonga_client::URIBase::new().build();
    /// let mut command = CommandQuery::new("select");
    /// command.set_argument(vec![("table", "Sites")]);
    /// let url = ruroonga_client::RequestURI::new(uri_base, command.encode()).url();
    /// ```
    pub fn url(self) -> String {
        let url = format!("{}{}", self.base, self.query);
        url
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use builtin::command_query::CommandQuery;
    use uri_base::URIBase;

    #[test]
    fn construct_request_uri() {
        let url = RequestURI::new("http://localhost:10041".to_string(),
                                  "/d/status".to_string())
            .url();
        assert_eq!("http://localhost:10041/d/status", url)
    }

    #[test]
    fn construct_with_actual_usage() {
        let uri_base = URIBase::new().build();
        let mut command = CommandQuery::new("select");
        command.set_argument(vec![("table", "Sites")]);
        let url = RequestURI::new(uri_base, command.encode()).url();
        assert_eq!("http://localhost:10041/d/select?table=Sites", url)
    }
}
<commit_msg>request_uri: Use Cow to reduce allocation<commit_after>use std::borrow::Cow;

#[derive(Debug, Clone)]
pub struct RequestURI<'a> {
    base: Cow<'a, str>,
    query: Cow<'a, str>,
}

impl<'a> RequestURI<'a> {
    /// Create RequestURI type resource.
    pub fn new<T>(base: T, query: T) -> RequestURI<'a>
        where T: Into<Cow<'a, str>>
    {
        RequestURI {
            base: base.into(),
            query: query.into(),
        }
    }

    /// Construct requesting URL from RequestURI type resource.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruroonga_client;
    /// use ruroonga_client::builtin::command_query::CommandQuery;
    /// let uri_base = ruroonga_client::URIBase::new().build();
    /// let mut command = CommandQuery::new("select");
    /// command.set_argument(vec![("table", "Sites")]);
    /// let url = ruroonga_client::RequestURI::new(uri_base, command.encode()).url();
    /// ```
    pub fn url(self) -> String {
        let url = format!("{}{}", self.base.into_owned(), self.query.into_owned());
        url
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use builtin::command_query::CommandQuery;
    use uri_base::URIBase;

    #[test]
    fn construct_request_uri() {
        let url = RequestURI::new("http://localhost:10041",
                                  "/d/status")
            .url();
        assert_eq!("http://localhost:10041/d/status", url)
    }

    #[test]
    fn construct_request_uri_with_owned_str() {
        let url = RequestURI::new("http://localhost:10041".to_string(),
                                  "/d/status".to_string())
            .url();
        assert_eq!("http://localhost:10041/d/status", url)
    }

    #[test]
    fn construct_with_actual_usage() {
        let uri_base = URIBase::new().build();
        let mut command = CommandQuery::new("select");
        command.set_argument(vec![("table", "Sites")]);
        let url = RequestURI::new(uri_base, command.encode()).url();
        assert_eq!("http://localhost:10041/d/select?table=Sites", url)
    }
}
<|endoftext|>


<commit_before>//! WASM32 intrinsics

#[cfg(test)]
use stdsimd_test::assert_instr;
#[cfg(test)]
use wasm_bindgen_test::wasm_bindgen_test;

#[cfg(any(target_feature = "atomics", dox))]
mod atomic;
#[cfg(any(target_feature = "atomics", dox))]
pub use self::atomic::*;

#[cfg(any(target_feature = "simd128", dox))]
mod simd128;
#[cfg(any(target_feature = "simd128", dox))]
pub use self::simd128::*;

mod memory;
pub use self::memory::*;

/// Generates the trap instruction `UNREACHABLE`
#[cfg_attr(test, assert_instr(unreachable))]
#[inline]
pub unsafe fn unreachable() -> ! {
    crate::intrinsics::abort()
}
<commit_msg>Stabilize `unreachable`.<commit_after>//! WASM32 intrinsics

#[cfg(test)]
use stdsimd_test::assert_instr;
#[cfg(test)]
use wasm_bindgen_test::wasm_bindgen_test;

#[cfg(any(target_feature = "atomics", dox))]
mod atomic;
#[cfg(any(target_feature = "atomics", dox))]
pub use self::atomic::*;

#[cfg(any(target_feature = "simd128", dox))]
mod simd128;
#[cfg(any(target_feature = "simd128", dox))]
pub use self::simd128::*;

mod memory;
pub use self::memory::*;

/// Generates the trap instruction `UNREACHABLE`
#[cfg_attr(test, assert_instr(unreachable))]
#[inline]
#[stable(feature = "unreachable_wasm32", since = "1.37.0")]
pub unsafe fn unreachable() -> ! {
    crate::intrinsics::abort()
}
<|endoftext|>


<commit_before>use drop_bomb::DropBomb;

use crate::{
    parser_impl::ParserImpl,
    token_set::TokenSet,
    SyntaxKind::{self, ERROR},
};

/// `Parser` struct provides the low-level API for
/// navigating through the stream of tokens and
/// constructing the parse tree. The actual parsing
/// happens in the `grammar` module.
///
/// However, the result of this `Parser` is not a real
/// tree, but rather a flat stream of events of the form
/// "start expression, consume number literal,
/// finish expression". See `Event` docs for more.
pub(crate) struct Parser<'t>(pub(super) ParserImpl<'t>);

impl<'t> Parser<'t> {
    /// Returns the kind of the current token.
    /// If parser has already reached the end of input,
    /// the special `EOF` kind is returned.
    pub(crate) fn current(&self) -> SyntaxKind {
        self.nth(0)
    }

    /// Lookahead operation: returns the kind of the next nth
    /// token.
    pub(crate) fn nth(&self, n: u32) -> SyntaxKind {
        self.0.nth(n)
    }

    /// Checks if the current token is `kind`.
    pub(crate) fn at(&self, kind: SyntaxKind) -> bool {
        self.current() == kind
    }

    /// Checks if the current token is `kind`.
    pub(crate) fn at_ts(&self, kinds: TokenSet) -> bool {
        kinds.contains(self.current())
    }

    pub(crate) fn next2(&self) -> Option<(SyntaxKind, SyntaxKind)> {
        self.0.next2()
    }

    pub(crate) fn next3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> {
        self.0.next3()
    }

    /// Checks if the current token is contextual keyword with text `t`.
    pub(crate) fn at_contextual_kw(&self, t: &str) -> bool {
        self.0.at_kw(t)
    }

    /// Starts a new node in the syntax tree. All nodes and tokens
    /// consumed between the `start` and the corresponding `Marker::complete`
    /// belong to the same node.
    pub(crate) fn start(&mut self) -> Marker {
        Marker::new(self.0.start())
    }

    /// Advances the parser by one token.
    pub(crate) fn bump(&mut self) {
        self.0.bump();
    }

    /// Advances the parser by one token, remapping its kind.
    /// This is useful to create contextual keywords from
    /// identifiers. For example, the lexer creates an `union`
    /// *identifier* token, but the parser remaps it to the
    /// `union` keyword, and keyword is what ends up in the
    /// final tree.
    pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) {
        self.0.bump_remap(kind);
    }

    /// Advances the parser by `n` tokens, remapping its kind.
    /// This is useful to create compound tokens from parts. For
    /// example, an `<<` token is two consecutive remapped `<` tokens
    pub(crate) fn bump_compound(&mut self, kind: SyntaxKind, n: u8) {
        self.0.bump_compound(kind, n);
    }

    /// Emit error with the `message`
    /// TODO: this should be much more fancy and support
    /// structured errors with spans and notes, like rustc
    /// does.
    pub(crate) fn error<T: Into<String>>(&mut self, message: T) {
        self.0.error(message.into())
    }

    /// Consume the next token if it is `kind`.
    pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
        if !self.at(kind) {
            return false;
        }
        self.bump();
        true
    }

    /// Consume the next token if it is `kind` or emit an error
    /// otherwise.
    pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
        if self.eat(kind) {
            return true;
        }
        self.error(format!("expected {:?}", kind));
        false
    }

    /// Create an error node and consume the next token.
    pub(crate) fn err_and_bump(&mut self, message: &str) {
        self.err_recover(message, TokenSet::EMPTY);
    }

    /// Create an error node and consume the next token.
    pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) {
        if self.at(SyntaxKind::L_CURLY) || self.at(SyntaxKind::R_CURLY) || self.at_ts(recovery) {
            self.error(message);
        } else {
            let m = self.start();
            self.error(message);
            self.bump();
            m.complete(self, ERROR);
        };
    }
}

/// See `Parser::start`.
pub(crate) struct Marker {
    pos: u32,
    bomb: DropBomb,
}

impl Marker {
    fn new(pos: u32) -> Marker {
        Marker {
            pos,
            bomb: DropBomb::new("Marker must be either completed or abandoned"),
        }
    }

    /// Finishes the syntax tree node and assigns `kind` to it.
    pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
        self.bomb.defuse();
        p.0.complete(self.pos, kind);
        CompletedMarker(self.pos, kind)
    }

    /// Abandons the syntax tree node. All its children
    /// are attached to its parent instead.
    pub(crate) fn abandon(mut self, p: &mut Parser) {
        self.bomb.defuse();
        p.0.abandon(self.pos);
    }
}

pub(crate) struct CompletedMarker(u32, SyntaxKind);

impl CompletedMarker {
    /// This one is tricky :-)
    /// This method allows to create a new node which starts
    /// *before* the current one. That is, parser could start
    /// node `A`, then complete it, and then after parsing the
    /// whole `A`, decide that it should have started some node
    /// `B` before starting `A`. `precede` allows to do exactly
    /// that. See also docs about `forward_parent` in `Event::Start`.
    pub(crate) fn precede(self, p: &mut Parser) -> Marker {
        Marker::new(p.0.precede(self.0))
    }

    pub(crate) fn kind(&self) -> SyntaxKind {
        self.1
    }
}
<commit_msg>Actually fix at_ts doc comment (committed wrong file :P)<commit_after>use drop_bomb::DropBomb;

use crate::{
    parser_impl::ParserImpl,
    token_set::TokenSet,
    SyntaxKind::{self, ERROR},
};

/// `Parser` struct provides the low-level API for
/// navigating through the stream of tokens and
/// constructing the parse tree. The actual parsing
/// happens in the `grammar` module.
///
/// However, the result of this `Parser` is not a real
/// tree, but rather a flat stream of events of the form
/// "start expression, consume number literal,
/// finish expression". See `Event` docs for more.
pub(crate) struct Parser<'t>(pub(super) ParserImpl<'t>);

impl<'t> Parser<'t> {
    /// Returns the kind of the current token.
    /// If parser has already reached the end of input,
    /// the special `EOF` kind is returned.
    pub(crate) fn current(&self) -> SyntaxKind {
        self.nth(0)
    }

    /// Lookahead operation: returns the kind of the next nth
    /// token.
    pub(crate) fn nth(&self, n: u32) -> SyntaxKind {
        self.0.nth(n)
    }

    /// Checks if the current token is `kind`.
    pub(crate) fn at(&self, kind: SyntaxKind) -> bool {
        self.current() == kind
    }

    /// Checks if the current token is in `kinds`.
    pub(crate) fn at_ts(&self, kinds: TokenSet) -> bool {
        kinds.contains(self.current())
    }

    pub(crate) fn next2(&self) -> Option<(SyntaxKind, SyntaxKind)> {
        self.0.next2()
    }

    pub(crate) fn next3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> {
        self.0.next3()
    }

    /// Checks if the current token is contextual keyword with text `t`.
    pub(crate) fn at_contextual_kw(&self, t: &str) -> bool {
        self.0.at_kw(t)
    }

    /// Starts a new node in the syntax tree. All nodes and tokens
    /// consumed between the `start` and the corresponding `Marker::complete`
    /// belong to the same node.
    pub(crate) fn start(&mut self) -> Marker {
        Marker::new(self.0.start())
    }

    /// Advances the parser by one token.
    pub(crate) fn bump(&mut self) {
        self.0.bump();
    }

    /// Advances the parser by one token, remapping its kind.
    /// This is useful to create contextual keywords from
    /// identifiers. For example, the lexer creates an `union`
    /// *identifier* token, but the parser remaps it to the
    /// `union` keyword, and keyword is what ends up in the
    /// final tree.
    pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) {
        self.0.bump_remap(kind);
    }

    /// Advances the parser by `n` tokens, remapping its kind.
    /// This is useful to create compound tokens from parts. For
    /// example, an `<<` token is two consecutive remapped `<` tokens
    pub(crate) fn bump_compound(&mut self, kind: SyntaxKind, n: u8) {
        self.0.bump_compound(kind, n);
    }

    /// Emit error with the `message`
    /// TODO: this should be much more fancy and support
    /// structured errors with spans and notes, like rustc
    /// does.
    pub(crate) fn error<T: Into<String>>(&mut self, message: T) {
        self.0.error(message.into())
    }

    /// Consume the next token if it is `kind`.
    pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
        if !self.at(kind) {
            return false;
        }
        self.bump();
        true
    }

    /// Consume the next token if it is `kind` or emit an error
    /// otherwise.
    pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
        if self.eat(kind) {
            return true;
        }
        self.error(format!("expected {:?}", kind));
        false
    }

    /// Create an error node and consume the next token.
    pub(crate) fn err_and_bump(&mut self, message: &str) {
        self.err_recover(message, TokenSet::EMPTY);
    }

    /// Create an error node and consume the next token.
    pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) {
        if self.at(SyntaxKind::L_CURLY) || self.at(SyntaxKind::R_CURLY) || self.at_ts(recovery) {
            self.error(message);
        } else {
            let m = self.start();
            self.error(message);
            self.bump();
            m.complete(self, ERROR);
        };
    }
}

/// See `Parser::start`.
pub(crate) struct Marker {
    pos: u32,
    bomb: DropBomb,
}

impl Marker {
    fn new(pos: u32) -> Marker {
        Marker {
            pos,
            bomb: DropBomb::new("Marker must be either completed or abandoned"),
        }
    }

    /// Finishes the syntax tree node and assigns `kind` to it.
    pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
        self.bomb.defuse();
        p.0.complete(self.pos, kind);
        CompletedMarker(self.pos, kind)
    }

    /// Abandons the syntax tree node. All its children
    /// are attached to its parent instead.
    pub(crate) fn abandon(mut self, p: &mut Parser) {
        self.bomb.defuse();
        p.0.abandon(self.pos);
    }
}

pub(crate) struct CompletedMarker(u32, SyntaxKind);

impl CompletedMarker {
    /// This one is tricky :-)
    /// This method allows to create a new node which starts
    /// *before* the current one. That is, parser could start
    /// node `A`, then complete it, and then after parsing the
    /// whole `A`, decide that it should have started some node
    /// `B` before starting `A`. `precede` allows to do exactly
    /// that. See also docs about `forward_parent` in `Event::Start`.
    pub(crate) fn precede(self, p: &mut Parser) -> Marker {
        Marker::new(p.0.precede(self.0))
    }

    pub(crate) fn kind(&self) -> SyntaxKind {
        self.1
    }
}
<|endoftext|>