<commit_before>//! Seat global utilities
//!
//! This module provides you with utilities for handling the seat globals
//! and the associated input wayland objects.
//!
//! ## How to use it
//!
//! ### Initialization
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//!
//! use smithay::wayland::seat::Seat;
//!
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! // insert the seat:
//! let (seat_state_token, seat_global) = Seat::new(
//!     &mut event_loop,
//!     "seat-0".into(), // the name of the seat, will be advertize to clients
//!     None /* insert a logger here*/
//! );
//! # }
//! ```
//!
//! ### Run usage
//!
//! Once the seat is initialized, you can add capabilities to it.
//!
//! Currently, only pointer and keyboard capabilities are supported by
//! smithay.
//!
//! You can add these capabilities via methods of the `Seat` struct that was
//! inserted in the event loop, that you can retreive via its token:
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//! #
//! # use smithay::wayland::seat::Seat;
//! #
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! # let (seat_state_token, seat_global) = Seat::new(
//! #     &mut event_loop,
//! #     "seat-0".into(), // the name of the seat, will be advertize to clients
//! #     None /* insert a logger here*/
//! # );
//! let pointer_handle = event_loop.state().get_mut(&seat_state_token).add_pointer();
//! # }
//! ```
//!
//! These handles can be cloned and sent accross thread, so you can keep one around
//! in your event-handling code to forward inputs to your clients.

mod keyboard;
mod pointer;

pub use self::keyboard::{Error as KeyboardError, KeyboardHandle};
pub use self::pointer::PointerHandle;
use wayland_server::{Client, EventLoopHandle, Global, Liveness, Resource, StateToken};
use wayland_server::protocol::{wl_keyboard, wl_pointer, wl_seat};

/// Internal data of a seat global
///
/// This struct gives you access to the control of the
/// capabilities of the associated seat.
///
/// It is directly inserted in the event loop by its `new` method.
///
/// See module-level documentation for details of use.
pub struct Seat {
    log: ::slog::Logger,
    name: String,
    pointer: Option<PointerHandle>,
    keyboard: Option<KeyboardHandle>,
    known_seats: Vec<wl_seat::WlSeat>,
}

impl Seat {
    /// Create a new seat global
    ///
    /// A new seat global is created with given name and inserted
    /// into this event loop.
    ///
    /// You are provided with the state token to retrieve it (allowing
    /// you to add or remove capabilities from it), and the global handle,
    /// in case you want to remove it.
    pub fn new<L>(
        evlh: &mut EventLoopHandle, name: String, logger: L
    ) -> (StateToken<Seat>, Global<wl_seat::WlSeat, StateToken<Seat>>)
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = ::slog_or_stdlog(logger);
        let seat = Seat {
            log: log.new(o!("smithay_module" => "seat_handler", "seat_name" => name.clone())),
            name: name,
            pointer: None,
            keyboard: None,
            known_seats: Vec::new(),
        };
        let token = evlh.state().insert(seat);
        // TODO: support version 5 (axis)
        let global = evlh.register_global(4, seat_global_bind, token.clone());
        (token, global)
    }

    /// Adds the pointer capability to this seat
    ///
    /// You are provided a `PointerHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// Calling this method on a seat that already has a pointer capability
    /// will overwrite it, and will be seen by the clients as if the
    /// mouse was unplugged and a new one was plugged.
    pub fn add_pointer(&mut self) -> PointerHandle {
        let pointer = self::pointer::create_pointer_handler();
        if self.pointer.is_some() {
            // there is already a pointer, remove it and notify the clients
            // of the change
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.pointer = Some(pointer.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        pointer
    }

    /// Remove the pointer capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_pointer(&mut self) {
        if self.pointer.is_some() {
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Adds the keyboard capability to this seat
    ///
    /// You are provided a `KbdHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// You also provide a Model/Layout/Variant/Options specification of the
    /// keymap to be used for this keyboard, as well as any repeat-info that
    /// will be forwarded to the clients.
    ///
    /// Calling this method on a seat that already has a keyboard capability
    /// will overwrite it, and will be seen by the clients as if the
    /// keyboard was unplugged and a new one was plugged.
    pub fn add_keyboard(
        &mut self, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_delay: i32,
        repeat_rate: i32,
    ) -> Result<KeyboardHandle, KeyboardError> {
        let keyboard = self::keyboard::create_keyboard_handler(
            "evdev", // we need this one
            model,
            layout,
            variant,
            options,
            repeat_delay,
            repeat_rate,
            &self.log,
        )?;
        if self.keyboard.is_some() {
            // there is already a keyboard, remove it and notify the clients
            // of the change
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.keyboard = Some(keyboard.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        Ok(keyboard)
    }

    /// Remove the keyboard capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_keyboard(&mut self) {
        if self.keyboard.is_some() {
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Cleanup internal states from old resources
    ///
    /// Deletes all remnnant of ressources from clients that
    /// are now disconnected.
    ///
    /// It can be wise to run this from time to time.
    pub fn cleanup(&mut self) {
        if let Some(ref pointer) = self.pointer {
            pointer.cleanup_old_pointers();
        }
        if let Some(ref kbd) = self.keyboard {
            kbd.cleanup_old_kbds();
        }
        self.known_seats.retain(|s| s.status() == Liveness::Alive);
    }

    fn compute_caps(&self) -> wl_seat::Capability {
        let mut caps = wl_seat::Capability::empty();
        if self.pointer.is_some() {
            caps |= wl_seat::Capability::Pointer;
        }
        if self.keyboard.is_some() {
            caps |= wl_seat::Capability::Keyboard;
        }
        caps
    }
}

fn seat_global_bind(
    evlh: &mut EventLoopHandle, token: &mut StateToken<Seat>, _: &Client, seat: wl_seat::WlSeat
) {
    evlh.register(&seat, seat_implementation(), token.clone(), None);
    let seat_mgr = evlh.state().get_mut(token);
    if seat.version() >= 2 {
        seat.name(seat_mgr.name.clone());
    }
    seat.capabilities(seat_mgr.compute_caps());
    seat_mgr.known_seats.push(seat);
}

fn seat_implementation() -> wl_seat::Implementation<StateToken<Seat>> {
    wl_seat::Implementation {
        get_pointer: |evlh, token, _, _, pointer| {
            evlh.register(&pointer, pointer_implementation(), (), None);
            if let Some(ref ptr_handle) = evlh.state().get(token).pointer {
                ptr_handle.new_pointer(pointer);
            } else {
                // we should send a protocol error... but the protocol does not allow
                // us, so this pointer will just remain inactive ¯\_(ツ)_/¯
            }
        },
        get_keyboard: |evlh, token, _, _, keyboard| {
            evlh.register(&keyboard, keyboard_implementation(), (), None);
            if let Some(ref kbd_handle) = evlh.state().get(token).keyboard {
                kbd_handle.new_kbd(keyboard);
            } else {
                // same, should error but cant
            }
        },
        get_touch: |_evlh, _token, _, _, _touch| {
            // TODO
        },
        release: |_, _, _, _| {},
    }
}

fn pointer_implementation() -> wl_pointer::Implementation<()> {
    wl_pointer::Implementation {
        set_cursor: |_, _, _, _, _, _, _, _| {},
        release: |_, _, _, _| {},
    }
}

fn keyboard_implementation() -> wl_keyboard::Implementation<()> {
    wl_keyboard::Implementation {
        release: |_, _, _, _| {},
    }
}
<commit_msg>Reexport ModifiersState to make it publically accessible<commit_after>//! Seat global utilities
//!
//! This module provides you with utilities for handling the seat globals
//! and the associated input wayland objects.
//!
//! ## How to use it
//!
//! ### Initialization
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//!
//! use smithay::wayland::seat::Seat;
//!
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! // insert the seat:
//! let (seat_state_token, seat_global) = Seat::new(
//!     &mut event_loop,
//!     "seat-0".into(), // the name of the seat, will be advertize to clients
//!     None /* insert a logger here*/
//! );
//! # }
//! ```
//!
//! ### Run usage
//!
//! Once the seat is initialized, you can add capabilities to it.
//!
//! Currently, only pointer and keyboard capabilities are supported by
//! smithay.
//!
//! You can add these capabilities via methods of the `Seat` struct that was
//! inserted in the event loop, that you can retreive via its token:
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//! #
//! # use smithay::wayland::seat::Seat;
//! #
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! # let (seat_state_token, seat_global) = Seat::new(
//! #     &mut event_loop,
//! #     "seat-0".into(), // the name of the seat, will be advertize to clients
//! #     None /* insert a logger here*/
//! # );
//! let pointer_handle = event_loop.state().get_mut(&seat_state_token).add_pointer();
//! # }
//! ```
//!
//! These handles can be cloned and sent accross thread, so you can keep one around
//! in your event-handling code to forward inputs to your clients.

mod keyboard;
mod pointer;

pub use self::keyboard::{Error as KeyboardError, KeyboardHandle, ModifiersState};
pub use self::pointer::PointerHandle;
use wayland_server::{Client, EventLoopHandle, Global, Liveness, Resource, StateToken};
use wayland_server::protocol::{wl_keyboard, wl_pointer, wl_seat};

/// Internal data of a seat global
///
/// This struct gives you access to the control of the
/// capabilities of the associated seat.
///
/// It is directly inserted in the event loop by its `new` method.
///
/// See module-level documentation for details of use.
pub struct Seat {
    log: ::slog::Logger,
    name: String,
    pointer: Option<PointerHandle>,
    keyboard: Option<KeyboardHandle>,
    known_seats: Vec<wl_seat::WlSeat>,
}

impl Seat {
    /// Create a new seat global
    ///
    /// A new seat global is created with given name and inserted
    /// into this event loop.
    ///
    /// You are provided with the state token to retrieve it (allowing
    /// you to add or remove capabilities from it), and the global handle,
    /// in case you want to remove it.
    pub fn new<L>(
        evlh: &mut EventLoopHandle, name: String, logger: L
    ) -> (StateToken<Seat>, Global<wl_seat::WlSeat, StateToken<Seat>>)
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = ::slog_or_stdlog(logger);
        let seat = Seat {
            log: log.new(o!("smithay_module" => "seat_handler", "seat_name" => name.clone())),
            name: name,
            pointer: None,
            keyboard: None,
            known_seats: Vec::new(),
        };
        let token = evlh.state().insert(seat);
        // TODO: support version 5 (axis)
        let global = evlh.register_global(4, seat_global_bind, token.clone());
        (token, global)
    }

    /// Adds the pointer capability to this seat
    ///
    /// You are provided a `PointerHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// Calling this method on a seat that already has a pointer capability
    /// will overwrite it, and will be seen by the clients as if the
    /// mouse was unplugged and a new one was plugged.
    pub fn add_pointer(&mut self) -> PointerHandle {
        let pointer = self::pointer::create_pointer_handler();
        if self.pointer.is_some() {
            // there is already a pointer, remove it and notify the clients
            // of the change
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.pointer = Some(pointer.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        pointer
    }

    /// Remove the pointer capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_pointer(&mut self) {
        if self.pointer.is_some() {
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Adds the keyboard capability to this seat
    ///
    /// You are provided a `KbdHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// You also provide a Model/Layout/Variant/Options specification of the
    /// keymap to be used for this keyboard, as well as any repeat-info that
    /// will be forwarded to the clients.
    ///
    /// Calling this method on a seat that already has a keyboard capability
    /// will overwrite it, and will be seen by the clients as if the
    /// keyboard was unplugged and a new one was plugged.
    pub fn add_keyboard(
        &mut self, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_delay: i32,
        repeat_rate: i32,
    ) -> Result<KeyboardHandle, KeyboardError> {
        let keyboard = self::keyboard::create_keyboard_handler(
            "evdev", // we need this one
            model,
            layout,
            variant,
            options,
            repeat_delay,
            repeat_rate,
            &self.log,
        )?;
        if self.keyboard.is_some() {
            // there is already a keyboard, remove it and notify the clients
            // of the change
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.keyboard = Some(keyboard.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        Ok(keyboard)
    }

    /// Remove the keyboard capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_keyboard(&mut self) {
        if self.keyboard.is_some() {
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Cleanup internal states from old resources
    ///
    /// Deletes all remnnant of ressources from clients that
    /// are now disconnected.
    ///
    /// It can be wise to run this from time to time.
    pub fn cleanup(&mut self) {
        if let Some(ref pointer) = self.pointer {
            pointer.cleanup_old_pointers();
        }
        if let Some(ref kbd) = self.keyboard {
            kbd.cleanup_old_kbds();
        }
        self.known_seats.retain(|s| s.status() == Liveness::Alive);
    }

    fn compute_caps(&self) -> wl_seat::Capability {
        let mut caps = wl_seat::Capability::empty();
        if self.pointer.is_some() {
            caps |= wl_seat::Capability::Pointer;
        }
        if self.keyboard.is_some() {
            caps |= wl_seat::Capability::Keyboard;
        }
        caps
    }
}

fn seat_global_bind(
    evlh: &mut EventLoopHandle, token: &mut StateToken<Seat>, _: &Client, seat: wl_seat::WlSeat
) {
    evlh.register(&seat, seat_implementation(), token.clone(), None);
    let seat_mgr = evlh.state().get_mut(token);
    if seat.version() >= 2 {
        seat.name(seat_mgr.name.clone());
    }
    seat.capabilities(seat_mgr.compute_caps());
    seat_mgr.known_seats.push(seat);
}

fn seat_implementation() -> wl_seat::Implementation<StateToken<Seat>> {
    wl_seat::Implementation {
        get_pointer: |evlh, token, _, _, pointer| {
            evlh.register(&pointer, pointer_implementation(), (), None);
            if let Some(ref ptr_handle) = evlh.state().get(token).pointer {
                ptr_handle.new_pointer(pointer);
            } else {
                // we should send a protocol error... but the protocol does not allow
                // us, so this pointer will just remain inactive ¯\_(ツ)_/¯
            }
        },
        get_keyboard: |evlh, token, _, _, keyboard| {
            evlh.register(&keyboard, keyboard_implementation(), (), None);
            if let Some(ref kbd_handle) = evlh.state().get(token).keyboard {
                kbd_handle.new_kbd(keyboard);
            } else {
                // same, should error but cant
            }
        },
        get_touch: |_evlh, _token, _, _, _touch| {
            // TODO
        },
        release: |_, _, _, _| {},
    }
}

fn pointer_implementation() -> wl_pointer::Implementation<()> {
    wl_pointer::Implementation {
        set_cursor: |_, _, _, _, _, _, _, _| {},
        release: |_, _, _, _| {},
    }
}

fn keyboard_implementation() -> wl_keyboard::Implementation<()> {
    wl_keyboard::Implementation {
        release: |_, _, _, _| {},
    }
}
<|endoftext|>


<commit_before>
struct median_filter_t<'a> {
    window: &'a mut Vec<u8>,
    input: &'a mut Vec<u8>,
    hole: i64,
    max: i64,
}

fn median_init(f: &mut median_filter_t, w_size: usize){
    f.max = 0;
    f.hole = 0;

    *f.window = Vec::with_capacity(w_size);
    *f.input = Vec::with_capacity(w_size/2);
}

fn median_close_hole(f: &mut median_filter_t) {
    while f.hole < f.max - 1 {
        let i: usize = f.hole as usize;
        f.window[i] = f.window[i + 1];
        f.hole += 1;
    }

    if f.hole == f.max - 1 {
        f.max = f.max - 1;
    }
}

fn media_remove(f: &mut median_filter_t, v: u8) {
    median_close_hole(f);

    let mut lo: i64 = 0;
    let mut hi: i64 = f.max - 1;

    f.hole = (hi / 2) as i64;

    while lo <= hi {
        let i: usize = f.hole as usize;
        if v > f.window[i] {
            lo = f.hole + 1;
        } else if v < f.window[i] {
            hi = f.hole - 1;
        } else {
            break;
        }
        f.hole = (lo + hi) / 2;
    }
}

fn median_add(f: &mut median_filter_t, v: u8) {
    if f.hole == f.max {
        f.max += 1;
    }

    let mut i: usize = f.hole as usize;
    while (f.hole > 0) && (f.window[i] > v) {
        f.window[i] = f.window[i-1];
        f.hole -= 1;
        i = f.hole as usize;
    }

    i = f.hole as usize;

    while (f.hole < f.max - 1) && (f.window[i+1] < v) {
        f.window[i] = f.window[i+1];
        f.hole += 1;
        i = f.hole as usize;
    }

    f.window[i] = v;
    f.hole = f.max;
}

fn median_get(f: &mut median_filter_t) -> u8 {
    median_close_hole(f);

    if f.max == 0 {
        return 0;
    }

    if (f.max & 1i64) == 1 {
        let i: usize = f.max as usize;
        return f.window[(i-1)/2];
    } else {
        let i: usize = f.max as usize;
        return (f.window[(i-1)/2] + f.window[i/2]) / 2;
    }
}

fn main() {
    println!("Hello, world!");
}
<commit_msg>add prototype of the last function<commit_after>
struct median_filter_t<'a> {
    window: &'a mut Vec<u8>,
    input: &'a mut Vec<u8>,
    hole: i64,
    max: i64,
}

fn median_init(f: &mut median_filter_t, w_size: usize){
    f.max = 0;
    f.hole = 0;

    *f.window = Vec::with_capacity(w_size);
    *f.input = Vec::with_capacity(w_size/2);
}

fn median_close_hole(f: &mut median_filter_t) {
    while f.hole < f.max - 1 {
        let i: usize = f.hole as usize;
        f.window[i] = f.window[i + 1];
        f.hole += 1;
    }

    if f.hole == f.max - 1 {
        f.max = f.max - 1;
    }
}

fn media_remove(f: &mut median_filter_t, v: u8) {
    median_close_hole(f);

    let mut lo: i64 = 0;
    let mut hi: i64 = f.max - 1;

    f.hole = (hi / 2) as i64;

    while lo <= hi {
        let i: usize = f.hole as usize;
        if v > f.window[i] {
            lo = f.hole + 1;
        } else if v < f.window[i] {
            hi = f.hole - 1;
        } else {
            break;
        }
        f.hole = (lo + hi) / 2;
    }
}

fn median_add(f: &mut median_filter_t, v: u8) {
    if f.hole == f.max {
        f.max += 1;
    }

    let mut i: usize = f.hole as usize;
    while (f.hole > 0) && (f.window[i] > v) {
        f.window[i] = f.window[i-1];
        f.hole -= 1;
        i = f.hole as usize;
    }

    i = f.hole as usize;

    while (f.hole < f.max - 1) && (f.window[i+1] < v) {
        f.window[i] = f.window[i+1];
        f.hole += 1;
        i = f.hole as usize;
    }

    f.window[i] = v;
    f.hole = f.max;
}

fn median_get(f: &mut median_filter_t) -> u8 {
    median_close_hole(f);

    if f.max == 0 {
        return 0;
    }

    if (f.max & 1i64) == 1 {
        let i: usize = f.max as usize;
        return f.window[(i-1)/2];
    } else {
        let i: usize = f.max as usize;
        return (f.window[(i-1)/2] + f.window[i/2]) / 2;
    }
}

fn median_filter(input: &mut Vec<u8>, size: i64, w_size: i64) -> i32 {

    return 0;
}

fn main() {
    println!("Hello, world!");
}
<|endoftext|>


<commit_before>//! Set up resource content for game.

use std::str::FromStr;
use std::collections::HashMap;
use std::iter::FromIterator;
use glium;
use image::{self, GenericImage};
use euclid::Point2D;
use vitral_atlas;
use vitral;
use calx_color::Rgba;
use calx_color::color::*;
use calx_resource::ResourceStore;
use world::BrushBuilder;
use backend::{Backend, Font};

impl_store!(FONT, String, Font);

fn to_image_buffer<I>(image: &I) -> vitral::ImageBuffer
    where I: image::GenericImage<Pixel = image::Rgba<u8>>
{
    vitral::ImageBuffer::from_iter(image.width(),
                                   image.height(),
                                   &mut image.pixels().map(|p| unsafe {
                                       ::std::mem::transmute::<image::Rgba<u8>, u32>(p.2)
                                   }))
}

pub fn font(display: &glium::Display, backend: &mut Backend) {
    use tilesheet::tilesheet_bounds;

    const PATH: &'static str = "display/assets/font.png";

    let mut font_sheet = image::open(PATH).expect(&format!("Font sheet '{}' not found", PATH));

    // Use the tilesheet machinery to extract individual glyph boundaries from the special font
    // tilesheet.
    let bounds = tilesheet_bounds(&font_sheet);

    // Construct Vitral ImageBuffers of the glyphs.
    let glyphs: Vec<vitral::ImageBuffer> = bounds.iter()
                                                 .map(|rect| {
                                                     to_image_buffer(&font_sheet.sub_image(
                rect.origin.x as u32, rect.origin.y as u32,
                rect.size.width as u32, rect.size.height as u32))
                                                 })
                                                 .collect();

    assert!(glyphs.len() == 96, "Unexpected number of font glyphs");
    let font_height = glyphs[0].size.height;

    // Build the font atlas and map the items to CharData.
    let items: Vec<vitral::CharData<usize>> = vitral_atlas::build(&glyphs, 2048, |img| {
                                                  backend.make_texture(display, img)
                                              })
                                                  .expect("Atlas construction failed")
                                                  .into_iter()
                                                  .map(|image| {
                                                      let advance = image.size.width as f32;
                                                      vitral::CharData {
                                                          image: image,
                                                          draw_offset:
                                                              Point2D::new(0.0, font_height as f32),
                                                          advance: advance,
                                                      }
                                                  })
                                                  .collect();

    let font = Font(vitral::FontData {
        chars: HashMap::from_iter((32u8..128).map(|c| c as char).zip(items.into_iter())),
        height: font_height as f32,
    });

    Font::insert_resource("default".to_string(), font);
}

/// Init the static brush assets.
pub fn brushes(display: &glium::Display, backend: &mut Backend) {
    // FIXME: This API needs to be more ergonomic. In particular, need better syntactic cues for
    // brush boundries.

    BrushBuilder::new()
        .file("display/assets/floors.png")
        ////
        .tile(0, 0)
        .brush("blank_floor")
        ////
        .color(DARKGREEN)
        .tile(32, 0)
        .brush("grass")
        ////
        .color(DARKGREEN)
        .tile(64, 0)
        .brush("grass2")
        ////
        .color(SLATEGRAY)
        .tile(32, 0)
        .brush("ground")
        ////
        .color(SLATEGRAY)
        .tile(32, 0)
        .brush("corridor")
        ////
        .color(ROYALBLUE)
        .tile(96, 0)
        .brush("water")
        ////
        .color(RED)
        .tile(96, 0)
        .brush("magma")
        ////
        .file("display/assets/portals.png")
        ////
        .color(LIGHTCYAN)
        .tile(0, 0)
        .frame()
        .tile(32, 0)
        .frame()
        .tile(64, 0)
        .frame()
        .tile(96, 0)
        .frame()
        .tile(128, 0)
        .frame()
        .tile(160, 0)
        .frame()
        .tile(192, 0)
        .frame()
        .tile(224, 0)
        .frame()
        .tile(256, 0)
        .frame()
        .tile(288, 0)
        .frame()
        .tile(320, 0)
        .frame()
        .tile(352, 0)
        .frame()
        .tile(384, 0)
        .brush("gate")
        ////
        .file("display/assets/props.png")
        ////
        .color(RED)
        .tile(0, 0)
        .brush("cursor")
        .color(RED)
        .tile(32, 0)
        .brush("cursor_top")
        .color(Rgba::from_str("#fa08").unwrap())
        .tile(0, 0)
        .brush("portal") // TODO: This thing is a temporary display helper for mapedit, maybe remove when can?
        ////
        .color(SADDLEBROWN)
        .tile(160, 64)
        .color(GREEN)
        .tile(192, 64)
        .brush("tree")
        ////
        .file("display/assets/walls.png")
        ////
        .color(LIGHTSLATEGRAY)
        .wall(0, 0, 32, 0)
        .brush("wall")

        .color(LIGHTSLATEGRAY)
        .wall(0, 0, 96, 0)
        .brush("open_door")

        // XXX: Wall helper function doesn't handle complex splats.
        //
        .color(SADDLEBROWN)
        .splat(128, 0, 16, 32).offset(16, 16)
        .color(LIGHTSLATEGRAY)
        .splat(0, 0, 16, 32).offset(16, 16)

        .frame()
        .color(SADDLEBROWN)
        .splat(128 + 16, 0, 16, 32).offset(0, 16)
        .color(LIGHTSLATEGRAY)
        .splat(16, 0, 16, 32).offset(0, 16)

        .frame()
        .color(SADDLEBROWN)
        .splat(160, 0, 16, 32).offset(16, 16)
        .color(LIGHTSLATEGRAY)
        .splat(96, 0, 16, 32).offset(16, 16)

        .frame()
        .color(SADDLEBROWN)
        .splat(160 + 16, 0, 16, 32).offset(0, 16)
        .color(LIGHTSLATEGRAY)
        .splat(96 + 16, 0, 16, 32).offset(0, 16)

        .brush("door")
        // Door finally ends here.

        ////
        .file("display/assets/blobs.png")
        ////
        .color(BLACK)
        .blob(0, 64, 0, 96, 0, 128)
        .brush("solid-blob")
        .color(DARKGOLDENROD)
        .blob(0, 0, 0, 32, 0, 160)
        .brush("rock")
        ////
        .file("display/assets/mobs.png")
        .color(AZURE)
        .tile(0, 0)
        .bob()
        .brush("player")
        .color(GREEN)
        .tile(32, 0)
        .bob()
        .brush("snake")
        .color(OLIVE)
        .tile(64, 0)
        .bob()
        .brush("dreg")
        ////
        .finish(|img| backend.make_texture(&display, img));
}
<commit_msg>Rearrange for nicer formatting<commit_after>//! Set up resource content for game.

use std::str::FromStr;
use std::collections::HashMap;
use std::iter::FromIterator;
use glium;
use image::{self, GenericImage};
use euclid::Point2D;
use vitral_atlas;
use vitral;
use calx_color::Rgba;
use calx_color::color::*;
use calx_resource::ResourceStore;
use world::BrushBuilder;
use backend::{Backend, Font};

impl_store!(FONT, String, Font);

fn to_image_buffer<I>(image: &I) -> vitral::ImageBuffer
    where I: image::GenericImage<Pixel = image::Rgba<u8>>
{
    vitral::ImageBuffer::from_iter(image.width(),
                                   image.height(),
                                   &mut image.pixels().map(|p| unsafe {
                                       ::std::mem::transmute::<image::Rgba<u8>, u32>(p.2)
                                   }))
}

pub fn font(display: &glium::Display, backend: &mut Backend) {
    use tilesheet::tilesheet_bounds;

    const PATH: &'static str = "display/assets/font.png";

    let mut font_sheet = image::open(PATH).expect(&format!("Font sheet '{}' not found", PATH));

    // Use the tilesheet machinery to extract individual glyph boundaries from the special font
    // tilesheet.
    let bounds = tilesheet_bounds(&font_sheet);

    // Construct Vitral ImageBuffers of the glyphs.
    let glyphs: Vec<vitral::ImageBuffer> = bounds.iter()
                                                 .map(|rect| {
                                                     to_image_buffer(&font_sheet.sub_image(
                rect.origin.x as u32, rect.origin.y as u32,
                rect.size.width as u32, rect.size.height as u32))
                                                 })
                                                 .collect();

    assert!(glyphs.len() == 96, "Unexpected number of font glyphs");
    let font_height = glyphs[0].size.height;

    // Build the font atlas and map the items to CharData.
    let items = vitral_atlas::build(&glyphs, 2048, |img| backend.make_texture(display, img))
                    .expect("Atlas construction failed")
                    .into_iter()
                    .map(|image| {
                        let advance = image.size.width as f32;
                        vitral::CharData {
                            image: image,
                            draw_offset: Point2D::new(0.0, font_height as f32),
                            advance: advance,
                        }
                    })
                    .collect::<Vec<vitral::CharData<usize>>>();

    let font = Font(vitral::FontData {
        chars: HashMap::from_iter((32u8..128).map(|c| c as char).zip(items.into_iter())),
        height: font_height as f32,
    });

    Font::insert_resource("default".to_string(), font);
}

/// Init the static brush assets.
pub fn brushes(display: &glium::Display, backend: &mut Backend) {
    // FIXME: This API needs to be more ergonomic. In particular, need better syntactic cues for
    // brush boundries.

    BrushBuilder::new()
        .file("display/assets/floors.png")
        ////
        .tile(0, 0)
        .brush("blank_floor")
        ////
        .color(DARKGREEN)
        .tile(32, 0)
        .brush("grass")
        ////
        .color(DARKGREEN)
        .tile(64, 0)
        .brush("grass2")
        ////
        .color(SLATEGRAY)
        .tile(32, 0)
        .brush("ground")
        ////
        .color(SLATEGRAY)
        .tile(32, 0)
        .brush("corridor")
        ////
        .color(ROYALBLUE)
        .tile(96, 0)
        .brush("water")
        ////
        .color(RED)
        .tile(96, 0)
        .brush("magma")
        ////
        .file("display/assets/portals.png")
        ////
        .color(LIGHTCYAN)
        .tile(0, 0)
        .frame()
        .tile(32, 0)
        .frame()
        .tile(64, 0)
        .frame()
        .tile(96, 0)
        .frame()
        .tile(128, 0)
        .frame()
        .tile(160, 0)
        .frame()
        .tile(192, 0)
        .frame()
        .tile(224, 0)
        .frame()
        .tile(256, 0)
        .frame()
        .tile(288, 0)
        .frame()
        .tile(320, 0)
        .frame()
        .tile(352, 0)
        .frame()
        .tile(384, 0)
        .brush("gate")
        ////
        .file("display/assets/props.png")
        ////
        .color(RED)
        .tile(0, 0)
        .brush("cursor")
        .color(RED)
        .tile(32, 0)
        .brush("cursor_top")
        .color(Rgba::from_str("#fa08").unwrap())
        .tile(0, 0)
        .brush("portal") // TODO: This thing is a temporary display helper for mapedit, maybe remove when can?
        ////
        .color(SADDLEBROWN)
        .tile(160, 64)
        .color(GREEN)
        .tile(192, 64)
        .brush("tree")
        ////
        .file("display/assets/walls.png")
        ////
        .color(LIGHTSLATEGRAY)
        .wall(0, 0, 32, 0)
        .brush("wall")

        .color(LIGHTSLATEGRAY)
        .wall(0, 0, 96, 0)
        .brush("open_door")

        // XXX: Wall helper function doesn't handle complex splats.
        //
        .color(SADDLEBROWN)
        .splat(128, 0, 16, 32).offset(16, 16)
        .color(LIGHTSLATEGRAY)
        .splat(0, 0, 16, 32).offset(16, 16)

        .frame()
        .color(SADDLEBROWN)
        .splat(128 + 16, 0, 16, 32).offset(0, 16)
        .color(LIGHTSLATEGRAY)
        .splat(16, 0, 16, 32).offset(0, 16)

        .frame()
        .color(SADDLEBROWN)
        .splat(160, 0, 16, 32).offset(16, 16)
        .color(LIGHTSLATEGRAY)
        .splat(96, 0, 16, 32).offset(16, 16)

        .frame()
        .color(SADDLEBROWN)
        .splat(160 + 16, 0, 16, 32).offset(0, 16)
        .color(LIGHTSLATEGRAY)
        .splat(96 + 16, 0, 16, 32).offset(0, 16)

        .brush("door")
        // Door finally ends here.

        ////
        .file("display/assets/blobs.png")
        ////
        .color(BLACK)
        .blob(0, 64, 0, 96, 0, 128)
        .brush("solid-blob")
        .color(DARKGOLDENROD)
        .blob(0, 0, 0, 32, 0, 160)
        .brush("rock")
        ////
        .file("display/assets/mobs.png")
        .color(AZURE)
        .tile(0, 0)
        .bob()
        .brush("player")
        .color(GREEN)
        .tile(32, 0)
        .bob()
        .brush("snake")
        .color(OLIVE)
        .tile(64, 0)
        .bob()
        .brush("dreg")
        ////
        .finish(|img| backend.make_texture(&display, img));
}
<|endoftext|>


<commit_before>// Copyright 2015 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use error::Error;
use regex::Regex;
use Result;
use std::{process, str};
use std::io::prelude::*;
use std::fs::File;
use target::default_base as default;
use telemetry::Netif;

pub fn file_get_owner(path: &str) -> Result<FileOwner> {
    Ok(FileOwner {
        user_name: try!(default::file_stat(path, vec!["-c", "%U"])),
        user_pid: try!(default::file_stat(path, vec!["-c", "%u"])).parse::<u64>().unwrap(),
        group_name: try!(default::file_stat(path, vec!["-c", "%G"])),
        group_pid: try!(default::file_stat(path, vec!["-c", "%g"])).parse::<u64>().unwrap()
    })
}

pub fn file_get_mode(path: &str) -> Result<u16> {
    Ok(try!(default::file_stat(path, vec!["-c", "%a"])).parse::<u16>().unwrap())
}

pub fn memory() -> Result<u64> {
    let output = process::Command::new("/usr/bin/free").arg("-b").output().unwrap();

    if !output.status.success() {
        return Err(Error::Generic("Could not determine memory".to_string()));
    }

    let regex = Regex::new(r"(?m)^Mem:\s+([0-9]+)").unwrap();
    let capture = regex.captures(try!(str::from_utf8(&output.stdout)).trim());

    if capture.is_some() {
        Ok(capture.unwrap().at(1).unwrap().parse::<u64>().unwrap())
    } else {
        Err(Error::Generic("Invalid memory output".to_string()))
    }
}

pub fn cpu_vendor() -> Result<String> {
    get_cpu_item("vendor_id")
}

pub fn cpu_brand_string() -> Result<String> {
    get_cpu_item("model name")
}

pub fn cpu_cores() -> Result<u32> {
    Ok(try!(try!(get_cpu_item("cpu cores")).parse::<u32>()))
}

fn get_cpu_item(item: &str) -> Result<String> {
    // XXX This result should be cached
    let mut cpuinfo_f = try!(File::open("/proc/cpuinfo"));
    let mut cpuinfo = String::new();
    try!(cpuinfo_f.read_to_string(&mut cpuinfo));

    let pattern = format!(r"(?m)^{}\s+: (.+)$", item);
    let regex = Regex::new(&pattern).unwrap();
    let capture = regex.captures(&cpuinfo);

    if capture.is_some() {
        Ok(capture.unwrap().at(1).unwrap().to_string())
    } else {
        Err(Error::Generic(format!("Could not find CPU item: {}", item)))
    }
}

pub fn net() -> Result<Vec<Netif>> {
    let if_pattern = r"(?m)^(?P<if>[a-z0-9]+)\s+Link encap:(Ethernet|Local Loopback)(?P<content>(?s).+?)\n\n";
    let kv_pattern = r"^\s+(?P<key>[A-Za-z0-9]+)(?:\s|:)(?P<value>.+)";
    let ipv4_pattern = r"^addr:(?P<ip>(?:[0-9]{1,3}\.){3}[0-9]{1,3})\s+(?:Bcast:[0-9.]{7,15}\s+)?Mask:(?P<mask>(?:[0-9]{1,3}\.){3}[0-9]{1,3})";
    let ipv6_pattern = r"^addr:\s*(?P<ip>(?:[a-f0-9]{4}::(?:[a-f0-9]{1,4}:){3}[a-f0-9]{1,4})|(?:::1))/(?P<prefix>[0-9]+)\s+Scope:(?P<scope>[A-Za-z0-9]+)";
    default::parse_net(if_pattern, kv_pattern, ipv4_pattern, ipv6_pattern)
}

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

    #[test]
    fn test_memory() {
        // XXX Not a proper test. Requires mocking.
        assert!(memory().is_ok());
    }

    #[test]
    fn test_cpu_vendor() {
        // XXX Not a proper test. Requires mocking.
        assert!(cpu_vendor().is_ok());
    }

    #[test]
    fn test_cpu_brand_string() {
        // XXX Not a proper test. Requires mocking.
        assert!(cpu_brand_string().is_ok());
    }

    #[test]
    fn test_cpu_cores() {
        // XXX Not a proper test. Requires mocking.
        assert!(cpu_cores().is_ok());
    }

    #[test]
    fn test_get_cpu_item_fail() {
        assert!(get_cpu_item("moocow").is_err());
    }

    #[test]
    fn test_net() {
        // XXX Not a proper test. Requires mocking.
        assert!(net().is_ok());
    }
}
<commit_msg>Fixed bug in linux target<commit_after>// Copyright 2015 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use error::Error;
use file::FileOwner;
use regex::Regex;
use Result;
use std::{process, str};
use std::io::prelude::*;
use std::fs::File;
use target::default_base as default;
use telemetry::Netif;

pub fn file_get_owner(path: &str) -> Result<FileOwner> {
    Ok(FileOwner {
        user_name: try!(default::file_stat(path, vec!["-c", "%U"])),
        user_uid: try!(default::file_stat(path, vec!["-c", "%u"])).parse::<u64>().unwrap(),
        group_name: try!(default::file_stat(path, vec!["-c", "%G"])),
        group_gid: try!(default::file_stat(path, vec!["-c", "%g"])).parse::<u64>().unwrap()
    })
}

pub fn file_get_mode(path: &str) -> Result<u16> {
    Ok(try!(default::file_stat(path, vec!["-c", "%a"])).parse::<u16>().unwrap())
}

pub fn memory() -> Result<u64> {
    let output = process::Command::new("/usr/bin/free").arg("-b").output().unwrap();

    if !output.status.success() {
        return Err(Error::Generic("Could not determine memory".to_string()));
    }

    let regex = Regex::new(r"(?m)^Mem:\s+([0-9]+)").unwrap();
    let capture = regex.captures(try!(str::from_utf8(&output.stdout)).trim());

    if capture.is_some() {
        Ok(capture.unwrap().at(1).unwrap().parse::<u64>().unwrap())
    } else {
        Err(Error::Generic("Invalid memory output".to_string()))
    }
}

pub fn cpu_vendor() -> Result<String> {
    get_cpu_item("vendor_id")
}

pub fn cpu_brand_string() -> Result<String> {
    get_cpu_item("model name")
}

pub fn cpu_cores() -> Result<u32> {
    Ok(try!(try!(get_cpu_item("cpu cores")).parse::<u32>()))
}

fn get_cpu_item(item: &str) -> Result<String> {
    // XXX This result should be cached
    let mut cpuinfo_f = try!(File::open("/proc/cpuinfo"));
    let mut cpuinfo = String::new();
    try!(cpuinfo_f.read_to_string(&mut cpuinfo));

    let pattern = format!(r"(?m)^{}\s+: (.+)$", item);
    let regex = Regex::new(&pattern).unwrap();
    let capture = regex.captures(&cpuinfo);

    if capture.is_some() {
        Ok(capture.unwrap().at(1).unwrap().to_string())
    } else {
        Err(Error::Generic(format!("Could not find CPU item: {}", item)))
    }
}

pub fn net() -> Result<Vec<Netif>> {
    let if_pattern = r"(?m)^(?P<if>[a-z0-9]+)\s+Link encap:(Ethernet|Local Loopback)(?P<content>(?s).+?)\n\n";
    let kv_pattern = r"^\s+(?P<key>[A-Za-z0-9]+)(?:\s|:)(?P<value>.+)";
    let ipv4_pattern = r"^addr:(?P<ip>(?:[0-9]{1,3}\.){3}[0-9]{1,3})\s+(?:Bcast:[0-9.]{7,15}\s+)?Mask:(?P<mask>(?:[0-9]{1,3}\.){3}[0-9]{1,3})";
    let ipv6_pattern = r"^addr:\s*(?P<ip>(?:[a-f0-9]{4}::(?:[a-f0-9]{1,4}:){3}[a-f0-9]{1,4})|(?:::1))/(?P<prefix>[0-9]+)\s+Scope:(?P<scope>[A-Za-z0-9]+)";
    default::parse_net(if_pattern, kv_pattern, ipv4_pattern, ipv6_pattern)
}

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

    #[test]
    fn test_memory() {
        // XXX Not a proper test. Requires mocking.
        assert!(memory().is_ok());
    }

    #[test]
    fn test_cpu_vendor() {
        // XXX Not a proper test. Requires mocking.
        assert!(cpu_vendor().is_ok());
    }

    #[test]
    fn test_cpu_brand_string() {
        // XXX Not a proper test. Requires mocking.
        assert!(cpu_brand_string().is_ok());
    }

    #[test]
    fn test_cpu_cores() {
        // XXX Not a proper test. Requires mocking.
        assert!(cpu_cores().is_ok());
    }

    #[test]
    fn test_get_cpu_item_fail() {
        assert!(get_cpu_item("moocow").is_err());
    }

    #[test]
    fn test_net() {
        // XXX Not a proper test. Requires mocking.
        assert!(net().is_ok());
    }
}
<|endoftext|>


<commit_before>//! Raw and high-level instruction abstractions

use std::num::{FromPrimitive, ToPrimitive};

/// A register index/name
///
/// There are 16 registers, `V0`..`VF`
#[derive(FromPrimitive, Copy, Debug)]
pub enum Register {
    V0 = 0x0,
    V1 = 0x1,
    V2 = 0x2,
    V3 = 0x3,
    V4 = 0x4,
    V5 = 0x5,
    V6 = 0x6,
    V7 = 0x7,
    V8 = 0x8,
    V9 = 0x9,
    VA = 0xA,
    VB = 0xB,
    VC = 0xC,
    VD = 0xD,
    VE = 0xE,
    VF = 0xF,
}

impl ToPrimitive for Register {
    fn to_i64(&self) -> Option<i64> {
        Some(*self as i64)
    }

    fn to_u64(&self) -> Option<u64> {
        Some(*self as u64)
    }
}

/// First register in an opcode
pub type Vx = Register;
/// Second register in an opcode
pub type Vy = Register;

/// A byte
///
/// Valid values are within `0x0` .. `0xFF`.
pub type Byte = u8;

/// A nibble (hex digit)
///
/// Valid values are within `0x0` .. `0xF`.
#[derive(Copy, Debug)]
pub struct Nibble {
    pub bits: u8,
}

impl Nibble {
    /// Creates a new `Nibble`, ignoring any high bits
    pub fn new(bits: u8) -> Nibble {
        Nibble { bits: bits & 0x0F }
    }
}

/// Absolute memory address
///
/// Valid addresses are within `0x0` .. `0xFFF`.
#[derive(Copy, Debug)]
pub struct Addr {
    pub bits: u16,
}

impl Addr {
    /// Creates a new `Addr`, ignoring any high bits
    pub fn new(bits: u16) -> Addr {
        Addr { bits: bits & 0x0FFF }
    }
}

/// Raw instruction
///
/// Helper around the raw bits, not necessarily a valid instruction.
#[derive(Copy)]
pub struct RawInstruction {
    bits: u16
}

impl RawInstruction {
    /// Creates a new raw instruction without any checks of the `bits`
    pub fn new(bits: u16) -> RawInstruction {
        RawInstruction{ bits: bits }
    }

    /// The *raw bits*
    #[allow(dead_code)]
    pub fn bits(&self) -> u16 {
        self.bits
    }

    /// The *address bits* part
    pub fn addr(&self) -> Addr {
        Addr::new(self.bits & 0x0FFF)
    }

    /// The *`Vx` register-index* part, i.e. `0xE` is `VE`
    pub fn x(&self) -> Vx {
        FromPrimitive::from_u8(((self.bits & 0x0F00) >> 8) as u8).unwrap()
    }

    /// The *`Vy` register-index* part, i.e. `0xE` is `VE`
    pub fn y(&self) -> Vy {
        FromPrimitive::from_u8(((self.bits & 0x00F0) >> 4) as u8).unwrap()
    }

    /// The *high nibble* part
    pub fn n_high(&self) -> Nibble {
        Nibble::new(((self.bits & 0xF000) >> 12) as u8)
    }

    /// The *low nibble* part
    pub fn n_low(&self) -> Nibble {
        Nibble::new((self.bits & 0x000F) as u8)
    }

    /// The *`k` byte* part
    pub fn k(&self) -> Byte {
        (self.bits & 0x00FF) as u8
    }
}

/// High-level instruction
///
/// A valid instruction that can be executed as-is.
#[derive(Copy,Debug)]
pub enum Instruction {
    Sys(Addr),              // 0nnn - SYS addr
    Clear,                  // 00E0 - CLS
    Return,                 // 00EE - RET
    Jump(Addr),             // 1nnn - JP addr
    Call(Addr),             // 2nnn - CALL addr
    SkipEqualK(Vx, Byte),   // 3xkk - SE Vx, byte
    SkipNotEqualK(Vx, Byte),// 4xkk - SNE Vx, byte
    SkipEqual(Vx, Vy),      // 5xy0 - SE Vx, Vy
    SetK(Vx, Byte),         // 6xkk - LD Vx, byte
    AddK(Vx, Byte),         // 7xkk - ADD Vx, byte
    Set(Vx, Vy),            // 8xy0 - LD Vx, Vy
    Or(Vx, Vy),             // 8xy1 - OR Vx, Vy
    And(Vx, Vy),            // 8xy2 - AND Vx, Vy
    XOr(Vx, Vy),            // 8xy3 - XOR Vx, Vy
    Add(Vx, Vy),            // 8xy4 - ADD Vx, Vy
    Sub(Vx, Vy),            // 8xy5 - SUB Vx, Vy
    ShiftRight(Vx, Vy),     // 8xy6 - SHR Vx {, Vy}
    SubInv(Vx, Vy),         // 8xy7 - SUBN Vx, Vy
    ShiftLeft(Vx, Vy),      // 8xyE - SHL Vx {, Vy}
    SkipNotEqual(Vx, Vy),   // 9xy0 - SNE Vx, Vy
    LoadI(Addr),            // Annn - LD I, addr
    LongJump(Addr),         // Bnnn - JP V0, addr
    Rand(Vx, Byte),         // Cxkk - RND Vx, byte
    Draw(Vx, Vy, Nibble),   // Dxyn - DRW Vx, Vy, nibble
    SkipPressed(Vx),        // Ex9E - SKP Vx
    SkipNotPressed(Vx),     // ExA1 - SKNP Vx
    GetTimer(Vx),           // Fx07 - LD Vx, DT
    WaitKey(Vx),            // Fx0A - LD Vx, K
    SetTimer(Vx),           // Fx15 - LD DT, Vx
    SetSoundTimer(Vx),      // Fx18 - LD ST, Vx
    AddToI(Vx),             // Fx1E - ADD I, Vx
    LoadHexGlyph(Vx),       // Fx29 - LD F, Vx
    StoreBCD(Vx),           // Fx33 - LD B, Vx
    StoreRegisters(Vx),     // Fx55 - LD [I], Vx
    LoadRegisters(Vx),      // Fx65 - LD Vx, [I]
    Unknown,
}

impl Instruction {
    /// Creates a new instruction from raw bits,
    /// or `Instruction::Unknown` if no valid match could be found
    pub fn from_raw(raw: &RawInstruction) -> Instruction {
        use self::Instruction::*;

        match raw.n_high().bits {
            0x0 => {
                match raw.k() {
                    0xE0 => Clear,
                    0xEE => Return,
                    _ => Sys(raw.addr())
                }
            },
            0x1 => Jump(raw.addr()),
            0x2 => Call(raw.addr()),
            0x3 => SkipEqualK(raw.x(), raw.k()),
            0x4 => SkipNotEqualK(raw.x(), raw.k()),
            0x5 => SkipEqual(raw.x(), raw.y()),
            0x6 => SetK(raw.x(), raw.k()),
            0x7 => AddK(raw.x(), raw.k()),
            0x8 => {
                match raw.n_low().bits {
                    0x0 => Set(raw.x(), raw.y()),
                    0x1 => Or(raw.x(), raw.y()),
                    0x2 => And(raw.x(), raw.y()),
                    0x3 => XOr(raw.x(), raw.y()),
                    0x4 => Add(raw.x(), raw.y()),
                    0x5 => Sub(raw.x(), raw.y()),
                    0x6 => ShiftRight(raw.x(), raw.y()),
                    0x7 => SubInv(raw.x(), raw.y()),
                    0xE => ShiftLeft(raw.x(), raw.y()),
                    _ => Unknown
                }
            },
            0x9 => SkipNotEqual(raw.x(), raw.y()),
            0xA => LoadI(raw.addr()),
            0xB => LongJump(raw.addr()),
            0xC => Rand(raw.x(), raw.k()),
            0xD => Draw(raw.x(), raw.y(), raw.n_low()),
            0xE => {
                match raw.k() {
                    0x9E => SkipPressed(raw.x()),
                    0xA1 => SkipNotPressed(raw.x()),
                    _ => Unknown,
                }
            },
            0xF => {
                match raw.k() {
                    0x07 => GetTimer(raw.x()),
                    0x0A => WaitKey(raw.x()),
                    0x15 => SetTimer(raw.x()),
                    0x18 => SetSoundTimer(raw.x()),
                    0x1E => AddToI(raw.x()),
                    0x29 => LoadHexGlyph(raw.x()),
                    0x33 => StoreBCD(raw.x()),
                    0x55 => StoreRegisters(raw.x()),
                    0x65 => LoadRegisters(raw.x()),
                    _ => Unknown,
                }
            }
            _ => Unknown
        }
    }
}
<commit_msg>Add rustdoc for `Instruction` variants<commit_after>//! Raw and high-level instruction abstractions

use std::num::{FromPrimitive, ToPrimitive};

/// A register index/name
///
/// There are 16 registers, `V0`..`VF`
#[derive(FromPrimitive, Copy, Debug)]
pub enum Register {
    V0 = 0x0,
    V1 = 0x1,
    V2 = 0x2,
    V3 = 0x3,
    V4 = 0x4,
    V5 = 0x5,
    V6 = 0x6,
    V7 = 0x7,
    V8 = 0x8,
    V9 = 0x9,
    VA = 0xA,
    VB = 0xB,
    VC = 0xC,
    VD = 0xD,
    VE = 0xE,
    VF = 0xF,
}

impl ToPrimitive for Register {
    fn to_i64(&self) -> Option<i64> {
        Some(*self as i64)
    }

    fn to_u64(&self) -> Option<u64> {
        Some(*self as u64)
    }
}

/// First register in an opcode
pub type Vx = Register;
/// Second register in an opcode
pub type Vy = Register;

/// A byte
///
/// Valid values are within `0x0` .. `0xFF`.
pub type Byte = u8;

/// A nibble (hex digit)
///
/// Valid values are within `0x0` .. `0xF`.
#[derive(Copy, Debug)]
pub struct Nibble {
    pub bits: u8,
}

impl Nibble {
    /// Creates a new `Nibble`, ignoring any high bits
    pub fn new(bits: u8) -> Nibble {
        Nibble { bits: bits & 0x0F }
    }
}

/// Absolute memory address
///
/// Valid addresses are within `0x0` .. `0xFFF`.
#[derive(Copy, Debug)]
pub struct Addr {
    pub bits: u16,
}

impl Addr {
    /// Creates a new `Addr`, ignoring any high bits
    pub fn new(bits: u16) -> Addr {
        Addr { bits: bits & 0x0FFF }
    }
}

/// Raw instruction
///
/// Helper around the raw bits, not necessarily a valid instruction.
#[derive(Copy)]
pub struct RawInstruction {
    bits: u16
}

impl RawInstruction {
    /// Creates a new raw instruction without any checks of the `bits`
    pub fn new(bits: u16) -> RawInstruction {
        RawInstruction{ bits: bits }
    }

    /// The *raw bits*
    #[allow(dead_code)]
    pub fn bits(&self) -> u16 {
        self.bits
    }

    /// The *address bits* part
    pub fn addr(&self) -> Addr {
        Addr::new(self.bits & 0x0FFF)
    }

    /// The *`Vx` register-index* part, i.e. `0xE` is `VE`
    pub fn x(&self) -> Vx {
        FromPrimitive::from_u8(((self.bits & 0x0F00) >> 8) as u8).unwrap()
    }

    /// The *`Vy` register-index* part, i.e. `0xE` is `VE`
    pub fn y(&self) -> Vy {
        FromPrimitive::from_u8(((self.bits & 0x00F0) >> 4) as u8).unwrap()
    }

    /// The *high nibble* part
    pub fn n_high(&self) -> Nibble {
        Nibble::new(((self.bits & 0xF000) >> 12) as u8)
    }

    /// The *low nibble* part
    pub fn n_low(&self) -> Nibble {
        Nibble::new((self.bits & 0x000F) as u8)
    }

    /// The *`k` byte* part
    pub fn k(&self) -> Byte {
        (self.bits & 0x00FF) as u8
    }
}

/// High-level instruction
///
/// A valid instruction that can be executed as-is.
#[derive(Copy,Debug)]
pub enum Instruction {
    /// Jumps to machine subroutine at `Addr`.
    ///
    /// Note that this is intentionally not implemented in the `Vm`.
    Sys(Addr),              // 0nnn - SYS addr
    /// Clears the screen.
    ///
    /// Sets all pixels to the unlit state.
    Clear,                  // 00E0 - CLS
    /// Returns from a subroutine
    Return,                 // 00EE - RET
    /// Jumps to `Addr`
    Jump(Addr),             // 1nnn - JP addr
    /// Calls subroutine at `Addr`
    Call(Addr),             // 2nnn - CALL addr
    /// Skips the next instructions if `Vx` equals `Byte`
    SkipEqualK(Vx, Byte),   // 3xkk - SE Vx, byte
    /// Skips the next instruction if `Vx` does not equal `Byte`
    SkipNotEqualK(Vx, Byte),// 4xkk - SNE Vx, byte
    /// Skips the next instruction if `Vx` and `Vy` are equal
    SkipEqual(Vx, Vy),      // 5xy0 - SE Vx, Vy
    /// Sets `Vy` to `Byte`
    SetK(Vx, Byte),         // 6xkk - LD Vx, byte
    /// Adds `Byte` to `Vx`, then stores the result in `Vx`
    AddK(Vx, Byte),         // 7xkk - ADD Vx, byte
    /// Stores `Vy` in `Vx`
    Set(Vx, Vy),            // 8xy0 - LD Vx, Vy
    /// Performs a bitwise OR (`|`) of `Vx` and `Vy`, then stores the result in `Vx`
    Or(Vx, Vy),             // 8xy1 - OR Vx, Vy
    /// Performs a bitwise AND (`&`) of `Vx` and `Vy`, then stores the result in `Vx`
    And(Vx, Vy),            // 8xy2 - AND Vx, Vy
    /// Performs a bitwise XOR (`^`) of `Vx` and `Vy`, then stores the result in `Vx`
    XOr(Vx, Vy),            // 8xy3 - XOR Vx, Vy
    /// Adds `Vx` and `Vy`, then stores the result in in `Vx`.
    ///
    /// `VF` is set to `1` on overflow, `0` otherwise.
    Add(Vx, Vy),            // 8xy4 - ADD Vx, Vy
    /// Subtracts `Vy` from `Vx`, then stores the result in `Vx`.
    ///
    /// `VF` is set to `1` if `Vx` is larger than `Vy` prior subtraction, `0` otherwise.
    Sub(Vx, Vy),            // 8xy5 - SUB Vx, Vy
    /// Shifts `Vy` right by one bit, then stores the result in `Vx`.
    ///
    /// Stores the least-significant bit prior shift of `Vy` in `VF`.
    ShiftRight(Vx, Vy),     // 8xy6 - SHR Vx {, Vy}
    /// Subtracts `Vx` from `Vy`, then stores the result in `Vx`.
    ///
    /// `VF` is set to `1` if `Vx` is larger than `Vy` prior subtraction, `0` otherwise.
    ///
    /// Note that this is the same as `Sub` with inverted register operands.
    SubInv(Vx, Vy),         // 8xy7 - SUBN Vx, Vy
    /// Shifts `Vy` left by one bit, then stores the result in `Vx`.
    ///
    /// Stores the most-significant bit prior shift of `Vy` in `VF`.
    ShiftLeft(Vx, Vy),      // 8xyE - SHL Vx {, Vy}
    /// Skips the next instruction if `Vx` and `Vy` are not equal
    SkipNotEqual(Vx, Vy),   // 9xy0 - SNE Vx, Vy
    /// Sets the `I` register to `Addr`
    LoadI(Addr),            // Annn - LD I, addr
    /// Jumps to `V0 + Addr`
    LongJump(Addr),         // Bnnn - JP V0, addr
    /// Sets `Vx` to a random byte ANDed with `Byte`
    Rand(Vx, Byte),         // Cxkk - RND Vx, byte
    /// Draws the sprite with `Nibble` bytes of data from the `I` register at position `(Vx, Vy)`.
    ///
    /// Sets `VF` to `1` if any pixels are set to unlit state, `0` otherwise.
    ///
    /// Note that sprites wrap around onto the opposite side of the screen.
    Draw(Vx, Vy, Nibble),   // Dxyn - DRW Vx, Vy, nibble
    /// Skips the next instruction if key `Vx` is pressed
    SkipPressed(Vx),        // Ex9E - SKP Vx
    /// Skips the next instruction if key `Vx` is not pressed
    SkipNotPressed(Vx),     // ExA1 - SKNP Vx
    /// Stores the value of the `delay timer` in `Vx`
    GetTimer(Vx),           // Fx07 - LD Vx, DT
    /// Stops execution until a key is pressed, then stores that key in `Vx`
    WaitKey(Vx),            // Fx0A - LD Vx, K
    /// Sets the `delay timer` to `Vx`
    SetTimer(Vx),           // Fx15 - LD DT, Vx
    /// Sets the `sound timer` to `Vx`
    SetSoundTimer(Vx),      // Fx18 - LD ST, Vx
    /// Adds `Vx` and the `I` register, then stores the result in `I`
    AddToI(Vx),             // Fx1E - ADD I, Vx
    /// Stores the address of the hexadecimal digit `Vx` in the `I` register
    LoadHexGlyph(Vx),       // Fx29 - LD F, Vx
    /// Stores the binary-coded decimal representation of `Vx` at address `I`, `I + 1` and `I + 2`
    StoreBCD(Vx),           // Fx33 - LD B, Vx
    /// Stores the registers `V0` to `Vx` inclusive at address `I`.
    ///
    /// Register `I` is set to `I + Vx + 1` afterwards.
    StoreRegisters(Vx),     // Fx55 - LD [I], Vx
    /// Reads the registers `V0` to `Vx` inclusive from address `I`.
    ///
    /// Register `I` is set to `I + Vx + 1` afterwards.
    LoadRegisters(Vx),      // Fx65 - LD Vx, [I]
    /// Placeholder for an unknown or illegal instruction.
    ///
    /// Note that this is not a real CHIP-8 instruction.
    Unknown,
}

impl Instruction {
    /// Creates a new instruction from raw bits,
    /// or `Instruction::Unknown` if no valid match could be found
    pub fn from_raw(raw: &RawInstruction) -> Instruction {
        use self::Instruction::*;

        match raw.n_high().bits {
            0x0 => {
                match raw.k() {
                    0xE0 => Clear,
                    0xEE => Return,
                    _ => Sys(raw.addr())
                }
            },
            0x1 => Jump(raw.addr()),
            0x2 => Call(raw.addr()),
            0x3 => SkipEqualK(raw.x(), raw.k()),
            0x4 => SkipNotEqualK(raw.x(), raw.k()),
            0x5 => SkipEqual(raw.x(), raw.y()),
            0x6 => SetK(raw.x(), raw.k()),
            0x7 => AddK(raw.x(), raw.k()),
            0x8 => {
                match raw.n_low().bits {
                    0x0 => Set(raw.x(), raw.y()),
                    0x1 => Or(raw.x(), raw.y()),
                    0x2 => And(raw.x(), raw.y()),
                    0x3 => XOr(raw.x(), raw.y()),
                    0x4 => Add(raw.x(), raw.y()),
                    0x5 => Sub(raw.x(), raw.y()),
                    0x6 => ShiftRight(raw.x(), raw.y()),
                    0x7 => SubInv(raw.x(), raw.y()),
                    0xE => ShiftLeft(raw.x(), raw.y()),
                    _ => Unknown
                }
            },
            0x9 => SkipNotEqual(raw.x(), raw.y()),
            0xA => LoadI(raw.addr()),
            0xB => LongJump(raw.addr()),
            0xC => Rand(raw.x(), raw.k()),
            0xD => Draw(raw.x(), raw.y(), raw.n_low()),
            0xE => {
                match raw.k() {
                    0x9E => SkipPressed(raw.x()),
                    0xA1 => SkipNotPressed(raw.x()),
                    _ => Unknown,
                }
            },
            0xF => {
                match raw.k() {
                    0x07 => GetTimer(raw.x()),
                    0x0A => WaitKey(raw.x()),
                    0x15 => SetTimer(raw.x()),
                    0x18 => SetSoundTimer(raw.x()),
                    0x1E => AddToI(raw.x()),
                    0x29 => LoadHexGlyph(raw.x()),
                    0x33 => StoreBCD(raw.x()),
                    0x55 => StoreRegisters(raw.x()),
                    0x65 => LoadRegisters(raw.x()),
                    _ => Unknown,
                }
            }
            _ => Unknown
        }
    }
}
<|endoftext|>


<commit_before>extern crate specs;

use self::specs::{Fetch, Join, WriteStorage, ReadStorage, System};

use model::comp::{Pos, Vel, Bounciness, Bounds, Actor};
use model::game::Id;
use collision::World;
use std::sync::RwLock;

pub struct Bounce;
impl<'a> System<'a> for Bounce {
    #[allow(type_complexity)]
    type SystemData = (ReadStorage<'a, Pos>,
     WriteStorage<'a, Vel>,
     ReadStorage<'a, Actor>,
     ReadStorage<'a, Bounciness>,
     Fetch<'a, Bounds<Pos>>,
     Fetch<'a, RwLock<World<Id>>>);

    fn run(&mut self, (pos, mut vel, actor, bounciness, pos_bounds, world): Self::SystemData) {
        let world = world.read().unwrap();
        for (pos, mut vel, actor, _) in (&pos, &mut vel, &actor, &bounciness).join() {
            handle_movement(actor, pos, &mut vel, &pos_bounds, &world);
        }
    }
}

fn handle_movement(
    actor: &Actor,
    pos: &Pos,
    vel: &mut Vel,
    bounds: &Bounds<Pos>,
    world: &World<Id>,
) {
    world.query_intersects_id(&actor.id, |_| {
        println!("bounce!");
    });
    let next_x = pos.x + vel.x;
    let next_y = pos.y + vel.y;
    if next_x > bounds.max.x || next_x < bounds.min.x {
        vel.x = -vel.x;
    }

    if next_y > bounds.max.y || next_y < bounds.min.y {
        vel.y = -vel.y;
    }
}
<commit_msg>Core: WIP of player collision<commit_after>extern crate specs;

use self::specs::{Fetch, Join, WriteStorage, ReadStorage, System};

use model::comp::{Pos, Vel, Bounciness, Bounds, Actor};
use model::game::{Id, Vector};
use collision::World;
use util::angle;
use std::sync::RwLock;

pub struct Bounce;
impl<'a> System<'a> for Bounce {
    #[allow(type_complexity)]
    type SystemData = (ReadStorage<'a, Pos>,
     WriteStorage<'a, Vel>,
     ReadStorage<'a, Actor>,
     ReadStorage<'a, Bounciness>,
     Fetch<'a, Bounds<Pos>>,
     Fetch<'a, RwLock<World<Id>>>);

    fn run(&mut self, (pos, mut vel, actor, bounciness, pos_bounds, world): Self::SystemData) {
        let world = world.read().unwrap();
        for (pos, mut vel, actor, _) in (&pos, &mut vel, &actor, &bounciness).join() {
            handle_movement(actor, pos, &mut vel, &pos_bounds, &world);
        }
    }
}

fn handle_movement(
    actor: &Actor,
    pos: &Pos,
    vel: &mut Vel,
    bounds: &Bounds<Pos>,
    world: &World<Id>,
) {
    world.query_intersects_id(&actor.id, |other| {
        let own: Vector = Vector {
            x: pos.x,
            y: pos.y,
        };
        let other = Vector {
            x: other.bounds.x,
            y: other.bounds.y,
        };
        let angle = angle(&own, &other);
        if angle > 270.0 || angle < 90.0 {
            vel.x = -vel.x.abs();
        } else {
            vel.x = vel.x.abs();
        }
    });
    let next_x = pos.x + vel.x;
    let next_y = pos.y + vel.y;
    if next_x > bounds.max.x || next_x < bounds.min.x {
        // Score and respawn
    }
    if next_y > bounds.max.y || next_y < bounds.min.y {
        vel.y = -vel.y;
    }
}
<|endoftext|>


<commit_before>//
// Mnemosyne: a functional systems programming language.
// (c) 2015 Hawk Weisman
//
// Mnemosyne is released under the MIT License. Please refer to
// the LICENSE file at the top-level directory of this distribution
// or at https://github.com/hawkw/mnemosyne/.
//

use std::borrow::Borrow;
use std::collections::HashMap;
use std::hash::Hash;
use std::{ fmt
         , iter
         };
use std::fmt::Write;
use std::rc::Rc;

use ::position::Positional;
use super::annotations::{ Annotated
                        , ScopednessTypestate
                        , ScopedState
                        , Scoped
                        };
use super::types;
use super::SymbolTable;

pub type Ident = Positional<String>;

pub type Expr<'a, S: ScopednessTypestate>
    = Annotated<'a
               , Form<'a, S>
               , S>;

pub type Body<'a, S: ScopednessTypestate> = Vec<Expr<'a, S>>;

pub type Bindings<'a, S: ScopednessTypestate>
    = Vec<Annotated<'a
                   , Binding<'a, S>
                   , S>>;

/// Trait for a node in the abstract syntax tree.
///
/// This provides a visitor method for semantic analysis (which may be split
/// into multiple transforms later), and a method for formatting the AST node
/// as an S-expression.
pub trait Node {

   /// Pretty-print the AST node as an S-expression at the desired
   /// indentation level.]
   ///
   /// Note that this prints the desugared form and may not be a perfect
   /// match for the original source code.
   fn to_sexpr(&self, level: usize) -> String;

}

impl fmt::Display for Node + Sized {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.to_sexpr(0))
    }
}

pub trait AnnotateTypes<'a>: Sized {

   #[allow(unused_variables)]
   fn annotate_types(self, scope: SymbolTable) -> Scoped<'a, Self> {
       unimplemented!() //TODO: implement
   }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Module<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub exporting: Vec<Ident>
  , pub body: Body<'a, S>
}

impl<'a, S> Module<'a, S> where S: ScopednessTypestate {

    /// Returns true if the namespace is exporting any nages
    #[inline] pub fn is_lib (&self) -> bool { !self.exporting.is_empty() }

}

impl<'a> Scoped<'a, Module<'a, ScopedState>>{

    pub fn contains_name<Q: ?Sized>(&self, name: &Q) -> bool
    where String: Borrow<Q>
        , String: PartialEq<Q>
        , Q: Hash + Eq
    {
        self.is_defined_here(name) &&
        self.node.exporting
            .iter()
            .find(|ref i| &i.value == name)
            .is_some()
    }

}

#[derive(PartialEq, Clone, Debug)]
pub enum Form<'a, S: ScopednessTypestate> {
    // TODO: maybe definitions aren't expressions?
    // (they don't return a value...)
    Define(DefForm<'a, S>)
  , If { condition: Rc<Expr<'a, S>>
       , if_clause: Rc<Expr<'a, S>>
       , else_clause: Option<Rc<Expr<'a, S>>>
       }
  , Let(LetForm<'a, S>)
  , Call { fun: Ident
         , body: Body<'a, S>
         }
  , Lambda(Function<'a, S>)
  , Logical(Logical<'a, S>)
  , Lit(Literal)
  , NameRef(NameRef)
}

#[derive(PartialEq, Clone, Debug)]
pub enum NameRef { Owned(Ident)
                 , Borrowed(Ident)
                 , Deref(Ident)
                 , Unique(Ident)
                 }

#[derive(PartialEq, Clone, Debug)]
pub struct Formal { pub name: Ident
                  , pub annot: Ident
                  }

#[derive(PartialEq, Clone, Debug)]
pub enum DefForm<'a, S: ScopednessTypestate> {
    TopLevel { name: Ident
             , annot: types::Type
             , value: Rc<Expr<'a, S>>
             }
  , Function { name: Ident
             , fun: Function<'a,S>
             }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Class<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub ty_param: Ident
  , pub defs: Vec<Prototype<'a, S>>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Instance<'a, S: ScopednessTypestate> {
    pub class: Ident
  , pub ty: types::Type
  , pub functions: Vec<Function<'a, S>>
}

/// Logical `and` and `or` expressions
///
/// The general expectation is that these will generally be parsed as infix.
#[derive(PartialEq, Clone, Debug)]
pub enum Logical<'a, S: ScopednessTypestate> {
    And { a: Rc<Expr<'a, S>>
        , b: Rc<Expr<'a, S>>
        }
  , Or { a: Rc<Expr<'a, S>>
       , b: Rc<Expr<'a, S>>
       }
}

#[derive(PartialEq, Clone, Debug)]
pub enum Literal { IntConst(i64)
                 , UintConst(u64)
                 }

impl fmt::Display for Literal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self { Literal::IntConst(ref n)    => write!(f, "{}", n)
                    , Literal::UintConst(ref n)   => write!(f, "{}", n)
                    }
    }
}

#[derive(PartialEq, Clone, Debug)]
pub enum LetForm<'a, S: ScopednessTypestate> {
    Let { bindings: Bindings<'a, S>
        , body: Body<'a, S>
        }
  , Invocation { proc_id: Ident
               , init: Binding<'a, S>
               , body: Body<'a, S>
               }
  , LetRec { bindings: Bindings<'a, S>
           , body: Body<'a, S>
           }
  , LetSplat { bindings: Bindings<'a, S>
             , body: Body<'a, S>
             }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Binding<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub typ: types::Type
  , pub value: Rc<Expr<'a, S>>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Function<'a, S: ScopednessTypestate> {
    pub sig: types::Signature
  , pub equations: Vec<Equation<'a, S>>
}

/// A pattern is a vector of pattern elements.
///
/// When entering a function scope that binds using patterns, we should
/// check that the pattern's length matches the arity of the function,
/// until autocurrying is implemented (after the Glorious Revolution).
pub type Pattern = Vec<PatElement>;

impl Node for Pattern {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       format!( "({})"
              , self.iter()
                    .fold(String::new(), |mut s, expr| {
                       write!(s, " {} ", expr.to_sexpr(level))
                           .expect("Could not write to string!");
                       s
                  })
               )
   }

}

/// An element in a pattern-matching expression.
///
/// A pattern element can be a name binding, a typed name binding,
/// a literal, or the magic underscore (anything). Destructuring bind
/// will come later, as will equality.
#[derive(PartialEq, Clone, Debug)]
pub enum PatElement { // eventually this could just be implemented using an Expr,
                      // but it's currently this way because the types of patterns
                      // that you can write are currently quite limited
                      Name(Ident)
                    , Typed { name: Ident, ty: types::Type }
                    , Lit(Literal)
                      // TODO: write literal types for other things (i.e. lists)
                    , Anything
                    }

impl Node for PatElement {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       match *self {
           PatElement::Name(ref n) => n.to_sexpr(level)
         , PatElement::Typed { ref name, ref ty } =>
            format!( "{}: {}"
                   , name.to_sexpr(level)
                   , ty )
        , PatElement::Lit(ref c) => format!("{}", c)
        , PatElement::Anything => String::from("_")
       }
   }

}

/// A function equation definition
#[derive(PartialEq, Clone, Debug)]
pub struct Equation<'a, S: ScopednessTypestate> {
    pub pattern: Pattern
 ,  pub body: Body<'a, S>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Prototype<'a, S: ScopednessTypestate> {
    pub formals: Vec<Annotated<'a, Formal, S>>
  , pub annot: Ident
}

pub type Variant<'a, S: ScopednessTypestate>
    = Vec<Annotated<'a, Formal, S>>;

#[derive(PartialEq, Clone, Debug)]
pub struct Data<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub variants: HashMap<Ident, Variant<'a, S>>
}

// #[derive(PartialEq, Clone, Debug)]
// pub enum Data<'a, S: ScopednessTypestate> {
//     Sum { name: Ident
//         , variants: Vec<Type> }
//   , Product { name: Ident
//             , fields: Vec<Binding<'a, S>> }
// }

impl<'a, S> Data<'a, S>
where S: ScopednessTypestate {

    /// Returns true if this ADT is a sum type
    pub fn is_sum_type(&self) -> bool {
        self.variants.len() > 1
    }

    /// Returns true if this ADT is a product type
    #[inline] pub fn is_product_type(&self) -> bool {
        !self.is_sum_type()
    }

    /// Returns the fields of a product type.
    ///
    /// # Returns
    ///  + A `Some<Vec<Annotated<'a, Formal, S>>>` representing
    ///    this type's fields, if this is the definition of a
    ///    product type.
    ///  + Otherwise, `None`
    pub fn get_product_fields(&self) -> Option<&Variant<'a, S>> {
        self.variants.get(&self.name)
    }
}

impl<'a, S> Node for Form<'a, S>
where S: ScopednessTypestate {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       match *self {
           Form::Define(ref form)  => form.to_sexpr(level)
         , Form::Let(ref form)     => form.to_sexpr(level)
         , Form::If { .. }         => unimplemented!()
         , Form::Call { ref fun, ref body } =>
               format!( "({}{})"
                      , fun.to_sexpr(level)
                      , body.iter()
                            .fold(String::new(), |mut s, expr| {
                                  write!(s, " {}", expr.to_sexpr(level))
                                      .expect("Could not write to string!");
                                  s
                             }))
         , Form::Lambda(ref fun)   => fun.to_sexpr(level)
         , Form::Logical(ref form) => form.to_sexpr(level)
         , Form::Lit(ref c)   => format!("{}", c)
         , Form::NameRef(ref n)    => n.to_sexpr(level)
       }
   }

}

impl<'a, S> Node for DefForm<'a, S>
where S: ScopednessTypestate {

    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            DefForm::TopLevel { ref name, ref annot, ref value } =>
                format!("{}(define {} {} {})"
                  , indent!(level)
                  , name.to_sexpr(level)
                  , annot
                  , value.to_sexpr(level + 1)
                  )
          , DefForm::Function { ref name, ref fun } =>
                format!("{}(define {} {}\n)"
                  , indent!(level)
                  , name.to_sexpr(level)
                  , fun.to_sexpr(level)
                  )
        }
    }

}

impl<'a, S> Node for LetForm<'a, S>
where S: ScopednessTypestate {

    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            LetForm::Let { ref bindings, ref body } =>
                format!("{}(let [{}]\n{})"
                    , indent!(level)
                    , bindings.iter()
                              .fold(String::new(), |mut s, binding| {
                                    write!(s, "{}\n", binding.to_sexpr(level))
                                        .expect("Could not write to string!");
                                    s
                                 })
                    , body.iter()
                          .fold(String::new(), |mut s, expr| {
                              write!(s, "{}", expr.to_sexpr(level + 1))
                                .expect("Could not write to string!");
                              s
                          })
                       )
          , LetForm::LetRec { ref bindings, ref body } =>
                format!("{}(letrec [{}]\n{})"
                    , indent!(level)
                    , bindings.iter()
                              .fold(String::new(), |mut s, binding| {
                                    write!(s, "{}\n", binding.to_sexpr(level))
                                        .expect("Could not write to string!");
                                    s
                               })
                    , body.iter()
                          .fold(String::new(), |mut s, expr| {
                                write!(s, "{}", expr.to_sexpr(level + 1)); s
                            })
                          )
          , LetForm::LetSplat { ref bindings, ref body } =>
                format!("{}(let* [{}]\n{})"
                    , indent!(level)
                    , bindings.iter()
                              .fold(String::new(), |mut s, binding| {
                                    write!(s, "{}\n", binding.to_sexpr(level))
                                        .expect("Could not write to string!");
                                    s
                               })
                    , body.iter()
                          .fold(String::new(), |mut s, expr| {
                                write!(s, "{}", expr.to_sexpr(level + 1))
                                    .expect("Could not write to string!");
                                s
                            })
                          )
          , _ => unimplemented!()
        }
    }

}

impl<'a, S> Node for Logical<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            Logical::And { ref a, ref b } =>
                format!( "(and {} {})"
                       , a.to_sexpr(level)
                       , b.to_sexpr(level)
                       )
         ,  Logical::Or { ref a, ref b }  =>
                format!( "(and {} {})"
                       , a.to_sexpr(level)
                       , b.to_sexpr(level)
                       )
        }
    }
}

impl<'a, S> Node for Function<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        unimplemented!()
    }
}

impl<'a, S> Node for Binding<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        unimplemented!()
    }
}

impl Node for Formal {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        format!("{}: {}", *(self.name), *(self.annot))
    }

}

impl Node for NameRef {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        match *self  { NameRef::Owned(ref name)      => format!("{}", **name)
                     , NameRef::Borrowed(ref name)   => format!("&{}", **name)
                     , NameRef::Deref(ref name)      => format!("*{}", **name)
                     , NameRef::Unique(ref name)     => format!("@{}", **name)
                     }

    }
}

impl Node for Ident {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String { self.value.clone() }

}
<commit_msg>Code reuse macros for to_sexpr()<commit_after>//
// Mnemosyne: a functional systems programming language.
// (c) 2015 Hawk Weisman
//
// Mnemosyne is released under the MIT License. Please refer to
// the LICENSE file at the top-level directory of this distribution
// or at https://github.com/hawkw/mnemosyne/.
//

use std::borrow::Borrow;
use std::collections::HashMap;
use std::hash::Hash;
use std::{ fmt
         , iter
         };
use std::fmt::Write;
use std::rc::Rc;

use ::position::Positional;
use super::annotations::{ Annotated
                        , ScopednessTypestate
                        , ScopedState
                        , Scoped
                        };
use super::types;
use super::SymbolTable;

pub type Ident = Positional<String>;

pub type Expr<'a, S: ScopednessTypestate>
    = Annotated<'a
               , Form<'a, S>
               , S>;

pub type Body<'a, S: ScopednessTypestate> = Vec<Expr<'a, S>>;

pub type Bindings<'a, S: ScopednessTypestate>
    = Vec<Annotated<'a
                   , Binding<'a, S>
                   , S>>;

macro_rules! concat_exprs {
    ($it:expr, $level:expr) => {
        $it.iter()
           .fold(String::new(), |mut s, expr| {
                 write!(s, " {} ", expr.to_sexpr($level))
                     .expect("Could not write to string!");
                 s
            })
        }
}

/// Trait for a node in the abstract syntax tree.
///
/// This provides a visitor method for semantic analysis (which may be split
/// into multiple transforms later), and a method for formatting the AST node
/// as an S-expression.
pub trait Node {

   /// Pretty-print the AST node as an S-expression at the desired
   /// indentation level.]
   ///
   /// Note that this prints the desugared form and may not be a perfect
   /// match for the original source code.
   fn to_sexpr(&self, level: usize) -> String;

}

impl fmt::Display for Node + Sized {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.to_sexpr(0))
    }
}

pub trait AnnotateTypes<'a>: Sized {

   #[allow(unused_variables)]
   fn annotate_types(self, scope: SymbolTable) -> Scoped<'a, Self> {
       unimplemented!() //TODO: implement
   }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Module<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub exporting: Vec<Ident>
  , pub body: Body<'a, S>
}

impl<'a, S> Module<'a, S> where S: ScopednessTypestate {

    /// Returns true if the namespace is exporting any nages
    #[inline] pub fn is_lib (&self) -> bool { !self.exporting.is_empty() }

}

impl<'a> Scoped<'a, Module<'a, ScopedState>>{

    pub fn contains_name<Q: ?Sized>(&self, name: &Q) -> bool
    where String: Borrow<Q>
        , String: PartialEq<Q>
        , Q: Hash + Eq
    {
        self.is_defined_here(name) &&
        self.node.exporting
            .iter()
            .find(|ref i| &i.value == name)
            .is_some()
    }

}

#[derive(PartialEq, Clone, Debug)]
pub enum Form<'a, S: ScopednessTypestate> {
    // TODO: maybe definitions aren't expressions?
    // (they don't return a value...)
    Define(DefForm<'a, S>)
  , If { condition: Rc<Expr<'a, S>>
       , if_clause: Rc<Expr<'a, S>>
       , else_clause: Option<Rc<Expr<'a, S>>>
       }
  , Let(LetForm<'a, S>)
  , Call { fun: Ident
         , body: Body<'a, S>
         }
  , Lambda(Function<'a, S>)
  , Logical(Logical<'a, S>)
  , Lit(Literal)
  , NameRef(NameRef)
}

#[derive(PartialEq, Clone, Debug)]
pub enum NameRef { Owned(Ident)
                 , Borrowed(Ident)
                 , Deref(Ident)
                 , Unique(Ident)
                 }

#[derive(PartialEq, Clone, Debug)]
pub struct Formal { pub name: Ident
                  , pub annot: Ident
                  }

#[derive(PartialEq, Clone, Debug)]
pub enum DefForm<'a, S: ScopednessTypestate> {
    TopLevel { name: Ident
             , annot: types::Type
             , value: Rc<Expr<'a, S>>
             }
  , Function { name: Ident
             , fun: Function<'a,S>
             }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Class<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub ty_param: Ident
  , pub defs: Vec<Prototype<'a, S>>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Instance<'a, S: ScopednessTypestate> {
    pub class: Ident
  , pub ty: types::Type
  , pub functions: Vec<Function<'a, S>>
}

/// Logical `and` and `or` expressions
///
/// The general expectation is that these will generally be parsed as infix.
#[derive(PartialEq, Clone, Debug)]
pub enum Logical<'a, S: ScopednessTypestate> {
    And { a: Rc<Expr<'a, S>>
        , b: Rc<Expr<'a, S>>
        }
  , Or { a: Rc<Expr<'a, S>>
       , b: Rc<Expr<'a, S>>
       }
}

#[derive(PartialEq, Clone, Debug)]
pub enum Literal { IntConst(i64)
                 , UintConst(u64)
                 }

impl fmt::Display for Literal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self { Literal::IntConst(ref n)    => write!(f, "{}", n)
                    , Literal::UintConst(ref n)   => write!(f, "{}", n)
                    }
    }
}

#[derive(PartialEq, Clone, Debug)]
pub enum LetForm<'a, S: ScopednessTypestate> {
    Let { bindings: Bindings<'a, S>
        , body: Body<'a, S>
        }
  , Invocation { proc_id: Ident
               , init: Binding<'a, S>
               , body: Body<'a, S>
               }
  , LetRec { bindings: Bindings<'a, S>
           , body: Body<'a, S>
           }
  , LetSplat { bindings: Bindings<'a, S>
             , body: Body<'a, S>
             }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Binding<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub typ: types::Type
  , pub value: Rc<Expr<'a, S>>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Function<'a, S: ScopednessTypestate> {
    pub sig: types::Signature
  , pub equations: Vec<Equation<'a, S>>
}

/// A pattern is a vector of pattern elements.
///
/// When entering a function scope that binds using patterns, we should
/// check that the pattern's length matches the arity of the function,
/// until autocurrying is implemented (after the Glorious Revolution).
pub type Pattern = Vec<PatElement>;

impl Node for Pattern {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       format!( "({})", concat_exprs!(self, level) )
   }

}

/// An element in a pattern-matching expression.
///
/// A pattern element can be a name binding, a typed name binding,
/// a literal, or the magic underscore (anything). Destructuring bind
/// will come later, as will equality.
#[derive(PartialEq, Clone, Debug)]
pub enum PatElement { // eventually this could just be implemented using an Expr,
                      // but it's currently this way because the types of patterns
                      // that you can write are currently quite limited
                      Name(Ident)
                    , Typed { name: Ident, ty: types::Type }
                    , Lit(Literal)
                      // TODO: write literal types for other things (i.e. lists)
                    , Anything
                    }

impl Node for PatElement {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       match *self {
           PatElement::Name(ref n) => n.to_sexpr(level)
         , PatElement::Typed { ref name, ref ty } =>
            format!( "{}: {}"
                   , name.to_sexpr(level)
                   , ty )
        , PatElement::Lit(ref c) => format!("{}", c)
        , PatElement::Anything => String::from("_")
       }
   }

}

/// A function equation definition
#[derive(PartialEq, Clone, Debug)]
pub struct Equation<'a, S: ScopednessTypestate> {
    pub pattern: Pattern
 ,  pub body: Body<'a, S>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Prototype<'a, S: ScopednessTypestate> {
    pub formals: Vec<Annotated<'a, Formal, S>>
  , pub annot: Ident
}

pub type Variant<'a, S: ScopednessTypestate>
    = Vec<Annotated<'a, Formal, S>>;

#[derive(PartialEq, Clone, Debug)]
pub struct Data<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub variants: HashMap<Ident, Variant<'a, S>>
}

// #[derive(PartialEq, Clone, Debug)]
// pub enum Data<'a, S: ScopednessTypestate> {
//     Sum { name: Ident
//         , variants: Vec<Type> }
//   , Product { name: Ident
//             , fields: Vec<Binding<'a, S>> }
// }

impl<'a, S> Data<'a, S>
where S: ScopednessTypestate {

    /// Returns true if this ADT is a sum type
    pub fn is_sum_type(&self) -> bool {
        self.variants.len() > 1
    }

    /// Returns true if this ADT is a product type
    #[inline] pub fn is_product_type(&self) -> bool {
        !self.is_sum_type()
    }

    /// Returns the fields of a product type.
    ///
    /// # Returns
    ///  + A `Some<Vec<Annotated<'a, Formal, S>>>` representing
    ///    this type's fields, if this is the definition of a
    ///    product type.
    ///  + Otherwise, `None`
    pub fn get_product_fields(&self) -> Option<&Variant<'a, S>> {
        self.variants.get(&self.name)
    }
}

impl<'a, S> Node for Form<'a, S>
where S: ScopednessTypestate {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       match *self {
           Form::Define(ref form)  => form.to_sexpr(level)
         , Form::Let(ref form)     => form.to_sexpr(level)
         , Form::If { .. }         => unimplemented!()
         , Form::Call { ref fun, ref body } =>
               format!( "({}{})"
                      , fun.to_sexpr(level)
                      , concat_exprs!(body, level) )
         , Form::Lambda(ref fun)   => fun.to_sexpr(level)
         , Form::Logical(ref form) => form.to_sexpr(level)
         , Form::Lit(ref c)   => format!("{}", c)
         , Form::NameRef(ref n)    => n.to_sexpr(level)
       }
   }

}

impl<'a, S> Node for DefForm<'a, S>
where S: ScopednessTypestate {

    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            DefForm::TopLevel { ref name, ref annot, ref value } =>
                format!("{}(define {} {} {})"
                  , indent!(level)
                  , name.to_sexpr(level)
                  , annot
                  , value.to_sexpr(level + 1)
                  )
          , DefForm::Function { ref name, ref fun } =>
                format!("{}(define {} {}\n)"
                  , indent!(level)
                  , name.to_sexpr(level)
                  , fun.to_sexpr(level)
                  )
        }
    }

}

impl<'a, S> Node for LetForm<'a, S>
where S: ScopednessTypestate {

    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            LetForm::Let { ref bindings, ref body } =>
                format!("{}(let [{}]\n{})"
                    , indent!(level)
                    , bindings.iter()
                              .fold(String::new(), |mut s, binding| {
                                    write!(s, "{}\n", binding.to_sexpr(level))
                                        .expect("Could not write to string!");
                                    s
                                 })
                    , concat_exprs!(body, level + 1)
                    )
          , LetForm::LetRec { ref bindings, ref body } =>
                format!("{}(letrec [{}]\n{})"
                    , indent!(level)
                    , bindings.iter()
                              .fold(String::new(), |mut s, binding| {
                                    write!(s, "{}\n", binding.to_sexpr(level))
                                        .expect("Could not write to string!");
                                    s
                               })
                    , concat_exprs!(body, level + 1)
                    )
          , LetForm::LetSplat { ref bindings, ref body } =>
                format!("{}(let* [{}]\n{})"
                    , indent!(level)
                    , bindings.iter()
                              .fold(String::new(), |mut s, binding| {
                                    write!(s, "{}\n", binding.to_sexpr(level))
                                        .expect("Could not write to string!");
                                    s
                               })
                    , concat_exprs!(body, level + 1)
                    )
          , _ => unimplemented!()
        }
    }

}

impl<'a, S> Node for Logical<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            Logical::And { ref a, ref b } =>
                format!( "(and {} {})"
                       , a.to_sexpr(level)
                       , b.to_sexpr(level)
                       )
         ,  Logical::Or { ref a, ref b }  =>
                format!( "(and {} {})"
                       , a.to_sexpr(level)
                       , b.to_sexpr(level)
                       )
        }
    }
}

impl<'a, S> Node for Function<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        unimplemented!()
    }
}

impl<'a, S> Node for Binding<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        unimplemented!()
    }
}

impl Node for Formal {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        format!("{}: {}", *(self.name), *(self.annot))
    }

}

impl Node for NameRef {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        match *self  { NameRef::Owned(ref name)      => format!("{}", **name)
                     , NameRef::Borrowed(ref name)   => format!("&{}", **name)
                     , NameRef::Deref(ref name)      => format!("*{}", **name)
                     , NameRef::Unique(ref name)     => format!("@{}", **name)
                     }

    }
}

impl Node for Ident {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String { self.value.clone() }

}
<|endoftext|>


<commit_before>use std::marker;

use crate::reflect::acc::v2::singular::GetOptionImplHasGetRef;
use crate::reflect::acc::v2::singular::MutOrDefaultGetMut;
use crate::reflect::acc::v2::singular::SetImplSetField;
use crate::reflect::acc::v2::singular::SingularFieldAccessorHolder;
use crate::reflect::acc::v2::singular::SingularFieldAccessorImpl;
use crate::reflect::acc::v2::AccessorV2;
use crate::reflect::acc::FieldAccessor;
use crate::reflect::runtime_types::RuntimeTypeWithDeref;
use crate::reflect::ProtobufValue;
use crate::EnumFull;
use crate::EnumOrUnknown;
use crate::MessageFull;

/// Make accessor for `oneof` `message` field
pub fn make_oneof_message_has_get_mut_set_accessor<M, F>(
    name: &'static str,
    has_field: fn(&M) -> bool,
    get_field: for<'a> fn(&'a M) -> &'a F,
    mut_field: for<'a> fn(&'a mut M) -> &'a mut F,
    set_field: fn(&mut M, F),
) -> FieldAccessor
where
    M: MessageFull + 'static,
    F: MessageFull + ProtobufValue,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder {
            accessor: Box::new(SingularFieldAccessorImpl::<M, F, _, _, _> {
                get_option_impl: GetOptionImplHasGetRef::<M, F> {
                    get: get_field,
                    has: has_field,
                },
                mut_or_default_impl: MutOrDefaultGetMut::<M, F> { mut_field },
                set_impl: SetImplSetField::<M, F> { set_field },
                _marker: marker::PhantomData,
            }),
        }),
    )
}

/// Make accessor for `Copy` field
pub fn make_oneof_copy_has_get_set_simpler_accessors<M, V>(
    name: &'static str,
    has: fn(&M) -> bool,
    get: fn(&M) -> V,
    set: fn(&mut M, V),
) -> FieldAccessor
where
    M: MessageFull,
    V: ProtobufValue + Copy,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_has_get_set(has, get, set)),
    )
}

/// Make accessor for `Copy` field
pub fn make_oneof_enum_accessors<M, E>(
    name: &'static str,
    get: fn(&M) -> Option<EnumOrUnknown<E>>,
    set: fn(&mut M, EnumOrUnknown<E>),
    // TODO: remove this
    _default_value: E,
) -> FieldAccessor
where
    M: MessageFull,
    E: EnumFull,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_get_option_set_enum(
            get, set,
        )),
    )
}

/// Make accessor for `oneof` field
pub fn make_oneof_deref_has_get_set_simpler_accessor<M, F>(
    name: &'static str,
    has: fn(&M) -> bool,
    get: for<'a> fn(&'a M) -> &'a <F::RuntimeType as RuntimeTypeWithDeref>::DerefTarget,
    set: fn(&mut M, F),
) -> FieldAccessor
where
    M: MessageFull + 'static,
    F: ProtobufValue,
    F::RuntimeType: RuntimeTypeWithDeref,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_has_get_set_deref(
            has, get, set,
        )),
    )
}
<commit_msg>Code cleanup<commit_after>use std::marker;

use crate::reflect::acc::v2::singular::GetOptionImplHasGetRef;
use crate::reflect::acc::v2::singular::MutOrDefaultGetMut;
use crate::reflect::acc::v2::singular::SetImplSetField;
use crate::reflect::acc::v2::singular::SingularFieldAccessorHolder;
use crate::reflect::acc::v2::singular::SingularFieldAccessorImpl;
use crate::reflect::acc::v2::AccessorV2;
use crate::reflect::acc::FieldAccessor;
use crate::reflect::runtime_types::RuntimeTypeWithDeref;
use crate::reflect::ProtobufValue;
use crate::EnumFull;
use crate::EnumOrUnknown;
use crate::MessageFull;

/// Make accessor for `oneof` `message` field
pub fn make_oneof_message_has_get_mut_set_accessor<M, F>(
    name: &'static str,
    has_field: fn(&M) -> bool,
    get_field: for<'a> fn(&'a M) -> &'a F,
    mut_field: for<'a> fn(&'a mut M) -> &'a mut F,
    set_field: fn(&mut M, F),
) -> FieldAccessor
where
    M: MessageFull,
    F: MessageFull,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder {
            accessor: Box::new(SingularFieldAccessorImpl::<M, F, _, _, _> {
                get_option_impl: GetOptionImplHasGetRef::<M, F> {
                    get: get_field,
                    has: has_field,
                },
                mut_or_default_impl: MutOrDefaultGetMut::<M, F> { mut_field },
                set_impl: SetImplSetField::<M, F> { set_field },
                _marker: marker::PhantomData,
            }),
        }),
    )
}

/// Make accessor for `Copy` field
pub fn make_oneof_copy_has_get_set_simpler_accessors<M, V>(
    name: &'static str,
    has: fn(&M) -> bool,
    get: fn(&M) -> V,
    set: fn(&mut M, V),
) -> FieldAccessor
where
    M: MessageFull,
    V: ProtobufValue + Copy,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_has_get_set(has, get, set)),
    )
}

/// Make accessor for `Copy` field
pub fn make_oneof_enum_accessors<M, E>(
    name: &'static str,
    get: fn(&M) -> Option<EnumOrUnknown<E>>,
    set: fn(&mut M, EnumOrUnknown<E>),
    // TODO: remove this
    _default_value: E,
) -> FieldAccessor
where
    M: MessageFull,
    E: EnumFull,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_get_option_set_enum(
            get, set,
        )),
    )
}

/// Make accessor for `oneof` field
pub fn make_oneof_deref_has_get_set_simpler_accessor<M, F>(
    name: &'static str,
    has: fn(&M) -> bool,
    get: for<'a> fn(&'a M) -> &'a <F::RuntimeType as RuntimeTypeWithDeref>::DerefTarget,
    set: fn(&mut M, F),
) -> FieldAccessor
where
    M: MessageFull + 'static,
    F: ProtobufValue,
    F::RuntimeType: RuntimeTypeWithDeref,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_has_get_set_deref(
            has, get, set,
        )),
    )
}
<|endoftext|>