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

use context::GraphicsContextMethods;

use std::libc::{c_char, c_int, c_long, c_uint, c_ulong, c_void};
use std::ptr::null;
use std::ptr;
use extra::arc::Arc;

// Constants.

static GLX_RGBA: c_int = 4;
static GLX_RED_SIZE: c_int = 8;
static GLX_GREEN_SIZE: c_int = 9;
static GLX_BLUE_SIZE: c_int = 10;
static GLX_DEPTH_SIZE: c_int = 12;

static ATTRIBUTES: [c_int, ..4] = [
    GLX_RGBA,
    GLX_DEPTH_SIZE, 24,
    0,
];

// External bindings to Xlib.

// Opaque structures.
struct _XPrivate;
struct _XrmHashBucketRec;
struct Depth;
struct GLXContextOpaque;
struct Visual;

// Sadly we need to copy some of this definition in here because the Xlib macros need to access it.
struct Display {
    ext_data: *XExtData,
    private1: *_XPrivate,
    fd: c_int,
    private2: c_int,
    proto_major_version: c_int,
    proto_minor_version: c_int,
    vendor: *c_char,
    private3: XID,
    private4: XID,
    private5: XID,
    private6: c_int,
    resource_alloc: *c_void,
    byte_order: c_int,
    bitmap_unit: c_int,
    bitmap_pad: c_int,
    bitmap_bit_order: c_int,
    nformats: c_int,
    pixmap_format: *ScreenFormat,
    private8: c_int,
    release: c_int,
    private9: *_XPrivate,
    private10: *_XPrivate,
    qlen: c_int,
    last_request_read: c_ulong,
    request: c_ulong,
    private11: XPointer,
    private12: XPointer,
    private13: XPointer,
    private14: XPointer,
    max_request_size: c_uint,
    db: *_XrmHashBucketRec,
    private15: *c_void,
    display_name: *c_char,

    // FIXME(pcwalton): These are needed for some reason...
    pad: *c_void,
    pad1: *c_void,

    default_screen: c_int,
    nscreens: c_int,
    screens: *Screen,
}

struct Screen {
    ext_data: *XExtData,
    display: *Display,
    root: Window,
    width: c_int,
    height: c_int,
    mwidth: c_int,
    mheight: c_int,
    ndepths: c_int,
    depths: *Depth,
    root_depth: c_int,
    root_visual: *Visual,
    default_gc: GC,
    cmap: Colormap,
    white_pixel: c_ulong,
    black_pixel: c_ulong,
    max_maps: c_int,
    min_maps: c_int,
    backing_store: c_int,
    save_unders: Bool,
    root_input_mask: c_long,
    pad: *c_void,
}

struct ScreenFormat;
struct XExtData;

struct XVisualInfo {
    visual: *Visual,
    visualid: VisualID,
    screen: c_int,
    depth: c_int,
    class: c_int,
    red_mask: c_ulong,
    green_mask: c_ulong,
    blue_mask: c_ulong,
    colormap_size: c_int,
    bits_per_rgb: c_int,
}

type Bool = c_int;
type Colormap = XID;
type Drawable = c_uint;                 // compatible with Window
type GC = *c_void;
type GLXContext = *GLXContextOpaque;
type GLXDrawable = c_uint;              // compatible with GLXPixmap
type GLXPixmap = c_uint;                // compatible with GLXDrawable
type Pixmap = c_uint;
type VisualID = c_ulong;
type Window = c_uint;                   // compatible with Drawable
type XID = c_uint;
type XPointer = *c_void;

#[link_args="-lX11 -lGL"]
#[nolink]
extern {
    fn XOpenDisplay(n: c_int) -> *Display;
    fn XCreatePixmap(display: *Display, d: Drawable, width: c_uint, height: c_uint, depth: c_uint)
                     -> Pixmap;

    fn glXChooseVisual(dpy: *Display, screen: c_int, attribList: *c_int) -> *XVisualInfo;
    fn glXCreateContext(dpy: *Display, vis: *XVisualInfo, shareList: GLXContext, direct: Bool)
                        -> GLXContext;
    fn glXCreateGLXPixmap(dpy: *Display, vis: *XVisualInfo, pixmap: Pixmap) -> GLXPixmap;
    fn glXMakeContextCurrent(dpy: *Display, draw: GLXDrawable, read: GLXDrawable, ctx: GLXContext)
                             -> Bool;
}

// X11 macros

fn DefaultScreen(dpy: *Display) -> c_int {
    unsafe {
        (*dpy).default_screen
    }
}
fn RootWindow(dpy: *Display, scr: c_int) -> Window {
    unsafe {
        (*ScreenOfDisplay(dpy, scr)).root
    }
}
fn ScreenOfDisplay(dpy: *Display, scr: c_int) -> *Screen {
    unsafe {
        *ptr::offset(&(*dpy).screens, scr as int)
    }
}

// Implementation

/// Linux-specific interface to 3D graphics contexts.
pub struct GraphicsContext {
    priv display: *Display,
    priv pixmap: GLXPixmap,
    priv context: Arc<GLXContext>,
}

impl GraphicsContext {
    // Creates a new, possibly shared, GLX context.
	#[fixed_stack_segment]
    fn new_possibly_shared(share_context: Option<GraphicsContext>) -> GraphicsContext {
        let (display, visual, pixmap) = GraphicsContext::create_display_visual_and_pixmap();

        unsafe {
            let context = match share_context {
                None => glXCreateContext(display, visual, null(), 1),
                Some(share_context) => {
                    let native_share_context = share_context.native();
                    glXCreateContext(display, visual, *native_share_context.get(), 1)
                }
            };

            assert!(context != null());

            GraphicsContext {
                display: display,
                pixmap: pixmap,
                context: Arc::new(context),
            }
        }
    }

	#[fixed_stack_segment]
    fn create_display_visual_and_pixmap() -> (*Display, *XVisualInfo, GLXPixmap) {
        unsafe {
            // Get a connection.
            let display = XOpenDisplay(0);

            // Get an appropriate visual.
            let visual = glXChooseVisual(display, DefaultScreen(display), &ATTRIBUTES[0]);

            // Create the pixmap.
            let root_window = RootWindow(display, DefaultScreen(display));
            let pixmap = XCreatePixmap(display, root_window, 10, 10, 24);
            let glx_pixmap = glXCreateGLXPixmap(display, visual, pixmap);

            debug!("XCreatePixmap returned %?, glXCreateGLXPixmap returned %?",
                   pixmap,
                   glx_pixmap);

            (display, visual, glx_pixmap)
        }
    }
}

impl GraphicsContextMethods<GLXContext> for GraphicsContext {
    /// Wraps the given instance of the native GLX graphics context, bumping the reference count in
    /// the process.
    fn wrap(instance: Arc<GLXContext>) -> GraphicsContext {
        let (display, _, pixmap) = GraphicsContext::create_display_visual_and_pixmap();
        GraphicsContext {
            display: display,
            pixmap: pixmap,
            context: instance.clone(),
        }
    }

    /// Returns the underlying native 3D context.
    fn native(&self) -> Arc<GLXContext> {
        self.context.clone()
    }

    /// Creates a new offscreen 3D graphics context.
    fn new() -> GraphicsContext {
        GraphicsContext::new_possibly_shared(None)
    }

    /// Creates a new offscreen 3D graphics context shared with the given context.
    fn new_shared(share_context: GraphicsContext) -> GraphicsContext {
        GraphicsContext::new_possibly_shared(Some(share_context))
    }

    /// Makes this context the current context.
	#[fixed_stack_segment]
    fn make_current(&self) {
        unsafe {
            let result = glXMakeContextCurrent(self.display,
                                               self.pixmap,
                                               self.pixmap,
                                               *self.context.get());
            assert!(result != 0);
        }
    }
}

impl Clone for GraphicsContext {
    fn clone(&self) -> GraphicsContext {
        GraphicsContext {
            display: self.display,
            pixmap: self.pixmap,
            context: self.context.clone(),
        }
    }
}

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

use context::GraphicsContextMethods;

use std::libc::{c_char, c_int, c_long, c_uint, c_ulong, c_void};
use std::ptr::null;
use std::ptr;
use extra::arc::Arc;

// Constants.

static GLX_RGBA: c_int = 4;
static GLX_RED_SIZE: c_int = 8;
static GLX_GREEN_SIZE: c_int = 9;
static GLX_BLUE_SIZE: c_int = 10;
static GLX_DEPTH_SIZE: c_int = 12;

static ATTRIBUTES: [c_int, ..4] = [
    GLX_RGBA,
    GLX_DEPTH_SIZE, 24,
    0,
];

// External bindings to Xlib.

// Opaque structures.
struct _XPrivate;
struct _XrmHashBucketRec;
struct Depth;
struct GLXContextOpaque;
struct Visual;

// Sadly we need to copy some of this definition in here because the Xlib macros need to access it.
struct Display {
    ext_data: *XExtData,
    private1: *_XPrivate,
    fd: c_int,
    private2: c_int,
    proto_major_version: c_int,
    proto_minor_version: c_int,
    vendor: *c_char,
    private3: XID,
    private4: XID,
    private5: XID,
    private6: c_int,
    resource_alloc: *c_void,
    byte_order: c_int,
    bitmap_unit: c_int,
    bitmap_pad: c_int,
    bitmap_bit_order: c_int,
    nformats: c_int,
    pixmap_format: *ScreenFormat,
    private8: c_int,
    release: c_int,
    private9: *_XPrivate,
    private10: *_XPrivate,
    qlen: c_int,
    last_request_read: c_ulong,
    request: c_ulong,
    private11: XPointer,
    private12: XPointer,
    private13: XPointer,
    private14: XPointer,
    max_request_size: c_uint,
    db: *_XrmHashBucketRec,
    private15: *c_void,
    display_name: *c_char,

    // FIXME(pcwalton): These are needed for some reason...
    pad: *c_void,
    pad1: *c_void,

    default_screen: c_int,
    nscreens: c_int,
    screens: *Screen,
}

struct Screen {
    ext_data: *XExtData,
    display: *Display,
    root: Window,
    width: c_int,
    height: c_int,
    mwidth: c_int,
    mheight: c_int,
    ndepths: c_int,
    depths: *Depth,
    root_depth: c_int,
    root_visual: *Visual,
    default_gc: GC,
    cmap: Colormap,
    white_pixel: c_ulong,
    black_pixel: c_ulong,
    max_maps: c_int,
    min_maps: c_int,
    backing_store: c_int,
    save_unders: Bool,
    root_input_mask: c_long,
    pad: *c_void,
}

struct ScreenFormat;
struct XExtData;

struct XVisualInfo {
    visual: *Visual,
    visualid: VisualID,
    screen: c_int,
    depth: c_int,
    class: c_int,
    red_mask: c_ulong,
    green_mask: c_ulong,
    blue_mask: c_ulong,
    colormap_size: c_int,
    bits_per_rgb: c_int,
}

type Bool = c_int;
type Colormap = XID;
type Drawable = c_uint;                 // compatible with Window
type GC = *c_void;
type GLXContext = *GLXContextOpaque;
type GLXDrawable = c_uint;              // compatible with GLXPixmap
type GLXPixmap = c_uint;                // compatible with GLXDrawable
type Pixmap = c_uint;
type VisualID = c_ulong;
type Window = c_uint;                   // compatible with Drawable
type XID = c_uint;
type XPointer = *c_void;

#[link_args="-lX11 -lGL"]
#[nolink]
extern {
    fn XOpenDisplay(n: c_int) -> *Display;
    fn XCreatePixmap(display: *Display, d: Drawable, width: c_uint, height: c_uint, depth: c_uint)
                     -> Pixmap;

    fn glXChooseVisual(dpy: *Display, screen: c_int, attribList: *c_int) -> *XVisualInfo;
    fn glXCreateContext(dpy: *Display, vis: *XVisualInfo, shareList: GLXContext, direct: Bool)
                        -> GLXContext;
    fn glXCreateGLXPixmap(dpy: *Display, vis: *XVisualInfo, pixmap: Pixmap) -> GLXPixmap;
    fn glXMakeContextCurrent(dpy: *Display, draw: GLXDrawable, read: GLXDrawable, ctx: GLXContext)
                             -> Bool;
}

// X11 macros

fn DefaultScreen(dpy: *Display) -> c_int {
    unsafe {
        (*dpy).default_screen
    }
}
fn RootWindow(dpy: *Display, scr: c_int) -> Window {
    unsafe {
        (*ScreenOfDisplay(dpy, scr)).root
    }
}
fn ScreenOfDisplay(dpy: *Display, scr: c_int) -> *Screen {
    unsafe {
        *ptr::offset(&(*dpy).screens, scr as int)
    }
}

// Implementation

/// Linux-specific interface to 3D graphics contexts.
pub struct GraphicsContext {
    priv display: *Display,
    priv pixmap: GLXPixmap,
    priv context: Arc<GLXContext>,
}

impl GraphicsContext {
    // Creates a new, possibly shared, GLX context.
	#[fixed_stack_segment]
    fn new_possibly_shared(share_context: Option<GraphicsContext>) -> GraphicsContext {
        let (display, visual, pixmap) = GraphicsContext::create_display_visual_and_pixmap();

        unsafe {
            let context = match share_context {
                None => glXCreateContext(display, visual, null(), 1),
                Some(share_context) => {
                    let native_share_context = share_context.native();
                    glXCreateContext(display, visual, *native_share_context.get(), 1)
                }
            };

            assert!(context != null());

            GraphicsContext {
                display: display,
                pixmap: pixmap,
                context: Arc::new(context),
            }
        }
    }

	#[fixed_stack_segment]
    fn create_display_visual_and_pixmap() -> (*Display, *XVisualInfo, GLXPixmap) {
        unsafe {
            // Get a connection.
            let display = XOpenDisplay(0);

            // Get an appropriate visual.
            let visual = glXChooseVisual(display, DefaultScreen(display), &ATTRIBUTES[0]);

            // Create the pixmap.
            let root_window = RootWindow(display, DefaultScreen(display));
            let pixmap = XCreatePixmap(display, root_window, 10, 10, 24);
            let glx_pixmap = glXCreateGLXPixmap(display, visual, pixmap);

            debug!("XCreatePixmap returned {}, glXCreateGLXPixmap returned {}",
                   pixmap,
                   glx_pixmap);

            (display, visual, glx_pixmap)
        }
    }
}

impl GraphicsContextMethods<GLXContext> for GraphicsContext {
    /// Wraps the given instance of the native GLX graphics context, bumping the reference count in
    /// the process.
    fn wrap(instance: Arc<GLXContext>) -> GraphicsContext {
        let (display, _, pixmap) = GraphicsContext::create_display_visual_and_pixmap();
        GraphicsContext {
            display: display,
            pixmap: pixmap,
            context: instance.clone(),
        }
    }

    /// Returns the underlying native 3D context.
    fn native(&self) -> Arc<GLXContext> {
        self.context.clone()
    }

    /// Creates a new offscreen 3D graphics context.
    fn new() -> GraphicsContext {
        GraphicsContext::new_possibly_shared(None)
    }

    /// Creates a new offscreen 3D graphics context shared with the given context.
    fn new_shared(share_context: GraphicsContext) -> GraphicsContext {
        GraphicsContext::new_possibly_shared(Some(share_context))
    }

    /// Makes this context the current context.
	#[fixed_stack_segment]
    fn make_current(&self) {
        unsafe {
            let result = glXMakeContextCurrent(self.display,
                                               self.pixmap,
                                               self.pixmap,
                                               *self.context.get());
            assert!(result != 0);
        }
    }
}

impl Clone for GraphicsContext {
    fn clone(&self) -> GraphicsContext {
        GraphicsContext {
            display: self.display,
            pixmap: self.pixmap,
            context: self.context.clone(),
        }
    }
}

<|endoftext|>


<commit_before>extern crate ra_syntax;
#[macro_use]
extern crate test_utils;
extern crate walkdir;

use std::{
    fmt::Write,
    fs,
    path::{Path, PathBuf, Component},
};

use ra_syntax::{
    utils::{check_fuzz_invariants, dump_tree},
    SourceFileNode,
};

#[test]
fn lexer_tests() {
    dir_tests(&["lexer"], |text| {
        let tokens = ra_syntax::tokenize(text);
        dump_tokens(&tokens, text)
    })
}

#[test]
fn parser_tests() {
    dir_tests(&["parser/inline", "parser/ok", "parser/err"], |text| {
        let file = SourceFileNode::parse(text);
        dump_tree(file.syntax())
    })
}

#[test]
fn parser_fuzz_tests() {
    for (_, text) in collect_tests(&["parser/fuzz-failures"]) {
        check_fuzz_invariants(&text)
    }
}

/// Test that Rust-analyzer can parse and validate the rust-analyser
/// TODO: Use this as a benchmark
#[test]
fn self_hosting_parsing() {
    use std::ffi::OsStr;
    let empty_vec = vec![];
    let dir = project_dir().join("crates");
    let mut count = 0;
    for entry in walkdir::WalkDir::new(dir)
        .into_iter()
        .filter_entry(|entry| {
            !entry
                .path()
                .components()
                // TODO: this more neatly
                .any(|component| {
                    // Get all files which are not in the crates/ra_syntax/tests/data folder
                    component == Component::Normal(OsStr::new("data"))
                })
        })
        .map(|e| e.unwrap())
        .filter(|entry| {
            // Get all `.rs ` files
            !entry.path().is_dir() && (entry.path().extension() == Some(OsStr::new("rs")))
        })
    {
        count += 1;
        let text = read_text(entry.path());
        let node = SourceFileNode::parse(&text);
        let errors = node.errors();
        assert_eq!(
            errors, empty_vec,
            "There should be no errors in the file {:?}",
            entry
        );
    }
    assert!(
        count > 30,
        "self_hosting_parsing found too few files - is it running in the right directory?"
    )
}
/// Read file and normalize newlines.
///
/// `rustc` seems to always normalize `\r\n` newlines to `\n`:
///
/// ```
/// let s = "
/// ";
/// assert_eq!(s.as_bytes(), &[10]);
/// ```
///
/// so this should always be correct.
fn read_text(path: &Path) -> String {
    fs::read_to_string(path)
        .expect(&format!("File at {:?} should be valid", path))
        .replace("\r\n", "\n")
}

pub fn dir_tests<F>(paths: &[&str], f: F)
where
    F: Fn(&str) -> String,
{
    for (path, input_code) in collect_tests(paths) {
        let parse_tree = f(&input_code);
        let path = path.with_extension("txt");
        if !path.exists() {
            println!("\nfile: {}", path.display());
            println!("No .txt file with expected result, creating...\n");
            println!("{}\n{}", input_code, parse_tree);
            fs::write(&path, parse_tree).unwrap();
            panic!("No expected result")
        }
        let expected = read_text(&path);
        let expected = expected.as_str();
        let parse_tree = parse_tree.as_str();
        assert_equal_text(expected, parse_tree, &path);
    }
}

const REWRITE: bool = false;

fn assert_equal_text(expected: &str, actual: &str, path: &Path) {
    if expected == actual {
        return;
    }
    let dir = project_dir();
    let pretty_path = path.strip_prefix(&dir).unwrap_or_else(|_| path);
    if expected.trim() == actual.trim() {
        println!("whitespace difference, rewriting");
        println!("file: {}\n", pretty_path.display());
        fs::write(path, actual).unwrap();
        return;
    }
    if REWRITE {
        println!("rewriting {}", pretty_path.display());
        fs::write(path, actual).unwrap();
        return;
    }
    assert_eq_text!(expected, actual, "file: {}", pretty_path.display());
}

fn collect_tests(paths: &[&str]) -> Vec<(PathBuf, String)> {
    paths
        .iter()
        .flat_map(|path| {
            let path = test_data_dir().join(path);
            test_from_dir(&path).into_iter()
        })
        .map(|path| {
            let text = read_text(&path);
            (path, text)
        })
        .collect()
}

fn test_from_dir(dir: &Path) -> Vec<PathBuf> {
    let mut acc = Vec::new();
    for file in fs::read_dir(&dir).unwrap() {
        let file = file.unwrap();
        let path = file.path();
        if path.extension().unwrap_or_default() == "rs" {
            acc.push(path);
        }
    }
    acc.sort();
    acc
}

fn project_dir() -> PathBuf {
    let dir = env!("CARGO_MANIFEST_DIR");
    PathBuf::from(dir)
        .parent()
        .unwrap()
        .parent()
        .unwrap()
        .to_owned()
}

fn test_data_dir() -> PathBuf {
    project_dir().join("crates/ra_syntax/tests/data")
}

fn dump_tokens(tokens: &[ra_syntax::Token], text: &str) -> String {
    let mut acc = String::new();
    let mut offset = 0;
    for token in tokens {
        let len: u32 = token.len.into();
        let len = len as usize;
        let token_text = &text[offset..offset + len];
        offset += len;
        write!(acc, "{:?} {} {:?}\n", token.kind, token.len, token_text).unwrap()
    }
    acc
}
<commit_msg>Ensure that the parser tests pass or fail correctly<commit_after>extern crate ra_syntax;
#[macro_use]
extern crate test_utils;
extern crate walkdir;

use std::{
    fmt::Write,
    fs,
    path::{Path, PathBuf, Component},
};

use ra_syntax::{
    utils::{check_fuzz_invariants, dump_tree},
    SourceFileNode,
};

#[test]
fn lexer_tests() {
    dir_tests(&["lexer"], |text, _| {
        let tokens = ra_syntax::tokenize(text);
        dump_tokens(&tokens, text)
    })
}

#[test]
fn parser_tests() {
    dir_tests(&["parser/inline", "parser/ok"], |text, path| {
        let file = SourceFileNode::parse(text);
        let errors = file.errors();
        assert_eq!(
            &*errors,
            &[] as &[ra_syntax::SyntaxError],
            "There should be no errors in the file {:?}",
            path.display()
        );
        dump_tree(file.syntax())
    });
    dir_tests(&["parser/err"], |text, path| {
        let file = SourceFileNode::parse(text);
        let errors = file.errors();
        assert_ne!(
            &*errors,
            &[] as &[ra_syntax::SyntaxError],
            "There should be errors in the file {:?}",
            path.display()
        );
        dump_tree(file.syntax())
    });
}

#[test]
fn parser_fuzz_tests() {
    for (_, text) in collect_tests(&["parser/fuzz-failures"]) {
        check_fuzz_invariants(&text)
    }
}

/// Test that Rust-analyzer can parse and validate the rust-analyser
/// TODO: Use this as a benchmark
#[test]
fn self_hosting_parsing() {
    use std::ffi::OsStr;
    let dir = project_dir().join("crates");
    let mut count = 0;
    for entry in walkdir::WalkDir::new(dir)
        .into_iter()
        .filter_entry(|entry| {
            !entry
                .path()
                .components()
                // TODO: this more neatly
                .any(|component| {
                    // Get all files which are not in the crates/ra_syntax/tests/data folder
                    component == Component::Normal(OsStr::new("data"))
                })
        })
        .map(|e| e.unwrap())
        .filter(|entry| {
            // Get all `.rs ` files
            !entry.path().is_dir() && (entry.path().extension() == Some(OsStr::new("rs")))
        })
    {
        count += 1;
        let text = read_text(entry.path());
        let node = SourceFileNode::parse(&text);
        let errors = node.errors();
        assert_eq!(
            &*errors,
            &[],
            "There should be no errors in the file {:?}",
            entry
        );
    }
    assert!(
        count > 30,
        "self_hosting_parsing found too few files - is it running in the right directory?"
    )
}
/// Read file and normalize newlines.
///
/// `rustc` seems to always normalize `\r\n` newlines to `\n`:
///
/// ```
/// let s = "
/// ";
/// assert_eq!(s.as_bytes(), &[10]);
/// ```
///
/// so this should always be correct.
fn read_text(path: &Path) -> String {
    fs::read_to_string(path)
        .expect(&format!("File at {:?} should be valid", path))
        .replace("\r\n", "\n")
}

fn dir_tests<F>(paths: &[&str], f: F)
where
    F: Fn(&str, &Path) -> String,
{
    for (path, input_code) in collect_tests(paths) {
        let parse_tree = f(&input_code, &path);
        let path = path.with_extension("txt");
        if !path.exists() {
            println!("\nfile: {}", path.display());
            println!("No .txt file with expected result, creating...\n");
            println!("{}\n{}", input_code, parse_tree);
            fs::write(&path, parse_tree).unwrap();
            panic!("No expected result")
        }
        let expected = read_text(&path);
        let expected = expected.as_str();
        let parse_tree = parse_tree.as_str();
        assert_equal_text(expected, parse_tree, &path);
    }
}

const REWRITE: bool = false;

fn assert_equal_text(expected: &str, actual: &str, path: &Path) {
    if expected == actual {
        return;
    }
    let dir = project_dir();
    let pretty_path = path.strip_prefix(&dir).unwrap_or_else(|_| path);
    if expected.trim() == actual.trim() {
        println!("whitespace difference, rewriting");
        println!("file: {}\n", pretty_path.display());
        fs::write(path, actual).unwrap();
        return;
    }
    if REWRITE {
        println!("rewriting {}", pretty_path.display());
        fs::write(path, actual).unwrap();
        return;
    }
    assert_eq_text!(expected, actual, "file: {}", pretty_path.display());
}

fn collect_tests(paths: &[&str]) -> Vec<(PathBuf, String)> {
    paths
        .iter()
        .flat_map(|path| {
            let path = test_data_dir().join(path);
            test_from_dir(&path).into_iter()
        })
        .map(|path| {
            let text = read_text(&path);
            (path, text)
        })
        .collect()
}

fn test_from_dir(dir: &Path) -> Vec<PathBuf> {
    let mut acc = Vec::new();
    for file in fs::read_dir(&dir).unwrap() {
        let file = file.unwrap();
        let path = file.path();
        if path.extension().unwrap_or_default() == "rs" {
            acc.push(path);
        }
    }
    acc.sort();
    acc
}

fn project_dir() -> PathBuf {
    let dir = env!("CARGO_MANIFEST_DIR");
    PathBuf::from(dir)
        .parent()
        .unwrap()
        .parent()
        .unwrap()
        .to_owned()
}

fn test_data_dir() -> PathBuf {
    project_dir().join("crates/ra_syntax/tests/data")
}

fn dump_tokens(tokens: &[ra_syntax::Token], text: &str) -> String {
    let mut acc = String::new();
    let mut offset = 0;
    for token in tokens {
        let len: u32 = token.len.into();
        let len = len as usize;
        let token_text = &text[offset..offset + len];
        offset += len;
        write!(acc, "{:?} {} {:?}\n", token.kind, token.len, token_text).unwrap()
    }
    acc
}
<|endoftext|>


<commit_before>//! Collect definitions for `Residue` and `SheetConf` objects
//! into a `DataBase` which can be read from or saved to disk.

use coord::{Coord, Translate};
use describe::{describe_list_short, describe_list, Describe};
use iterator::AtomIterItem;
use surface;
use system::{Component, Residue};
use volume;

use serde_json;
use std::fmt::Write;
use std::io;
use std::path::{Path, PathBuf};
use std::ffi::OsStr;
use std::fs::File;
use std::result;

#[derive(Copy, Clone, Debug)]
pub enum DataBaseError {
    BadPath,
}

#[macro_export]
/// Macro to wrap every object constructor into an enum with desired traits.
///
/// The traits are those important for the creation and display of system components.
/// The enum is used to hold created objects of different types in one container,
/// sharing one interface.
///
/// Implements `Describe`, `Component` and `Translate` for the enum. Also sets up
/// some getter functions directly to the object data.
///
/// # Requires
/// Wrapped objects have to implement the above traits and `Clone`, `Debug`,
/// `Deserialize` and `Serialize` (the last two from `serde`).
///
/// # Examples
/// Create two objects and let the macro create the wrapper and implement the traits for it.
///
/// ```
/// # #[macro_use] extern crate grafen;
/// # extern crate serde_json;
/// # #[macro_use] extern crate serde_derive;
/// # use grafen::coord::{Coord, Translate};
/// # use grafen::describe::Describe;
/// # use grafen::iterator::{AtomIterator, AtomIterItem};
/// # use grafen::system::{Component, Residue};
/// #
/// #[derive(Clone, Debug, Deserialize, Serialize)]
/// pub struct StructOne {
///     origin: Coord,
///     residue: Option<Residue>,
///     coords: Vec<Coord>
/// }
///
/// #[derive(Clone, Debug, Deserialize, Serialize)]
/// pub struct StructTwo {
///     origin: Coord,
///     residue: Option<Residue>,
///     coords: Vec<Coord>
/// }
///
/// // Not shown: implement required traits
/// # impl StructOne { fn calc_box_size(&self) -> Coord { Coord::default() } }
/// # impl StructTwo { fn calc_box_size(&self) -> Coord { Coord::default() } }
/// # impl Describe for StructOne {
/// #     fn describe(&self) -> String { "StructOne".to_string() }
/// #     fn describe_short(&self) -> String { self.describe() }
/// # }
/// # impl Describe for StructTwo {
/// #     fn describe(&self) -> String { "StructTwo".to_string() }
/// #     fn describe_short(&self) -> String { self.describe() }
/// # }
/// # impl_component![StructOne, StructTwo];
/// # impl_translate![StructOne, StructTwo];
///
/// // Construct the wrapping enum container
/// create_entry_wrapper![
///     Wrapper, // enum identifier
///     (StructOne => One), // Wrapper::One(StructOne)
///     (StructTwo => Two)  // Wrapper::Two(StructTwo)
/// ];
///
/// #
/// # fn main() {
/// let objects = vec![
///     Wrapper::One(StructOne {
///         origin: Coord::default(),
///         residue: None,
///         coords: vec![]
///     }),
///     Wrapper::Two(StructTwo {
///         origin: Coord::default(),
///         residue: None,
///         coords: vec![]
///     })
/// ];
///
/// assert_eq!("StructOne", &objects[0].describe());
/// assert_eq!(None, objects[0].iter_atoms().next());
///
/// assert_eq!("StructTwo", &objects[1].describe());
/// assert_eq!(None, objects[1].iter_atoms().next());
/// # }
/// ```
macro_rules! create_entry_wrapper {
    (
        $name:ident, // enum Identifier
        $( ($class:path => $entry:ident) ),+ // Identifier::Entry(Class)
    ) => {
        #[derive(Clone, Debug, Deserialize, Serialize)]
        /// Wrapper for accessing a shared interface from different components constructors.
        pub enum $name {
            $(
                $entry($class),
            )*
        }

        /// Getter function of linked data.
        impl<'a> $name {
            /// Get a reference to the coordinates of the component.
            pub fn get_coords(&'a self) -> &[Coord] {
                match *self {
                    $(
                        $name::$entry(ref object) => &object.coords,
                    )*
                }
            }

            pub fn get_coords_mut(&'a mut self) -> &mut Vec<Coord> {
                match *self {
                    $(
                        $name::$entry(ref mut object) => &mut object.coords,
                    )*
                }
            }

            /// Get a reference to the component's optional `Residue`.
            pub fn get_residue(&'a self) -> &'a Option<Residue> {
                match *self {
                    $(
                        $name::$entry(ref object) => &object.residue,
                    )*
                }
            }
        }

        impl Describe for $name {
            fn describe(&self) -> String {
                match *self {
                    $(
                        $name::$entry(ref object) => object.describe(),
                    )*
                }
            }

            fn describe_short(&self) -> String {
                match *self {
                    $(
                        $name::$entry(ref object) => object.describe_short(),
                    )*
                }
            }
        }

        impl<'a> Component<'a> for $name {
            fn box_size(&self) -> Coord {
                match *self {
                    $(
                        $name::$entry(ref object) => object.box_size(),
                    )*
                }
            }

            fn iter_atoms(&'a self) -> AtomIterItem {
                match *self {
                    $(
                        $name::$entry(ref object) => object.iter_atoms(),
                    )*
                }
            }

            fn num_atoms(&self) -> u64 {
                match *self {
                    $(
                        $name::$entry(ref object) => object.num_atoms(),
                    )*
                }
            }
        }

        impl Translate for $name {
            fn translate(self, coord: Coord) -> Self {
                match self {
                    $(
                        $name::$entry(object) => $name::$entry(object.translate(coord)),
                    )*
                }
            }

            fn translate_in_place(&mut self, coord: Coord) {
                match *self {
                    $(
                        $name::$entry(ref mut object)
                            => { object.translate_in_place(coord); }
                    )*
                }
            }
        }
    }
}

// Our wrapper for object constructors is `ComponentEntry`. Use the macro to construct it.
create_entry_wrapper![
    ComponentEntry,
    (volume::Cuboid => VolumeCuboid),
    (volume::Cylinder => VolumeCylinder),
    (surface::Sheet => SurfaceSheet),
    (surface::Cylinder => SurfaceCylinder)
];

#[derive(Clone, Debug, Deserialize, Serialize)]
/// A collection of residues and substrate configurations
/// which can be saved to and read from disk.
pub struct DataBase {
    #[serde(skip)]
    /// A path to the `DataBase` location on the hard drive.
    pub path: Option<PathBuf>,

    #[serde(rename = "residue_definitions", default = "Vec::new")]
    /// Definitions of `Residue` objects.
    pub residue_defs: Vec<Residue>,

    #[serde(rename = "component_definitions", default = "Vec::new")]
    /// New component constructors.
    pub component_defs: Vec<ComponentEntry>,
}

impl DataBase {
    /// Construct an empty `DataBase`.
    pub fn new() -> DataBase {
        DataBase {
            path: None,
            residue_defs: vec![],
            component_defs: vec![],
        }
    }

    /// Get the database path enclosed in single quotes if it exists,
    /// otherwise the unenclosed string "None".
    pub fn get_path_pretty(&self) -> String {
        self.path.as_ref()
            .map(|path| path.to_string_lossy().to_owned())
            .map(|path| format!("'{}'", path))
            .unwrap_or("None".to_string())
    }

    /// Set a new path for the `DataBase`. The input path is asserted to
    /// be a file and the extension is set to 'json'.
    pub fn set_path<T>(&mut self, new_path: &T) -> Result<(), DataBaseError>
            where T: ?Sized + AsRef<OsStr> {
        let mut path = PathBuf::from(new_path);

        if path.file_stem().is_some() {
            path.set_extension("json");
            self.path = Some(path);
            Ok(())
        } else {
            Err(DataBaseError::BadPath)
        }
    }

    /// Parse a reader for a JSON formatted `DataBase`.
    ///
    /// This and the `to_writer` method are defined to enable a unit
    /// test which ensures that the behaviour for reading and writing
    /// a `DataBase` is consistent.
    fn from_reader<R: io::Read>(reader: R) -> Result<DataBase, io::Error> {
        serde_json::from_reader(reader).map_err(|e| io::Error::from(e))
    }

    /// Write a `DataBase` as a JSON formatted object to an input writer.
    fn to_writer<W: io::Write>(&self, writer: &mut W) -> result::Result<(), io::Error> {
        serde_json::to_writer_pretty(writer, self).map_err(|e| io::Error::from(e))
    }
}

impl Describe for DataBase {
    fn describe(&self) -> String {
        let mut description = String::new();
        const ERR: &'static str = "Could not construct a string";

        writeln!(description, "Database path: {}\n", self.get_path_pretty()).expect(ERR);
        writeln!(description, "{}", describe_list_short("Component definitions", &self.component_defs)).expect(ERR);
        writeln!(description, "{}", describe_list("Residue definitions", &self.residue_defs)).expect(ERR);

        description
    }

    fn describe_short(&self) -> String {
        self.describe()
    }
}

/// Read a `DataBase` from a JSON formatted file.
/// The owned path is set to the input path.
pub fn read_database(from_path: &str) -> Result<DataBase, io::Error> {
    let path = Path::new(from_path);
    let buffer = File::open(&path)?;

    let mut database = DataBase::from_reader(buffer)?;
    database.path = Some(PathBuf::from(&from_path));

    Ok(database)
}

/// Write a `DataBase` as a JSON formatted file.
/// The function writes to that owned by the object.
pub fn write_database(database: &DataBase) -> Result<(), io::Error> {
    if let Some(ref path) = database.path {
        let mut buffer = File::create(&path)?;
        database.to_writer(&mut buffer)?;

        return Ok(());
    }

    Err(io::Error::new(
        io::ErrorKind::Other,
        "No path was set when trying to write the database to disk")
    )
}

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

    #[test]
    fn serialize_and_deserialize_residue_entry() {
        let base = Residue {
            code: "RES".to_string(),
            atoms: vec![
                Atom { code: "A1".to_string(), position: Coord::new(0.0, 1.0, 2.0) },
                Atom { code: "A2".to_string(), position: Coord::new(3.0, 4.0, 5.0) },
            ]
        };

        let serialized = serde_json::to_string(&base).unwrap();
        let deserialized: Residue = serde_json::from_str(&serialized).unwrap();

        assert_eq!(base, deserialized);
    }

    #[test]
    fn database_by_default_sets_empty_vectors_if_not_available() {
        let database: DataBase = serde_json::from_str("{}").unwrap();
        assert!(database.residue_defs.is_empty());
        assert!(database.component_defs.is_empty());
    }

    #[test]
    fn read_and_write_database() {
        let base = Residue {
            code: "RES".to_string(),
            atoms: vec![
                Atom { code: "A1".to_string(), position: Coord::new(0.0, 1.0, 2.0) },
                Atom { code: "A2".to_string(), position: Coord::new(3.0, 4.0, 5.0) },
            ]
        };

        let database = DataBase {
            path: Some(PathBuf::from("This/will/be/removed")),
            residue_defs: vec![base.clone()],
            component_defs: vec![],
        };

        let mut serialized: Vec<u8> = Vec::new();
        database.to_writer(&mut serialized).unwrap();
        let deserialized = DataBase::from_reader(serialized.as_slice()).unwrap();

        assert_eq!(None, deserialized.path);
        assert_eq!(database.residue_defs, deserialized.residue_defs);
    }

    #[test]
    fn set_database_path() {
        let mut database = DataBase::new();
        assert!(database.set_path("test").is_ok());
        assert_eq!("test.json", database.path.unwrap().to_str().unwrap());
    }

    #[test]
    fn set_database_to_empty_path_is_error() {
        let mut database = DataBase::new();
        database.path = Some(PathBuf::from("unchanged.json"));
        assert!(database.set_path("").is_err());
        assert_eq!("unchanged.json", database.path.unwrap().to_str().unwrap());
    }

    #[cfg(unix)]
    #[test]
    fn get_database_path() {
        let mut database = DataBase::new();
        assert_eq!("None", &database.get_path_pretty());

        database.set_path("/a/file.json").unwrap();
        assert_eq!("'/a/file.json'", &database.get_path_pretty());
    }
}
<commit_msg>Add documentation comment to mutable coordinate getter of `ComponentEntry`<commit_after>//! Collect definitions for `Residue` and `SheetConf` objects
//! into a `DataBase` which can be read from or saved to disk.

use coord::{Coord, Translate};
use describe::{describe_list_short, describe_list, Describe};
use iterator::AtomIterItem;
use surface;
use system::{Component, Residue};
use volume;

use serde_json;
use std::fmt::Write;
use std::io;
use std::path::{Path, PathBuf};
use std::ffi::OsStr;
use std::fs::File;
use std::result;

#[derive(Copy, Clone, Debug)]
pub enum DataBaseError {
    BadPath,
}

#[macro_export]
/// Macro to wrap every object constructor into an enum with desired traits.
///
/// The traits are those important for the creation and display of system components.
/// The enum is used to hold created objects of different types in one container,
/// sharing one interface.
///
/// Implements `Describe`, `Component` and `Translate` for the enum. Also sets up
/// some getter functions directly to the object data.
///
/// # Requires
/// Wrapped objects have to implement the above traits and `Clone`, `Debug`,
/// `Deserialize` and `Serialize` (the last two from `serde`).
///
/// # Examples
/// Create two objects and let the macro create the wrapper and implement the traits for it.
///
/// ```
/// # #[macro_use] extern crate grafen;
/// # extern crate serde_json;
/// # #[macro_use] extern crate serde_derive;
/// # use grafen::coord::{Coord, Translate};
/// # use grafen::describe::Describe;
/// # use grafen::iterator::{AtomIterator, AtomIterItem};
/// # use grafen::system::{Component, Residue};
/// #
/// #[derive(Clone, Debug, Deserialize, Serialize)]
/// pub struct StructOne {
///     origin: Coord,
///     residue: Option<Residue>,
///     coords: Vec<Coord>
/// }
///
/// #[derive(Clone, Debug, Deserialize, Serialize)]
/// pub struct StructTwo {
///     origin: Coord,
///     residue: Option<Residue>,
///     coords: Vec<Coord>
/// }
///
/// // Not shown: implement required traits
/// # impl StructOne { fn calc_box_size(&self) -> Coord { Coord::default() } }
/// # impl StructTwo { fn calc_box_size(&self) -> Coord { Coord::default() } }
/// # impl Describe for StructOne {
/// #     fn describe(&self) -> String { "StructOne".to_string() }
/// #     fn describe_short(&self) -> String { self.describe() }
/// # }
/// # impl Describe for StructTwo {
/// #     fn describe(&self) -> String { "StructTwo".to_string() }
/// #     fn describe_short(&self) -> String { self.describe() }
/// # }
/// # impl_component![StructOne, StructTwo];
/// # impl_translate![StructOne, StructTwo];
///
/// // Construct the wrapping enum container
/// create_entry_wrapper![
///     Wrapper, // enum identifier
///     (StructOne => One), // Wrapper::One(StructOne)
///     (StructTwo => Two)  // Wrapper::Two(StructTwo)
/// ];
///
/// #
/// # fn main() {
/// let objects = vec![
///     Wrapper::One(StructOne {
///         origin: Coord::default(),
///         residue: None,
///         coords: vec![]
///     }),
///     Wrapper::Two(StructTwo {
///         origin: Coord::default(),
///         residue: None,
///         coords: vec![]
///     })
/// ];
///
/// assert_eq!("StructOne", &objects[0].describe());
/// assert_eq!(None, objects[0].iter_atoms().next());
///
/// assert_eq!("StructTwo", &objects[1].describe());
/// assert_eq!(None, objects[1].iter_atoms().next());
/// # }
/// ```
macro_rules! create_entry_wrapper {
    (
        $name:ident, // enum Identifier
        $( ($class:path => $entry:ident) ),+ // Identifier::Entry(Class)
    ) => {
        #[derive(Clone, Debug, Deserialize, Serialize)]
        /// Wrapper for accessing a shared interface from different components constructors.
        pub enum $name {
            $(
                $entry($class),
            )*
        }

        /// Getter function of linked data.
        impl<'a> $name {
            /// Get a reference to the coordinates of the component.
            pub fn get_coords(&'a self) -> &[Coord] {
                match *self {
                    $(
                        $name::$entry(ref object) => &object.coords,
                    )*
                }
            }

            /// Get a mutable reference to the coordinates of the component.
            pub fn get_coords_mut(&'a mut self) -> &mut Vec<Coord> {
                match *self {
                    $(
                        $name::$entry(ref mut object) => &mut object.coords,
                    )*
                }
            }

            /// Get a reference to the component's optional `Residue`.
            pub fn get_residue(&'a self) -> &'a Option<Residue> {
                match *self {
                    $(
                        $name::$entry(ref object) => &object.residue,
                    )*
                }
            }
        }

        impl Describe for $name {
            fn describe(&self) -> String {
                match *self {
                    $(
                        $name::$entry(ref object) => object.describe(),
                    )*
                }
            }

            fn describe_short(&self) -> String {
                match *self {
                    $(
                        $name::$entry(ref object) => object.describe_short(),
                    )*
                }
            }
        }

        impl<'a> Component<'a> for $name {
            fn box_size(&self) -> Coord {
                match *self {
                    $(
                        $name::$entry(ref object) => object.box_size(),
                    )*
                }
            }

            fn iter_atoms(&'a self) -> AtomIterItem {
                match *self {
                    $(
                        $name::$entry(ref object) => object.iter_atoms(),
                    )*
                }
            }

            fn num_atoms(&self) -> u64 {
                match *self {
                    $(
                        $name::$entry(ref object) => object.num_atoms(),
                    )*
                }
            }
        }

        impl Translate for $name {
            fn translate(self, coord: Coord) -> Self {
                match self {
                    $(
                        $name::$entry(object) => $name::$entry(object.translate(coord)),
                    )*
                }
            }

            fn translate_in_place(&mut self, coord: Coord) {
                match *self {
                    $(
                        $name::$entry(ref mut object)
                            => { object.translate_in_place(coord); }
                    )*
                }
            }
        }
    }
}

// Our wrapper for object constructors is `ComponentEntry`. Use the macro to construct it.
create_entry_wrapper![
    ComponentEntry,
    (volume::Cuboid => VolumeCuboid),
    (volume::Cylinder => VolumeCylinder),
    (surface::Sheet => SurfaceSheet),
    (surface::Cylinder => SurfaceCylinder)
];

#[derive(Clone, Debug, Deserialize, Serialize)]
/// A collection of residues and substrate configurations
/// which can be saved to and read from disk.
pub struct DataBase {
    #[serde(skip)]
    /// A path to the `DataBase` location on the hard drive.
    pub path: Option<PathBuf>,

    #[serde(rename = "residue_definitions", default = "Vec::new")]
    /// Definitions of `Residue` objects.
    pub residue_defs: Vec<Residue>,

    #[serde(rename = "component_definitions", default = "Vec::new")]
    /// New component constructors.
    pub component_defs: Vec<ComponentEntry>,
}

impl DataBase {
    /// Construct an empty `DataBase`.
    pub fn new() -> DataBase {
        DataBase {
            path: None,
            residue_defs: vec![],
            component_defs: vec![],
        }
    }

    /// Get the database path enclosed in single quotes if it exists,
    /// otherwise the unenclosed string "None".
    pub fn get_path_pretty(&self) -> String {
        self.path.as_ref()
            .map(|path| path.to_string_lossy().to_owned())
            .map(|path| format!("'{}'", path))
            .unwrap_or("None".to_string())
    }

    /// Set a new path for the `DataBase`. The input path is asserted to
    /// be a file and the extension is set to 'json'.
    pub fn set_path<T>(&mut self, new_path: &T) -> Result<(), DataBaseError>
            where T: ?Sized + AsRef<OsStr> {
        let mut path = PathBuf::from(new_path);

        if path.file_stem().is_some() {
            path.set_extension("json");
            self.path = Some(path);
            Ok(())
        } else {
            Err(DataBaseError::BadPath)
        }
    }

    /// Parse a reader for a JSON formatted `DataBase`.
    ///
    /// This and the `to_writer` method are defined to enable a unit
    /// test which ensures that the behaviour for reading and writing
    /// a `DataBase` is consistent.
    fn from_reader<R: io::Read>(reader: R) -> Result<DataBase, io::Error> {
        serde_json::from_reader(reader).map_err(|e| io::Error::from(e))
    }

    /// Write a `DataBase` as a JSON formatted object to an input writer.
    fn to_writer<W: io::Write>(&self, writer: &mut W) -> result::Result<(), io::Error> {
        serde_json::to_writer_pretty(writer, self).map_err(|e| io::Error::from(e))
    }
}

impl Describe for DataBase {
    fn describe(&self) -> String {
        let mut description = String::new();
        const ERR: &'static str = "Could not construct a string";

        writeln!(description, "Database path: {}\n", self.get_path_pretty()).expect(ERR);
        writeln!(description, "{}", describe_list_short("Component definitions", &self.component_defs)).expect(ERR);
        writeln!(description, "{}", describe_list("Residue definitions", &self.residue_defs)).expect(ERR);

        description
    }

    fn describe_short(&self) -> String {
        self.describe()
    }
}

/// Read a `DataBase` from a JSON formatted file.
/// The owned path is set to the input path.
pub fn read_database(from_path: &str) -> Result<DataBase, io::Error> {
    let path = Path::new(from_path);
    let buffer = File::open(&path)?;

    let mut database = DataBase::from_reader(buffer)?;
    database.path = Some(PathBuf::from(&from_path));

    Ok(database)
}

/// Write a `DataBase` as a JSON formatted file.
/// The function writes to that owned by the object.
pub fn write_database(database: &DataBase) -> Result<(), io::Error> {
    if let Some(ref path) = database.path {
        let mut buffer = File::create(&path)?;
        database.to_writer(&mut buffer)?;

        return Ok(());
    }

    Err(io::Error::new(
        io::ErrorKind::Other,
        "No path was set when trying to write the database to disk")
    )
}

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

    #[test]
    fn serialize_and_deserialize_residue_entry() {
        let base = Residue {
            code: "RES".to_string(),
            atoms: vec![
                Atom { code: "A1".to_string(), position: Coord::new(0.0, 1.0, 2.0) },
                Atom { code: "A2".to_string(), position: Coord::new(3.0, 4.0, 5.0) },
            ]
        };

        let serialized = serde_json::to_string(&base).unwrap();
        let deserialized: Residue = serde_json::from_str(&serialized).unwrap();

        assert_eq!(base, deserialized);
    }

    #[test]
    fn database_by_default_sets_empty_vectors_if_not_available() {
        let database: DataBase = serde_json::from_str("{}").unwrap();
        assert!(database.residue_defs.is_empty());
        assert!(database.component_defs.is_empty());
    }

    #[test]
    fn read_and_write_database() {
        let base = Residue {
            code: "RES".to_string(),
            atoms: vec![
                Atom { code: "A1".to_string(), position: Coord::new(0.0, 1.0, 2.0) },
                Atom { code: "A2".to_string(), position: Coord::new(3.0, 4.0, 5.0) },
            ]
        };

        let database = DataBase {
            path: Some(PathBuf::from("This/will/be/removed")),
            residue_defs: vec![base.clone()],
            component_defs: vec![],
        };

        let mut serialized: Vec<u8> = Vec::new();
        database.to_writer(&mut serialized).unwrap();
        let deserialized = DataBase::from_reader(serialized.as_slice()).unwrap();

        assert_eq!(None, deserialized.path);
        assert_eq!(database.residue_defs, deserialized.residue_defs);
    }

    #[test]
    fn set_database_path() {
        let mut database = DataBase::new();
        assert!(database.set_path("test").is_ok());
        assert_eq!("test.json", database.path.unwrap().to_str().unwrap());
    }

    #[test]
    fn set_database_to_empty_path_is_error() {
        let mut database = DataBase::new();
        database.path = Some(PathBuf::from("unchanged.json"));
        assert!(database.set_path("").is_err());
        assert_eq!("unchanged.json", database.path.unwrap().to_str().unwrap());
    }

    #[cfg(unix)]
    #[test]
    fn get_database_path() {
        let mut database = DataBase::new();
        assert_eq!("None", &database.get_path_pretty());

        database.set_path("/a/file.json").unwrap();
        assert_eq!("'/a/file.json'", &database.get_path_pretty());
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "chrono_time")]
use chrono::prelude::*;
#[cfg(not(feature = "chrono_time"))]
use time::strptime;
use time::{Tm, strftime};
use super::Object;

const TIME_FMT_DECODE_STR: &str = "%Y%m%d%H%M%S%z";

#[cfg(feature = "chrono_time")]
impl From<DateTime<Local>> for Object {
	fn from(date: DateTime<Local>) -> Self {
		let mut timezone_str = date.format("D:%Y%m%d%H%M%S%:z'").to_string().into_bytes();
		convert_utc_offset(&mut timezone_str);
		Object::string_literal(timezone_str)
	}
}

// Find the last `:` and turn it into an `'` to account for PDF weirdness
fn convert_utc_offset(bytes: &mut [u8]) {
	let mut index = bytes.len();
	while let Some(last) = bytes[..index].last_mut() {
		if *last == b':' {
			*last = b'\'';
			break;
		}
		index -= 1;
	}
}

#[cfg(feature = "chrono_time")]
impl From<DateTime<UTC>> for Object {
	fn from(date: DateTime<UTC>) -> Self {
		Object::string_literal(date.format("D:%Y%m%d%H%M%SZ").to_string())
	}
}

impl From<Tm> for Object {
	fn from(date: Tm) -> Self {
		// can only fail if the TIME_FMT_ENCODE_STR would be invalid
		Object::string_literal(if date.tm_utcoff != 0 {
			// D:%Y%m%d%H%M%S:%z'
			//
			// UTC offset in the form +HHMM or -HHMM (empty string if the the object is naive).
			let timezone = strftime("%z", &date).unwrap();
			let timezone_str_start = strftime("%Y%m%d%H%M%S", &date).unwrap();

			let mut timezone_str = format!("D:{}:{}'", timezone_str_start, timezone).into_bytes();
			convert_utc_offset(&mut timezone_str);
			timezone_str
		} else {
			format!("D:{}", strftime("%Y%m%d%H%M%SZ", &date).unwrap()).into_bytes()
		})
	}
}

impl Object {

	// Parses the `D`, `:` and `\` out of a `Object::String` to parse the date time
	fn datetime_string(&self) -> Option<String> {
		if let Object::String(ref bytes, _) = self {
			String::from_utf8(bytes.iter().filter(|b| {
				![b'D', b':', b'\''].contains(b)
			}).map(|b|*b).collect()).ok()
		} else {
			None
		}
	}

	#[cfg(feature = "chrono_time")]
	pub fn as_datetime(&self) -> Option<DateTime<Local>> {
		let text = self.datetime_string()?;
		Local.datetime_from_str(&text, TIME_FMT_DECODE_STR).ok()
	}

	/// WARNING: `tm_wday` (weekday), `tm_yday` (day index in year), `tm_isdst`
	/// (daylight saving time) and `tm_nsec` (nanoseconds of the date from 1970)
	/// are set to 0 since they aren't available in the PDF time format. They could,
	/// however, be calculated manually
	#[cfg(not(feature = "chrono_time"))]
	pub fn as_datetime(&self) -> Option<Tm> {
		let text = self.datetime_string()?;
		strptime(&text, TIME_FMT_DECODE_STR).ok()
	}
}

#[cfg(feature = "chrono_time")]
#[test]
fn parse_datetime() {
	let time = Local::now().with_nanosecond(0).unwrap();
	let text: Object = time.into();
	let time2 = text.as_datetime();
	assert_eq!(time2, Some(time));
}

#[cfg(not(feature = "chrono_time"))]
#[test]
fn parse_datetime() {

	// Tm-based: Ignore tm_wday, tm_yday, tm_isdst and tm_nsec
	// - not important in the date parsing
	let time = Tm {
		tm_wday: 0,
		tm_yday: 0,
		tm_isdst: 0,
		tm_nsec: 0,
		.. ::time::now()
	};

	let text: Object = time.into();
	let time2 = text.as_datetime();
	assert_eq!(time2, Some(time));
}
<commit_msg>Adress timezone formatting problem from #34<commit_after>#[cfg(feature = "chrono_time")]
use chrono::prelude::*;
#[cfg(not(feature = "chrono_time"))]
use time::strptime;
use time::{Tm, strftime};
use super::Object;

const TIME_FMT_DECODE_STR: &str = "%Y%m%d%H%M%S%z";

#[cfg(feature = "chrono_time")]
impl From<DateTime<Local>> for Object {
	fn from(date: DateTime<Local>) -> Self {
		let mut timezone_str = date.format("D:%Y%m%d%H%M%S%:z'").to_string().into_bytes();
		convert_utc_offset(&mut timezone_str);
		Object::string_literal(timezone_str)
	}
}

// Find the last `:` and turn it into an `'` to account for PDF weirdness
fn convert_utc_offset(bytes: &mut [u8]) {
	let mut index = bytes.len();
	while let Some(last) = bytes[..index].last_mut() {
		if *last == b':' {
			*last = b'\'';
			break;
		}
		index -= 1;
	}
}

#[cfg(feature = "chrono_time")]
impl From<DateTime<UTC>> for Object {
	fn from(date: DateTime<UTC>) -> Self {
		Object::string_literal(date.format("D:%Y%m%d%H%M%SZ").to_string())
	}
}

impl From<Tm> for Object {
	fn from(date: Tm) -> Self {
		// can only fail if the TIME_FMT_ENCODE_STR would be invalid
		Object::string_literal(if date.tm_utcoff != 0 {
			// D:%Y%m%d%H%M%S:%z'
			//
			// UTC offset in the form +HHMM or -HHMM (empty string if the the object is naive).
			let timezone = strftime("%z", &date).unwrap();
			let timezone_str_start = strftime("%Y%m%d%H%M%S", &date).unwrap();
			let mut timezone_str = format!("D:{}{}:{}'", timezone_str_start, &timezone[..3], &timezone[3..]).into_bytes();
			convert_utc_offset(&mut timezone_str);
			timezone_str
		} else {
			format!("D:{}", strftime("%Y%m%d%H%M%SZ", &date).unwrap()).into_bytes()
		})
	}
}

impl Object {

	// Parses the `D`, `:` and `\` out of a `Object::String` to parse the date time
	fn datetime_string(&self) -> Option<String> {
		if let Object::String(ref bytes, _) = self {
			String::from_utf8(bytes.iter().filter(|b| {
				![b'D', b':', b'\''].contains(b)
			}).map(|b|*b).collect()).ok()
		} else {
			None
		}
	}

	#[cfg(feature = "chrono_time")]
	pub fn as_datetime(&self) -> Option<DateTime<Local>> {
		let text = self.datetime_string()?;
		Local.datetime_from_str(&text, TIME_FMT_DECODE_STR).ok()
	}

	/// WARNING: `tm_wday` (weekday), `tm_yday` (day index in year), `tm_isdst`
	/// (daylight saving time) and `tm_nsec` (nanoseconds of the date from 1970)
	/// are set to 0 since they aren't available in the PDF time format. They could,
	/// however, be calculated manually
	#[cfg(not(feature = "chrono_time"))]
	pub fn as_datetime(&self) -> Option<Tm> {
		let text = self.datetime_string()?;
		strptime(&text, TIME_FMT_DECODE_STR).ok()
	}
}

#[cfg(feature = "chrono_time")]
#[test]
fn parse_datetime() {
	let time = Local::now().with_nanosecond(0).unwrap();
	let text: Object = time.into();
	let time2 = text.as_datetime();
	assert_eq!(time2, Some(time));
}

#[cfg(not(feature = "chrono_time"))]
#[test]
fn parse_datetime() {

	// Tm-based: Ignore tm_wday, tm_yday, tm_isdst and tm_nsec
	// - not important in the date parsing
	let time = Tm {
		tm_wday: 0,
		tm_yday: 0,
		tm_isdst: 0,
		tm_nsec: 0,
		.. ::time::now()
	};

	let text: Object = time.into();
	let time2 = text.as_datetime();
	assert_eq!(time2, Some(time));
}
<|endoftext|>


<commit_before>//! The Tessellated Intelligence System is a
//!
//! > massively parallel computer architecture comprised of non-uniformly
//! > interconnected heterogeneous nodes.
//!
//! The manual can be found [online](https://www.vidarholen.net/contents/junk/files/TIS-100%20Reference%20Manual.pdf).
//! Another useful resource is the unofficial [TIS-100 Hackers Guide](https://alandesmet.github.io/TIS-100-Hackers-Guide/).

/// A `Node` models the basic execution node in TIS-100. You change a node state
/// by executing an `Instruction` on it.
#[derive(Debug)]
pub struct Node {
    pub acc: i32,
    bac: i32
}

impl PartialEq for Node {
    /// Node are equal when they have the same internal state
    fn eq(&self, other: &Node) -> bool {
        self.acc == other.acc && self.bac == other.bac
    }
}

impl Eq for Node {}

/// `Instruction`s are executed by a `Node`.
pub enum Instruction {
    /// Does nothing
    NOP,
    /// Moves value from `Source` to `Destination`
    MOV(Source, Destination),
    /// Swaps the value of the accumulator (acc) and the backup (bac) register
    SWP,
    /// Saves the value of the accumulator (acc) to the backup register
    SAV,
    /// Add value from `Source` to accumulator (acc), storing result in acc
    ADD(Source),
    /// Subtracts value from `Source` from accumulator (acc), storing result in acc
    SUB(Source),
}

/// `Source` are either ports, registers or literals
pub enum Source {
    NIL,
    ACC,
    Literal(i32)
}

/// `Destination` are either ports or registers
pub enum Destination {
    NIL,
    ACC
}

impl Node {
    pub fn new() -> Node {
        Node { acc: 0, bac: 0 }
    }

    pub fn with(acc: i32, bac: i32) -> Node {
        Node { acc: acc, bac: bac }
    }

    pub fn execute(&self, instruction: Instruction) -> Node {
        match instruction {
            Instruction::NOP => self.nop(),
            Instruction::MOV(source, destination) => self.mov(source, destination) ,
            Instruction::SWP => self.swap(),
            Instruction::SAV => self.save(),
            Instruction::ADD(source) => self.add(source),
            Instruction::SUB(source) => self.subtract(source),
        }
    }

    fn nop(&self) -> Node {
        Node { acc: self.acc, bac: self.bac }
    }

    fn mov(&self, source: Source, destination: Destination) -> Node {
        let value: i32 = match source {
            Source::NIL => 0,
            Source::ACC => self.acc,
            Source::Literal(value) => value
        };

        self.move_value(value, destination)
    }

    fn move_value(&self, value: i32, destination: Destination) -> Node {
        match destination {
            Destination::ACC => Node { acc: value, bac: self.bac },
            _ => self.nop()
        }
    }

    fn swap(&self) -> Node {
        Node { acc: self.bac, bac: self.acc }
    }

    fn save(&self) -> Node {
        Node { acc: self.acc, bac: self.acc }
    }

    fn add(&self, source: Source) -> Node{
        let value: i32 = match source {
            Source::NIL => 0,
            Source::ACC => self.acc,
            Source::Literal(value) => value
        };

        self.add_value(value)
    }

    fn add_value(&self, value: i32) -> Node {
        Node { acc: self.acc + value, bac: self.bac }
    }

    fn subtract(&self, source: Source) -> Node {
        let value: i32 = match source {
            Source::NIL => 0,
            Source::ACC => self.acc,
            Source::Literal(value) => value
        };

        self.subtract_value(value)
    }

    fn subtract_value(&self, value: i32) -> Node {
        Node { acc: self.acc - value, bac: self.bac }
    }
}

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

    #[test]
    fn node_should_start_with_accumulator_zero() {
        let node: Node = Node::new();

        assert_eq!(0, node.acc);
    }

    #[test]
    fn node_should_start_with_backup_zero() {
        let node: Node = Node::new();
        let instruction: Instruction = Instruction::SWP;

        let next: Node = node.execute(instruction);

        assert_eq!(0, next.acc);
    }

    #[test]
    fn node_should_execute_NOP_correctly() {
        let node: Node = Node::with(1, 0);
        let instruction: Instruction = Instruction::NOP;

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(1, 0), next);
    }

    #[test]
    fn node_should_execute_MOV_from_NIL_to_NIL_correctly() {
        let node: Node = Node::with(1, 0);
        let instruction: Instruction = Instruction::MOV(Source::NIL,
                                                        Destination::NIL);

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(1, 0), next);
    }

    #[test]
    fn node_should_execute_MOV_from_ACC_to_ACC_correctly() {
        let node: Node = Node::with(2, 1);
        let instruction: Instruction = Instruction::MOV(Source::ACC,
                                                        Destination::ACC);

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(2, 1), next);
    }

    #[test]
    fn node_should_execute_MOV_from_Literal_to_ACC_correctly() {
        let node: Node = Node::new();
        let instruction: Instruction = Instruction::MOV(Source::Literal(1),
                                                        Destination::ACC);

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(1, 0), next);
    }

    #[test]
    fn node_should_execute_SWP_correctly() {
        let node: Node = Node::with(1, 0);
        let instruction: Instruction = Instruction::SWP;

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(0, 1), next);
    }

    #[test]
    fn node_should_execute_SAV_correctly() {
        let node: Node = Node::with(1,0);
        let instruction: Instruction = Instruction::SAV;

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(1, 1), next);
    }

    #[test]
    fn node_should_execute_ADD_from_Literal_correctly() {
        let node: Node = Node::with(1, 0);
        let instruction: Instruction = Instruction::ADD(Source::Literal(1));

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(2, 0), next);
    }

    #[test]
    fn node_should_execute_SUB_from_Literal_correctly() {
        let node: Node = Node::with(2, 0);
        let instruction: Instruction = Instruction::SUB(Source::Literal(1));

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(1, 0), next);
    }
}

<commit_msg>Provide a correct example<commit_after>//! The Tessellated Intelligence System is a
//!
//! > massively parallel computer architecture comprised of non-uniformly
//! > interconnected heterogeneous nodes.
//!
//! The manual can be found [online](https://www.vidarholen.net/contents/junk/files/TIS-100%20Reference%20Manual.pdf).
//! Another useful resource is the unofficial [TIS-100 Hackers Guide](https://alandesmet.github.io/TIS-100-Hackers-Guide/).
//!
//! # Examples
//! Here we take a node and execute some instructions and check if double 1 has
//! the expected result.
//!
//! ```rust
//! extern crate tis_100_superoptimizer;
//!
//! use tis_100_superoptimizer::TIS_100::{Node,Instruction,Source,Destination};
//!
//! fn main() {
//!     let node: Node = Node::new();
//!     let last: Node = node
//!         .execute(Instruction::MOV(Source::Literal(1), Destination::ACC))
//!         .execute(Instruction::ADD(Source::ACC));
//!
//!     assert_eq!(2, last.acc);
//! }
//! ```

/// A `Node` models the basic execution node in TIS-100. You change a node state
/// by executing an `Instruction` on it.
#[derive(Debug)]
pub struct Node {
    pub acc: i32,
    bac: i32
}

impl PartialEq for Node {
    /// Node are equal when they have the same internal state
    fn eq(&self, other: &Node) -> bool {
        self.acc == other.acc && self.bac == other.bac
    }
}

impl Eq for Node {}

/// `Instruction`s are executed by a `Node`.
pub enum Instruction {
    /// Does nothing
    NOP,
    /// Moves value from `Source` to `Destination`
    MOV(Source, Destination),
    /// Swaps the value of the accumulator (acc) and the backup (bac) register
    SWP,
    /// Saves the value of the accumulator (acc) to the backup register
    SAV,
    /// Add value from `Source` to accumulator (acc), storing result in acc
    ADD(Source),
    /// Subtracts value from `Source` from accumulator (acc), storing result in acc
    SUB(Source),
}

/// `Source` are either ports, registers or literals
pub enum Source {
    NIL,
    ACC,
    Literal(i32)
}

/// `Destination` are either ports or registers
pub enum Destination {
    NIL,
    ACC
}

impl Node {
    pub fn new() -> Node {
        Node { acc: 0, bac: 0 }
    }

    pub fn with(acc: i32, bac: i32) -> Node {
        Node { acc: acc, bac: bac }
    }

    pub fn execute(&self, instruction: Instruction) -> Node {
        match instruction {
            Instruction::NOP => self.nop(),
            Instruction::MOV(source, destination) => self.mov(source, destination) ,
            Instruction::SWP => self.swap(),
            Instruction::SAV => self.save(),
            Instruction::ADD(source) => self.add(source),
            Instruction::SUB(source) => self.subtract(source),
        }
    }

    fn nop(&self) -> Node {
        Node { acc: self.acc, bac: self.bac }
    }

    fn mov(&self, source: Source, destination: Destination) -> Node {
        let value: i32 = match source {
            Source::NIL => 0,
            Source::ACC => self.acc,
            Source::Literal(value) => value
        };

        self.move_value(value, destination)
    }

    fn move_value(&self, value: i32, destination: Destination) -> Node {
        match destination {
            Destination::ACC => Node { acc: value, bac: self.bac },
            _ => self.nop()
        }
    }

    fn swap(&self) -> Node {
        Node { acc: self.bac, bac: self.acc }
    }

    fn save(&self) -> Node {
        Node { acc: self.acc, bac: self.acc }
    }

    fn add(&self, source: Source) -> Node{
        let value: i32 = match source {
            Source::NIL => 0,
            Source::ACC => self.acc,
            Source::Literal(value) => value
        };

        self.add_value(value)
    }

    fn add_value(&self, value: i32) -> Node {
        Node { acc: self.acc + value, bac: self.bac }
    }

    fn subtract(&self, source: Source) -> Node {
        let value: i32 = match source {
            Source::NIL => 0,
            Source::ACC => self.acc,
            Source::Literal(value) => value
        };

        self.subtract_value(value)
    }

    fn subtract_value(&self, value: i32) -> Node {
        Node { acc: self.acc - value, bac: self.bac }
    }
}

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

    #[test]
    fn node_should_start_with_accumulator_zero() {
        let node: Node = Node::new();

        assert_eq!(0, node.acc);
    }

    #[test]
    fn node_should_start_with_backup_zero() {
        let node: Node = Node::new();
        let instruction: Instruction = Instruction::SWP;

        let next: Node = node.execute(instruction);

        assert_eq!(0, next.acc);
    }

    #[test]
    fn node_should_execute_NOP_correctly() {
        let node: Node = Node::with(1, 0);
        let instruction: Instruction = Instruction::NOP;

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(1, 0), next);
    }

    #[test]
    fn node_should_execute_MOV_from_NIL_to_NIL_correctly() {
        let node: Node = Node::with(1, 0);
        let instruction: Instruction = Instruction::MOV(Source::NIL,
                                                        Destination::NIL);

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(1, 0), next);
    }

    #[test]
    fn node_should_execute_MOV_from_ACC_to_ACC_correctly() {
        let node: Node = Node::with(2, 1);
        let instruction: Instruction = Instruction::MOV(Source::ACC,
                                                        Destination::ACC);

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(2, 1), next);
    }

    #[test]
    fn node_should_execute_MOV_from_Literal_to_ACC_correctly() {
        let node: Node = Node::new();
        let instruction: Instruction = Instruction::MOV(Source::Literal(1),
                                                        Destination::ACC);

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(1, 0), next);
    }

    #[test]
    fn node_should_execute_SWP_correctly() {
        let node: Node = Node::with(1, 0);
        let instruction: Instruction = Instruction::SWP;

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(0, 1), next);
    }

    #[test]
    fn node_should_execute_SAV_correctly() {
        let node: Node = Node::with(1,0);
        let instruction: Instruction = Instruction::SAV;

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(1, 1), next);
    }

    #[test]
    fn node_should_execute_ADD_from_Literal_correctly() {
        let node: Node = Node::with(1, 0);
        let instruction: Instruction = Instruction::ADD(Source::Literal(1));

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(2, 0), next);
    }

    #[test]
    fn node_should_execute_SUB_from_Literal_correctly() {
        let node: Node = Node::with(2, 0);
        let instruction: Instruction = Instruction::SUB(Source::Literal(1));

        let next: Node = node.execute(instruction);

        assert_eq!(Node::with(1, 0), next);
    }
}

<|endoftext|>


<commit_before>use enums::*;

/// Parses a SPIR-V document.
pub fn parse_spirv(data: &[u8]) -> Result<Spirv, ParseError> {
    if data.len() < 20 {
        return Err(ParseError::MissingHeader);
    }

    // we need to determine whether we are in big endian order or little endian order depending
    // on the magic number at the start of the file
    let data = if data[0] == 0x07 && data[1] == 0x23 && data[2] == 0x02 && data[3] == 0x03 {
        // big endian
        data.chunks(4).map(|c| {
            ((c[0] as u32) << 24) | ((c[1] as u32) << 16) | ((c[2] as u32) << 8) | c[3] as u32
        }).collect::<Vec<_>>()

    } else if data[3] == 0x07 && data[2] == 0x23 && data[1] == 0x02 && data[0] == 0x03 {
        // little endian
        data.chunks(4).map(|c| {
            ((c[3] as u32) << 24) | ((c[2] as u32) << 16) | ((c[1] as u32) << 8) | c[0] as u32
        }).collect::<Vec<_>>()

    } else {
        return Err(ParseError::MissingHeader);
    };

    parse_u32s(&data)
}

/// Parses a SPIR-V document from a list of u32s.
///
/// Endianess has already been handled.
fn parse_u32s(i: &[u32]) -> Result<Spirv, ParseError> {
    if i.len() < 5 {
        return Err(ParseError::MissingHeader);
    }

    if i[0] != 0x07230203 {
        return Err(ParseError::WrongHeader);
    }

    let version = (((i[1] & 0x00ff0000) >> 16) as u8, ((i[1] & 0x0000ff00) >> 8) as u8);

    let instructions = {
        let mut ret = Vec::new();
        let mut i = &i[5..];
        while i.len() >= 1 {
            let (instruction, rest) = try!(parse_instruction(i));
            ret.push(instruction);
            i = rest;
        }
        ret
    };

    Ok(Spirv {
        version: version,
        bound: i[3],
        instructions: instructions,
    })
}

/// Error that can happen when parsing.
#[derive(Debug, Clone)]
pub enum ParseError {
    MissingHeader,
    WrongHeader,
    IncompleteInstruction,
    UnknownConstant(&'static str, u32),
}

#[derive(Debug, Clone)]
pub struct Spirv {
    pub version: (u8, u8),
    pub bound: u32,
    pub instructions: Vec<Instruction>,
}

#[derive(Debug, Clone)]
pub enum Instruction {
    Unknown(u16, Vec<u32>),
    Nop,
    Name { target_id: u32, name: String },
    MemberName { target_id: u32, member: u32, name: String },
    ExtInstImport { result_id: u32, name: String },
    MemoryModel(AddressingModel, MemoryModel),
    EntryPoint { execution: ExecutionModel, id: u32, name: String, interface: Vec<u32> },
    Capability(Capability),
    TypeVoid { result_id: u32 },
    TypeBool { result_id: u32 },
    TypeInt { result_id: u32, width: u32, signedness: bool },
    TypeFloat { result_id: u32, width: u32 },
    TypeVector { result_id: u32, component_id: u32, count: u32 },
    TypeImage { result_id: u32, sampled_type_id: u32, dim: Dim, depth: Option<bool>, arrayed: bool, ms: bool, sampled: Option<bool>, format: ImageFormat, access: Option<AccessQualifier> },
    TypeSampledImage { result_id: u32, image_type_id: u32 },
    TypeArray { result_id: u32, type_id: u32, length_id: u32 },
    TypeRuntimeArray { result_id: u32, type_id: u32 },
    TypeStruct { result_id: u32, member_types: Vec<u32> },
    TypeOpaque { result_id: u32, name: String },
    TypePointer { result_id: u32, storage_class: StorageClass, type_id: u32 },
    Constant { result_type_id: u32, result_id: u32, data: Vec<u32> },
    FunctionEnd,
    Variable { result_type_id: u32, result_id: u32, storage_class: StorageClass, initializer: Option<u32> },
    Label { result_id: u32 },
    Branch { result_id: u32 },
    Kill,
    Return,
}

fn parse_instruction(i: &[u32]) -> Result<(Instruction, &[u32]), ParseError> {
    assert!(i.len() >= 1);

    let word_count = (i[0] >> 16) as usize;
    assert!(word_count >= 1);
    let opcode = (i[0] & 0xffff) as u16;

    if i.len() < word_count {
        return Err(ParseError::IncompleteInstruction);
    }

    let opcode = try!(decode_instruction(opcode, &i[1 .. word_count]));
    Ok((opcode, &i[word_count..]))
}

fn decode_instruction(opcode: u16, operands: &[u32]) -> Result<Instruction, ParseError> {
    Ok(match opcode {
        0 => Instruction::Nop,
        5 => Instruction::Name { target_id: operands[0], name: parse_string(&operands[1..]).0 },
        6 => Instruction::MemberName { target_id: operands[0], member: operands[1], name: parse_string(&operands[2..]).0 },
        11 => Instruction::ExtInstImport {
            result_id: operands[0],
            name: parse_string(&operands[1..]).0
        },
        14 => Instruction::MemoryModel(try!(AddressingModel::from_num(operands[0])), try!(MemoryModel::from_num(operands[1]))),
        15 => {
            let (n, r) = parse_string(&operands[2..]);
            Instruction::EntryPoint {
                execution: try!(ExecutionModel::from_num(operands[0])),
                id: operands[1],
                name: n,
                interface: r.to_owned(),
            }
        },
        17 => Instruction::Capability(try!(Capability::from_num(operands[0]))),
        19 => Instruction::TypeVoid { result_id: operands[0] },
        20 => Instruction::TypeBool { result_id: operands[0] },
        21 => Instruction::TypeInt { result_id: operands[0], width: operands[1], signedness: operands[2] != 0 },
        22 => Instruction::TypeFloat { result_id: operands[0], width: operands[1] },
        23 => Instruction::TypeVector { result_id: operands[0], component_id: operands[1], count: operands[2] },
        25 => Instruction::TypeImage {
                result_id: operands[0],
                sampled_type_id: operands[1],
                dim: try!(Dim::from_num(operands[2])),
                depth: match operands[3] { 0 => Some(false), 1 => Some(true), 2 => None, _ => unreachable!() },
                arrayed: operands[4] != 0,
                ms: operands[5] != 0,
                sampled: match operands[6] { 0 => None, 1 => Some(true), 2 => Some(false), _ => unreachable!() },
                format: try!(ImageFormat::from_num(operands[7])),
                access: if operands.len() >= 9 { Some(try!(AccessQualifier::from_num(operands[8]))) } else { None },
        },
        27 => Instruction::TypeSampledImage { result_id: operands[0], image_type_id: operands[1] },
        28 => Instruction::TypeArray { result_id: operands[0], type_id: operands[1], length_id: operands[2] },
        29 => Instruction::TypeRuntimeArray { result_id: operands[0], type_id: operands[1] },
        30 => Instruction::TypeStruct { result_id: operands[0], member_types: operands[1..].to_owned() },
        31 => Instruction::TypeOpaque { result_id: operands[0], name: parse_string(&operands[1..]).0 },
        32 => Instruction::TypePointer { result_id: operands[0], storage_class: try!(StorageClass::from_num(operands[1])), type_id: operands[2] },
        43 => Instruction::Constant { result_type_id: operands[0], result_id: operands[1], data: operands[2..].to_owned() },
        56 => Instruction::FunctionEnd,
        59 => Instruction::Variable {
            result_type_id: operands[0], result_id: operands[1],
            storage_class: try!(StorageClass::from_num(operands[2])),
            initializer: operands.get(3).map(|&v| v)
        },
        248 => Instruction::Label { result_id: operands[0] },
        249 => Instruction::Branch { result_id: operands[0] },
        252 => Instruction::Kill,
        253 => Instruction::Return,
        _ => Instruction::Unknown(opcode, operands.to_owned()),
    })
}

fn parse_string(data: &[u32]) -> (String, &[u32]) {
    let bytes = data.iter().flat_map(|&n| {
        let b1 = (n & 0xff) as u8;
        let b2 = ((n >> 8) & 0xff) as u8;
        let b3 = ((n >> 16) & 0xff) as u8;
        let b4 = ((n >> 24) & 0xff) as u8;
        vec![b1, b2, b3, b4].into_iter()
    }).take_while(|&b| b != 0).collect::<Vec<u8>>();

    let r = 1 + bytes.len() / 4;
    let s = String::from_utf8(bytes).expect("Shader content is not UTF-8");

    (s, &data[r..])
}

#[cfg(test)]
mod test {
    use parse;

    #[test]
    fn test() {
        let data = include_bytes!("../examples/example.spv");
        println!("{:#?}", parse::parse_spirv(data).unwrap());
    }
}
<commit_msg>Fix test<commit_after>use enums::*;

/// Parses a SPIR-V document.
pub fn parse_spirv(data: &[u8]) -> Result<Spirv, ParseError> {
    if data.len() < 20 {
        return Err(ParseError::MissingHeader);
    }

    // we need to determine whether we are in big endian order or little endian order depending
    // on the magic number at the start of the file
    let data = if data[0] == 0x07 && data[1] == 0x23 && data[2] == 0x02 && data[3] == 0x03 {
        // big endian
        data.chunks(4).map(|c| {
            ((c[0] as u32) << 24) | ((c[1] as u32) << 16) | ((c[2] as u32) << 8) | c[3] as u32
        }).collect::<Vec<_>>()

    } else if data[3] == 0x07 && data[2] == 0x23 && data[1] == 0x02 && data[0] == 0x03 {
        // little endian
        data.chunks(4).map(|c| {
            ((c[3] as u32) << 24) | ((c[2] as u32) << 16) | ((c[1] as u32) << 8) | c[0] as u32
        }).collect::<Vec<_>>()

    } else {
        return Err(ParseError::MissingHeader);
    };

    parse_u32s(&data)
}

/// Parses a SPIR-V document from a list of u32s.
///
/// Endianess has already been handled.
fn parse_u32s(i: &[u32]) -> Result<Spirv, ParseError> {
    if i.len() < 5 {
        return Err(ParseError::MissingHeader);
    }

    if i[0] != 0x07230203 {
        return Err(ParseError::WrongHeader);
    }

    let version = (((i[1] & 0x00ff0000) >> 16) as u8, ((i[1] & 0x0000ff00) >> 8) as u8);

    let instructions = {
        let mut ret = Vec::new();
        let mut i = &i[5..];
        while i.len() >= 1 {
            let (instruction, rest) = try!(parse_instruction(i));
            ret.push(instruction);
            i = rest;
        }
        ret
    };

    Ok(Spirv {
        version: version,
        bound: i[3],
        instructions: instructions,
    })
}

/// Error that can happen when parsing.
#[derive(Debug, Clone)]
pub enum ParseError {
    MissingHeader,
    WrongHeader,
    IncompleteInstruction,
    UnknownConstant(&'static str, u32),
}

#[derive(Debug, Clone)]
pub struct Spirv {
    pub version: (u8, u8),
    pub bound: u32,
    pub instructions: Vec<Instruction>,
}

#[derive(Debug, Clone)]
pub enum Instruction {
    Unknown(u16, Vec<u32>),
    Nop,
    Name { target_id: u32, name: String },
    MemberName { target_id: u32, member: u32, name: String },
    ExtInstImport { result_id: u32, name: String },
    MemoryModel(AddressingModel, MemoryModel),
    EntryPoint { execution: ExecutionModel, id: u32, name: String, interface: Vec<u32> },
    Capability(Capability),
    TypeVoid { result_id: u32 },
    TypeBool { result_id: u32 },
    TypeInt { result_id: u32, width: u32, signedness: bool },
    TypeFloat { result_id: u32, width: u32 },
    TypeVector { result_id: u32, component_id: u32, count: u32 },
    TypeImage { result_id: u32, sampled_type_id: u32, dim: Dim, depth: Option<bool>, arrayed: bool, ms: bool, sampled: Option<bool>, format: ImageFormat, access: Option<AccessQualifier> },
    TypeSampledImage { result_id: u32, image_type_id: u32 },
    TypeArray { result_id: u32, type_id: u32, length_id: u32 },
    TypeRuntimeArray { result_id: u32, type_id: u32 },
    TypeStruct { result_id: u32, member_types: Vec<u32> },
    TypeOpaque { result_id: u32, name: String },
    TypePointer { result_id: u32, storage_class: StorageClass, type_id: u32 },
    Constant { result_type_id: u32, result_id: u32, data: Vec<u32> },
    FunctionEnd,
    Variable { result_type_id: u32, result_id: u32, storage_class: StorageClass, initializer: Option<u32> },
    Label { result_id: u32 },
    Branch { result_id: u32 },
    Kill,
    Return,
}

fn parse_instruction(i: &[u32]) -> Result<(Instruction, &[u32]), ParseError> {
    assert!(i.len() >= 1);

    let word_count = (i[0] >> 16) as usize;
    assert!(word_count >= 1);
    let opcode = (i[0] & 0xffff) as u16;

    if i.len() < word_count {
        return Err(ParseError::IncompleteInstruction);
    }

    let opcode = try!(decode_instruction(opcode, &i[1 .. word_count]));
    Ok((opcode, &i[word_count..]))
}

fn decode_instruction(opcode: u16, operands: &[u32]) -> Result<Instruction, ParseError> {
    Ok(match opcode {
        0 => Instruction::Nop,
        5 => Instruction::Name { target_id: operands[0], name: parse_string(&operands[1..]).0 },
        6 => Instruction::MemberName { target_id: operands[0], member: operands[1], name: parse_string(&operands[2..]).0 },
        11 => Instruction::ExtInstImport {
            result_id: operands[0],
            name: parse_string(&operands[1..]).0
        },
        14 => Instruction::MemoryModel(try!(AddressingModel::from_num(operands[0])), try!(MemoryModel::from_num(operands[1]))),
        15 => {
            let (n, r) = parse_string(&operands[2..]);
            Instruction::EntryPoint {
                execution: try!(ExecutionModel::from_num(operands[0])),
                id: operands[1],
                name: n,
                interface: r.to_owned(),
            }
        },
        17 => Instruction::Capability(try!(Capability::from_num(operands[0]))),
        19 => Instruction::TypeVoid { result_id: operands[0] },
        20 => Instruction::TypeBool { result_id: operands[0] },
        21 => Instruction::TypeInt { result_id: operands[0], width: operands[1], signedness: operands[2] != 0 },
        22 => Instruction::TypeFloat { result_id: operands[0], width: operands[1] },
        23 => Instruction::TypeVector { result_id: operands[0], component_id: operands[1], count: operands[2] },
        25 => Instruction::TypeImage {
                result_id: operands[0],
                sampled_type_id: operands[1],
                dim: try!(Dim::from_num(operands[2])),
                depth: match operands[3] { 0 => Some(false), 1 => Some(true), 2 => None, _ => unreachable!() },
                arrayed: operands[4] != 0,
                ms: operands[5] != 0,
                sampled: match operands[6] { 0 => None, 1 => Some(true), 2 => Some(false), _ => unreachable!() },
                format: try!(ImageFormat::from_num(operands[7])),
                access: if operands.len() >= 9 { Some(try!(AccessQualifier::from_num(operands[8]))) } else { None },
        },
        27 => Instruction::TypeSampledImage { result_id: operands[0], image_type_id: operands[1] },
        28 => Instruction::TypeArray { result_id: operands[0], type_id: operands[1], length_id: operands[2] },
        29 => Instruction::TypeRuntimeArray { result_id: operands[0], type_id: operands[1] },
        30 => Instruction::TypeStruct { result_id: operands[0], member_types: operands[1..].to_owned() },
        31 => Instruction::TypeOpaque { result_id: operands[0], name: parse_string(&operands[1..]).0 },
        32 => Instruction::TypePointer { result_id: operands[0], storage_class: try!(StorageClass::from_num(operands[1])), type_id: operands[2] },
        43 => Instruction::Constant { result_type_id: operands[0], result_id: operands[1], data: operands[2..].to_owned() },
        56 => Instruction::FunctionEnd,
        59 => Instruction::Variable {
            result_type_id: operands[0], result_id: operands[1],
            storage_class: try!(StorageClass::from_num(operands[2])),
            initializer: operands.get(3).map(|&v| v)
        },
        248 => Instruction::Label { result_id: operands[0] },
        249 => Instruction::Branch { result_id: operands[0] },
        252 => Instruction::Kill,
        253 => Instruction::Return,
        _ => Instruction::Unknown(opcode, operands.to_owned()),
    })
}

fn parse_string(data: &[u32]) -> (String, &[u32]) {
    let bytes = data.iter().flat_map(|&n| {
        let b1 = (n & 0xff) as u8;
        let b2 = ((n >> 8) & 0xff) as u8;
        let b3 = ((n >> 16) & 0xff) as u8;
        let b4 = ((n >> 24) & 0xff) as u8;
        vec![b1, b2, b3, b4].into_iter()
    }).take_while(|&b| b != 0).collect::<Vec<u8>>();

    let r = 1 + bytes.len() / 4;
    let s = String::from_utf8(bytes).expect("Shader content is not UTF-8");

    (s, &data[r..])
}

#[cfg(test)]
mod test {
    use parse;

    #[test]
    fn test() {
        let data = include_bytes!("../tests/frag.spv");
        println!("{:#?}", parse::parse_spirv(data).unwrap());
    }
}
<|endoftext|>


<commit_before>extern crate find_folder;

use ::screen;
use ::screen::Screen;

use piston_window;
use piston_window::Transformed;

use gfx_device_gl;

pub struct Game {
    window: piston_window::PistonWindow,
    screens: Vec<Box<screen::Screen>>,
}

impl Game {
    pub fn new() -> Game {
        let window: piston_window::PistonWindow = piston_window::WindowSettings::new("rrthozopsi", [600, 600]).exit_on_esc(true).build().unwrap();
        let screens: Vec<Box<screen::Screen>> = vec![Box::new(screen::MainMenuScreen::new())];
        Game {
            window: window,
            screens: screens,
            events: events::Events::new(),
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let mut screen = self.screens.last_mut().unwrap();

        // TODO: Remove clone?
        for window in &mut self.window {
            match window.event {
                Some(Event::Update(args)) => { screen.on_update(&args); }
                Some(Event::Render(args)) => { screen.on_draw(&args, &window); }
                Some(Event::Input(input)) => { screen.on_input(&input); }
                _ => {}
            }
        }
    }

    pub fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        if self.events.is_up()   { self.player.mov(0.0, -150.0 * args.dt); }
        if self.events.is_down() { self.player.mov(0.0, 150.0 * args.dt); }
        if self.events.is_left() { self.player.mov(-150.0 * args.dt, 0.0); }
        if self.events.is_right() { self.player.mov(150.0 * args.dt, 0.0); }
    }

    pub fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);

            let center = context.transform.trans((args.width / 2) as f64, (args.height / 2) as f64);
            self.player.render(graphics, &center);
        });
    }

    pub fn on_input(&mut self, input: &piston_window::Input) {
        self.events.process_input(&input);
    }
}
<commit_msg>Events (variable) has been removed from game<commit_after>extern crate find_folder;

use ::screen;
use ::screen::Screen;

use piston_window;
use piston_window::Transformed;

use gfx_device_gl;

pub struct Game {
    window: piston_window::PistonWindow,
    screens: Vec<Box<screen::Screen>>,
}

impl Game {
    pub fn new() -> Game {
        let window: piston_window::PistonWindow = piston_window::WindowSettings::new("rrthozopsi", [600, 600]).exit_on_esc(true).build().unwrap();
        let screens: Vec<Box<screen::Screen>> = vec![Box::new(screen::MainMenuScreen::new())];
        Game {
            window: window,
            screens: screens,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let mut screen = self.screens.last_mut().unwrap();

        // TODO: Remove clone?
        for window in &mut self.window {
            match window.event {
                Some(Event::Update(args)) => { screen.on_update(&args); }
                Some(Event::Render(args)) => { screen.on_draw(&args, &window); }
                Some(Event::Input(input)) => { screen.on_input(&input); }
                _ => {}
            }
        }
    }

    pub fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        if self.events.is_up()   { self.player.mov(0.0, -150.0 * args.dt); }
        if self.events.is_down() { self.player.mov(0.0, 150.0 * args.dt); }
        if self.events.is_left() { self.player.mov(-150.0 * args.dt, 0.0); }
        if self.events.is_right() { self.player.mov(150.0 * args.dt, 0.0); }
    }

    pub fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);

            let center = context.transform.trans((args.width / 2) as f64, (args.height / 2) as f64);
            self.player.render(graphics, &center);
        });
    }

    pub fn on_input(&mut self, input: &piston_window::Input) {
        self.events.process_input(&input);
    }
}
<|endoftext|>


<commit_before>extern crate walkdir;

use std::path;
use self::walkdir::{WalkDir, DirEntry, Error};
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;

pub fn file_list(dir: &path::Path, filenames: &mut Vec<DirEntry>) -> Result<usize, Error> {
    for entry in WalkDir::new(dir).min_depth(1) {
        match entry {
            Err(err) => return Err(err),
            Ok(entry) => filenames.push(entry),
        }
    }
    Ok(filenames.len())
}

pub fn handle_files(runtime_context: &::RuntimeContext, filenames: Vec<walkdir::DirEntry>) -> usize {
    let debug = runtime_context.debug;
    let mut record_count = 0;
    for filename in filenames {
        debug!(debug, "Processing file {}.", filename.path().display());
        match File::open(filename.path()) {
            Ok(file) => {
                let buffered_file = BufReader::new(&file);
                // let lines = buffered_file.lines();
                // for line in lines {
                //     // let l = line.unwrap();
                //     // println!("{}", l);
                //
                // }
                let current_file_count = buffered_file.lines().count();
                record_count += current_file_count;
                debug!(debug, "Found {} records.", current_file_count);
            },
            Err(e) => {
                println!("ERROR: {}", e);
            }
        }
    }

    record_count
}
<commit_msg>Added a little more information to one of the debug statements.<commit_after>extern crate walkdir;

use std::path;
use self::walkdir::{WalkDir, DirEntry, Error};
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;

pub fn file_list(dir: &path::Path, filenames: &mut Vec<DirEntry>) -> Result<usize, Error> {
    for entry in WalkDir::new(dir).min_depth(1) {
        match entry {
            Err(err) => return Err(err),
            Ok(entry) => filenames.push(entry),
        }
    }
    Ok(filenames.len())
}

pub fn handle_files(runtime_context: &::RuntimeContext, filenames: Vec<walkdir::DirEntry>) -> usize {
    let debug = runtime_context.debug;
    let mut record_count = 0;
    for filename in filenames {
        debug!(debug, "Processing file {}.", filename.path().display());
        match File::open(filename.path()) {
            Ok(file) => {
                let buffered_file = BufReader::new(&file);
                // let lines = buffered_file.lines();
                // for line in lines {
                //     // let l = line.unwrap();
                //     // println!("{}", l);
                //
                // }
                let current_file_count = buffered_file.lines().count();
                record_count += current_file_count;
                debug!(debug, "Found {} records in file {}.", current_file_count, filename.path().display());
            },
            Err(e) => {
                println!("ERROR: {}", e);
            }
        }
    }

    record_count
}
<|endoftext|>