<commit_before>// FIXME: Replace these examples with executable tests
//! Traits related to relationships between multiple tables.
//!
//! **Note: This feature is under active development, and we are seeking feedback on the APIs that
//! have been released. Please feel free to [open issues][open-issue], or join [our chat][gitter]
//! to provide feedback.**
//!
//! [open-issue]: https://github.com/diesel-rs/diesel/issues/new
//! [gitter]: https://gitter.im/diesel-rs/diesel
//!
//! Note: This guide is written assuming the usage of `diesel_codegen` or `diesel_codegen_syntex`.
//! Associations in Diesel are bidirectional, but primarily focus on the child-to-parent
//! relationship. You can declare an association between two records with `#[has_many]` and
//! `#[belongs_to]`.
//!
//! ```ignore
//! #[derive(Identifiable, Queryable, Associations)]
//! #[has_many(posts)]
//! pub struct User {
//!     id: i32,
//!     name: String,
//! }
//!
//! #[derive(Identifiable, Queryable, Associations)]
//! #[belongs_to(User)]
//! pub struct Post {
//!     id: i32,
//!     user_id: i32,
//!     title: String,
//! }
//! ```
//!
//! Note that in addition to the `#[has_many]` and `#[belongs_to]` annotations, we also need to
//! `#[derive(Associations)]`
//!
//! `#[has_many]` should be passed the name of the table that the children will be loaded from,
//! while `#[belongs_to]` is given the name of the struct that represents the parent. Both types
//! must implement the [`Identifiable`][identifiable] trait.
//!
//! [Identifiable]: trait.Identifiable.html
//!
//! `#[has_many]` actually has no behavior on its own. It only enables joining between the two
//! tables. If you are only accessing data through the [`belonging_to`][belonging-to] method, you
//! only need to define the `#[belongs_to]` side.
//!
//! Once the associations are defined, you can join between the two tables using the
//! [`inner_join`][inner-join] or [`left_outer_join`][left-outer-join].
//!
//! [inner-join]: /diesel/query_source/trait.Table.html#method.inner_join
//! [left-outer-join]: /diesel/query_source/trait.Table.html#method.left_outer_join
//!
//! ```ignore
//! let data: Vec<(User, Post)> = users::table.inner_join(posts::table).load(&connection);
//! ```
//!
//! Note: Due to language limitations, only two tables can be joined per query. This will change in
//! the future.
//!
//! Typically however, queries are loaded in multiple queries. For most datasets, the reduced
//! amount of duplicated information sent over the wire saves more time than the extra round trip
//! costs us. You can load the children for a single parent using the
//! [`belonging_to`][belonging-to]
//!
//! [belonging-to]: /diesel/prelude/trait.BelongingToDsl.html#tymethod.belonging_to
//!
//! ```ignore
//! let user = try!(users::find(1).first(&connection));
//! let posts = Post::belonging_to(&user).load(&connection);
//! ```
//!
//! If you're coming from other ORMs, you'll notice that this design is quite different from most.
//! There you would have an instance method on the parent, or have the children stored somewhere on
//! the posts. This design leads to many problems, including [N+1 query
//! bugs][load-your-entire-database-into-memory-lol], and runtime errors when accessing an
//! association that isn't there.
//!
//! [load-your-entire-database-into-memory-lol]: http://stackoverflow.com/q/97197/1254484
//!
//! In Diesel, data and its associations are considered to be separate. If you want to pass around
//! a user and all of its posts, that type is `(User, Vec<Post>)`.
//!
//! Next lets look at how to load the children for more than one parent record.
//! [`belonging_to`][belonging-to] can be used to load the data, but we'll also need to group it
//! with its parents. For this we use an additional method [`grouped_by`][grouped-by]
//!
//! [grouped-by]: trait.GroupedBy.html#tymethod.grouped_by
//!
//! ```ignore
//! fn first_twenty_users_and_their_posts(conn: &PgConnection) -> QueryResult<Vec<(User, Vec<Post>)>> {
//!     let users = try!(users::limit(20).load::<User>(conn));
//!     let posts = try!(Post::belonging_to(&users).load::<Post>(conn));
//!     let grouped_posts = posts.grouped_by(&users);
//!     users.into_iter().zip(grouped_posts).collect()
//! }
//! ```
//!
//! [`grouped_by`][grouped-by] takes a `Vec<Child>` and a `Vec<Parent>` and returns a
//! `Vec<Vec<Child>>` where the index of the children matches the index of the parent they belong
//! to. Or to put it another way, it returns them in an order ready to be `zip`ed with the parents. You
//! can do this multiple times. For example, if you wanted to load the comments for all the posts
//! as well, you could do this: (explicit type annotations have been added for documentation
//! purposes)
//!
//! ```ignore
//! let posts: Vec<Post> = try!(Post::belonging_to(&users).load());
//! let comments: Vec<Comment> = try!(Comment::belonging_to(&posts).load());
//! let comments: Vec<Vec<Comment>> = comments.grouped_by(&posts);
//! let posts_and_comments: Vec<Vec<(Post, Vec<Comment>)>> = posts.into_iter().zip(comments).grouped_by(&users);
//! let result: Vec<(User, Vec<(Post, Vec<Comment>)>)> = users.into_iter().zip(posts_and_comments).collect();
//! ```
//!
//! And that's it. This module will be expanded in the future with more complex joins, and the
//! ability to define "through" associations (e.g. load all the comments left on any posts written
//! by a user in a single query). However, the goal is to provide simple building blocks which can
//! be used to construct the complex behavior applications need.
mod belongs_to;

use std::hash::Hash;

use query_source::Table;

pub use self::belongs_to::{BelongsTo, GroupedBy};

pub trait HasTable {
    type Table: Table;

    fn table() -> Self::Table;
}

impl<'a, T: HasTable> HasTable for &'a T {
    type Table = T::Table;

    fn table() -> Self::Table {
        T::table()
    }
}

/// Represents a struct which can be identified on a single table in the
/// database. This must be implemented to use associations, and some features of
/// updating. This trait is usually implemented on a reference to a struct, not
/// the struct itself.
///
/// ### Deriving
///
/// This trait can be automatically derived using `diesel_codegen` by adding
/// `#[derive(Identifiable)]` to your struct. The primary key will be assumed to
/// be a field and column called `id`. By default the table will be assumed to
/// be the plural form of the struct name (using *very* dumb pluralization -- it
/// just adds an `s` at the end). If your table name differs from that
/// convention, or requires complex pluralization, it can be specified using
/// `#[table_name = "some_table_name"]`. The inferred table name is considered
/// public API and will never change without a major version bump.
pub trait Identifiable: HasTable {
    type Id: Hash + Eq;

    fn id(self) -> Self::Id;
}
<commit_msg>Update associations docs<commit_after>// FIXME: Replace these examples with executable tests
//! Traits related to relationships between multiple tables.
//!
//! **Note: This feature is under active development, and we are seeking feedback on the APIs that
//! have been released. Please feel free to [open issues][open-issue], or join [our chat][gitter]
//! to provide feedback.**
//!
//! [open-issue]: https://github.com/diesel-rs/diesel/issues/new
//! [gitter]: https://gitter.im/diesel-rs/diesel
//!
//! Note: The derives in this guide are provided by `diesel_codegen`. Make sure you have
//! `#[macro_use] extern crate diesel_codegen;` at the root of your crate.
//!
//! Associations in Diesel are bidirectional, but primarily focus on the child-to-parent
//! relationship. You can declare an association between two records with `#[has_many]` and
//! `#[belongs_to]`.
//!
//! ```ignore
//! #[derive(Identifiable, Queryable, Associations)]
//! #[has_many(posts)]
//! pub struct User {
//!     id: i32,
//!     name: String,
//! }
//!
//! #[derive(Identifiable, Queryable, Associations)]
//! #[belongs_to(User)]
//! pub struct Post {
//!     id: i32,
//!     user_id: i32,
//!     title: String,
//! }
//! ```
//!
//! Note that in addition to the `#[has_many]` and `#[belongs_to]` annotations, we also need to
//! `#[derive(Associations)]`
//!
//! `#[has_many]` should be passed the name of the table that the children will be loaded from,
//! while `#[belongs_to]` is given the name of the struct that represents the parent. Both types
//! must implement the [`Identifiable`][identifiable] trait. The struct or table referenced in your
//! association has to be in scope, so you'll need `use schema::posts` or similar to bring the
//! table into scope, and `use some_module::User` if `User` were in a different module.
//!
//! [Identifiable]: trait.Identifiable.html
//!
//! `#[has_many]` actually has no behavior on its own. It only enables joining between the two
//! tables. If you are only writing `children.inner_join(parents)` or
//! `Child::belonging_to(&parents)`, you only need to define the `#[belongs_to]` side.
//!
//! Once the associations are defined, you can join between the two tables using the
//! [`inner_join`][inner-join] or [`left_outer_join`][left-outer-join].
//!
//! [inner-join]: /diesel/query_source/trait.Table.html#method.inner_join
//! [left-outer-join]: /diesel/query_source/trait.Table.html#method.left_outer_join
//!
//! ```ignore
//! let data: Vec<(User, Post)> = users::table.inner_join(posts::table).load(&connection);
//! ```
//!
//! Note: Due to language limitations, only two tables can be joined per query. This will change in
//! the future.
//!
//! Typically however, queries are loaded in multiple queries. For most datasets, the reduced
//! amount of duplicated information sent over the wire saves more time than the extra round trip
//! costs us. You can load the children for a single parent using the
//! [`belonging_to`][belonging-to]
//!
//! [belonging-to]: /diesel/prelude/trait.BelongingToDsl.html#tymethod.belonging_to
//!
//! ```ignore
//! let user = try!(users::find(1).first(&connection));
//! let posts = Post::belonging_to(&user).load(&connection);
//! ```
//!
//! If you're coming from other ORMs, you'll notice that this design is quite different from most.
//! There you would have an instance method on the parent, or have the children stored somewhere on
//! the posts. This design leads to many problems, including [N+1 query
//! bugs][load-your-entire-database-into-memory-lol], and runtime errors when accessing an
//! association that isn't there.
//!
//! [load-your-entire-database-into-memory-lol]: http://stackoverflow.com/q/97197/1254484
//!
//! In Diesel, data and its associations are considered to be separate. If you want to pass around
//! a user and all of its posts, that type is `(User, Vec<Post>)`.
//!
//! Next lets look at how to load the children for more than one parent record.
//! [`belonging_to`][belonging-to] can be used to load the data, but we'll also need to group it
//! with its parents. For this we use an additional method [`grouped_by`][grouped-by]
//!
//! [grouped-by]: trait.GroupedBy.html#tymethod.grouped_by
//!
//! ```ignore
//! fn first_twenty_users_and_their_posts(conn: &PgConnection) -> QueryResult<Vec<(User, Vec<Post>)>> {
//!     let users = try!(users::limit(20).load::<User>(conn));
//!     let posts = try!(Post::belonging_to(&users).load::<Post>(conn));
//!     let grouped_posts = posts.grouped_by(&users);
//!     users.into_iter().zip(grouped_posts).collect()
//! }
//! ```
//!
//! [`grouped_by`][grouped-by] takes a `Vec<Child>` and a `Vec<Parent>` and returns a
//! `Vec<Vec<Child>>` where the index of the children matches the index of the parent they belong
//! to. Or to put it another way, it returns them in an order ready to be `zip`ed with the parents. You
//! can do this multiple times. For example, if you wanted to load the comments for all the posts
//! as well, you could do this: (explicit type annotations have been added for documentation
//! purposes)
//!
//! ```ignore
//! let posts: Vec<Post> = try!(Post::belonging_to(&users).load());
//! let comments: Vec<Comment> = try!(Comment::belonging_to(&posts).load());
//! let comments: Vec<Vec<Comment>> = comments.grouped_by(&posts);
//! let posts_and_comments: Vec<Vec<(Post, Vec<Comment>)>> = posts.into_iter().zip(comments).grouped_by(&users);
//! let result: Vec<(User, Vec<(Post, Vec<Comment>)>)> = users.into_iter().zip(posts_and_comments).collect();
//! ```
//!
//! And that's it. This module will be expanded in the future with more complex joins, and the
//! ability to define "through" associations (e.g. load all the comments left on any posts written
//! by a user in a single query). However, the goal is to provide simple building blocks which can
//! be used to construct the complex behavior applications need.
mod belongs_to;

use std::hash::Hash;

use query_source::Table;

pub use self::belongs_to::{BelongsTo, GroupedBy};

pub trait HasTable {
    type Table: Table;

    fn table() -> Self::Table;
}

impl<'a, T: HasTable> HasTable for &'a T {
    type Table = T::Table;

    fn table() -> Self::Table {
        T::table()
    }
}

/// Represents a struct which can be identified on a single table in the
/// database. This must be implemented to use associations, and some features of
/// updating. This trait is usually implemented on a reference to a struct, not
/// the struct itself.
///
/// ### Deriving
///
/// This trait can be automatically derived using `diesel_codegen` by adding
/// `#[derive(Identifiable)]` to your struct. The primary key will be assumed to
/// be a field and column called `id`. By default the table will be assumed to
/// be the plural form of the struct name (using *very* dumb pluralization -- it
/// just adds an `s` at the end). If your table name differs from that
/// convention, or requires complex pluralization, it can be specified using
/// `#[table_name = "some_table_name"]`. The inferred table name is considered
/// public API and will never change without a major version bump.
pub trait Identifiable: HasTable {
    type Id: Hash + Eq;

    fn id(self) -> Self::Id;
}
<|endoftext|>


<commit_before>//! Low-Level bindings for NumPy C API.
//!
//! https://docs.scipy.org/doc/numpy/reference/c-api.html
//!
//! Most of functions in this submodule are unsafe.
//! If you use functions in this submodule, you need to understand
//! basic usage of Python C API, especially for the reference counting.
//!
//! - http://docs.python.jp/3/c-api/
//! - http://dgrunwald.github.io/rust-pyo3/doc/pyo3/

use pyo3::ffi;
use std::ffi::CString;
use std::os::raw::c_void;
use std::ptr::null_mut;

fn get_numpy_api(module: &str, capsule: &str) -> *const *const c_void {
    let module = CString::new(module).unwrap();
    let capsule = CString::new(capsule).unwrap();
    unsafe fn get_capsule(capsule: *mut ffi::PyObject) -> *const *const c_void {
        ffi::PyCapsule_GetPointer(capsule, null_mut()) as *const *const c_void
    }
    unsafe {
        assert_ne!(
            ffi::Py_IsInitialized(),
            0,
            r"Numpy API is called before initializing Python!
Please make sure that you get gil, by `let gil = Python::acquire_gil();`"
        );
        let numpy = ffi::PyImport_ImportModule(module.as_ptr());
        assert!(!numpy.is_null(), "Failed to import numpy module");
        let capsule = ffi::PyObject_GetAttrString(numpy as *mut ffi::PyObject, capsule.as_ptr());
        assert!(!capsule.is_null(), "Failed to import numpy module");
        get_capsule(capsule)
    }
}

// Define Array&UFunc APIs
macro_rules! impl_api {
    [ $offset:expr; $fname:ident ( $($arg:ident : $t:ty),* ) $( -> $ret:ty )* ] => {
        #[allow(non_snake_case)]
        pub unsafe fn $fname(&self, $($arg : $t), *) $( -> $ret )* {
            let fptr = self.0.offset($offset)
                               as (*const extern fn ($($arg : $t), *) $( -> $ret )* );
            (*fptr)($($arg), *)
        }
    }
}

pub mod array;
pub mod flags;
pub mod objects;
pub mod types;
pub mod ufunc;

pub use self::array::*;
pub use self::flags::*;
pub use self::objects::*;
pub use self::types::*;
pub use self::ufunc::*;
<commit_msg>Remove unnecessary parentheses<commit_after>//! Low-Level bindings for NumPy C API.
//!
//! https://docs.scipy.org/doc/numpy/reference/c-api.html
//!
//! Most of functions in this submodule are unsafe.
//! If you use functions in this submodule, you need to understand
//! basic usage of Python C API, especially for the reference counting.
//!
//! - http://docs.python.jp/3/c-api/
//! - http://dgrunwald.github.io/rust-pyo3/doc/pyo3/

use pyo3::ffi;
use std::ffi::CString;
use std::os::raw::c_void;
use std::ptr::null_mut;

fn get_numpy_api(module: &str, capsule: &str) -> *const *const c_void {
    let module = CString::new(module).unwrap();
    let capsule = CString::new(capsule).unwrap();
    unsafe fn get_capsule(capsule: *mut ffi::PyObject) -> *const *const c_void {
        ffi::PyCapsule_GetPointer(capsule, null_mut()) as *const *const c_void
    }
    unsafe {
        assert_ne!(
            ffi::Py_IsInitialized(),
            0,
            r"Numpy API is called before initializing Python!
Please make sure that you get gil, by `let gil = Python::acquire_gil();`"
        );
        let numpy = ffi::PyImport_ImportModule(module.as_ptr());
        assert!(!numpy.is_null(), "Failed to import numpy module");
        let capsule = ffi::PyObject_GetAttrString(numpy as *mut ffi::PyObject, capsule.as_ptr());
        assert!(!capsule.is_null(), "Failed to import numpy module");
        get_capsule(capsule)
    }
}

// Define Array&UFunc APIs
macro_rules! impl_api {
    [ $offset:expr; $fname:ident ( $($arg:ident : $t:ty),* ) $( -> $ret:ty )* ] => {
        #[allow(non_snake_case)]
        pub unsafe fn $fname(&self, $($arg : $t), *) $( -> $ret )* {
            let fptr = self.0.offset($offset)
                               as *const extern fn ($($arg : $t), *) $( -> $ret )*;
            (*fptr)($($arg), *)
        }
    }
}

pub mod array;
pub mod flags;
pub mod objects;
pub mod types;
pub mod ufunc;

pub use self::array::*;
pub use self::flags::*;
pub use self::objects::*;
pub use self::types::*;
pub use self::ufunc::*;
<|endoftext|>


<commit_before>use anyhow::{bail, Context, Result};
use std::io;

fn f() -> Result<()> {
    bail!(io::Error::new(io::ErrorKind::PermissionDenied, "oh no!"));
}

fn g() -> Result<()> {
    f().context("f failed")
}

fn h() -> Result<()> {
    g().context("g failed")
}

const EXPECTED_ALTDISPLAY_F: &str = "\
oh no!\
";

const EXPECTED_ALTDISPLAY_G: &str = "\
f failed: oh no!\
";

const EXPECTED_ALTDISPLAY_H: &str = "\
g failed: f failed: oh no!\
";

const EXPECTED_DEBUG_F: &str = "\
oh no!

Stack backtrace:
    Run with RUST_LIB_BACKTRACE=1 env variable to display a backtrace
";

const EXPECTED_DEBUG_G: &str = "\
f failed

Caused by:
    oh no!

Stack backtrace:
    Run with RUST_LIB_BACKTRACE=1 env variable to display a backtrace
";

const EXPECTED_DEBUG_H: &str = "\
g failed

Caused by:
    0: f failed
    1: oh no!

Stack backtrace:
    Run with RUST_LIB_BACKTRACE=1 env variable to display a backtrace
";

const EXPECTED_ALTDEBUG_F: &str = "\
Custom {
    kind: PermissionDenied,
    error: \"oh no!\",
}\
";

const EXPECTED_ALTDEBUG_G: &str = "\
Error {
    context: \"f failed\",
    source: Custom {
        kind: PermissionDenied,
        error: \"oh no!\",
    },
}\
";

const EXPECTED_ALTDEBUG_H: &str = "\
Error {
    context: \"g failed\",
    source: Error {
        context: \"f failed\",
        source: Custom {
            kind: PermissionDenied,
            error: \"oh no!\",
        },
    },
}\
";

#[test]
fn test_display() {
    assert_eq!("g failed", h().unwrap_err().to_string());
}

#[test]
fn test_altdisplay() {
    assert_eq!(EXPECTED_ALTDISPLAY_F, format!("{:#}", f().unwrap_err()));
    assert_eq!(EXPECTED_ALTDISPLAY_G, format!("{:#}", g().unwrap_err()));
    assert_eq!(EXPECTED_ALTDISPLAY_H, format!("{:#}", h().unwrap_err()));
}

#[test]
#[cfg_attr(not(backtrace), ignore)]
fn test_debug() {
    assert_eq!(EXPECTED_DEBUG_F, format!("{:?}", f().unwrap_err()));
    assert_eq!(EXPECTED_DEBUG_G, format!("{:?}", g().unwrap_err()));
    assert_eq!(EXPECTED_DEBUG_H, format!("{:?}", h().unwrap_err()));
}

#[test]
fn test_altdebug() {
    assert_eq!(EXPECTED_ALTDEBUG_F, format!("{:#?}", f().unwrap_err()));
    assert_eq!(EXPECTED_ALTDEBUG_G, format!("{:#?}", g().unwrap_err()));
    assert_eq!(EXPECTED_ALTDEBUG_H, format!("{:#?}", h().unwrap_err()));
}
<commit_msg>Line up altdisplay expected strings on one line<commit_after>use anyhow::{bail, Context, Result};
use std::io;

fn f() -> Result<()> {
    bail!(io::Error::new(io::ErrorKind::PermissionDenied, "oh no!"));
}

fn g() -> Result<()> {
    f().context("f failed")
}

fn h() -> Result<()> {
    g().context("g failed")
}

const EXPECTED_ALTDISPLAY_F: &str = "oh no!";

const EXPECTED_ALTDISPLAY_G: &str = "f failed: oh no!";

const EXPECTED_ALTDISPLAY_H: &str = "g failed: f failed: oh no!";

const EXPECTED_DEBUG_F: &str = "\
oh no!

Stack backtrace:
    Run with RUST_LIB_BACKTRACE=1 env variable to display a backtrace
";

const EXPECTED_DEBUG_G: &str = "\
f failed

Caused by:
    oh no!

Stack backtrace:
    Run with RUST_LIB_BACKTRACE=1 env variable to display a backtrace
";

const EXPECTED_DEBUG_H: &str = "\
g failed

Caused by:
    0: f failed
    1: oh no!

Stack backtrace:
    Run with RUST_LIB_BACKTRACE=1 env variable to display a backtrace
";

const EXPECTED_ALTDEBUG_F: &str = "\
Custom {
    kind: PermissionDenied,
    error: \"oh no!\",
}\
";

const EXPECTED_ALTDEBUG_G: &str = "\
Error {
    context: \"f failed\",
    source: Custom {
        kind: PermissionDenied,
        error: \"oh no!\",
    },
}\
";

const EXPECTED_ALTDEBUG_H: &str = "\
Error {
    context: \"g failed\",
    source: Error {
        context: \"f failed\",
        source: Custom {
            kind: PermissionDenied,
            error: \"oh no!\",
        },
    },
}\
";

#[test]
fn test_display() {
    assert_eq!("g failed", h().unwrap_err().to_string());
}

#[test]
fn test_altdisplay() {
    assert_eq!(EXPECTED_ALTDISPLAY_F, format!("{:#}", f().unwrap_err()));
    assert_eq!(EXPECTED_ALTDISPLAY_G, format!("{:#}", g().unwrap_err()));
    assert_eq!(EXPECTED_ALTDISPLAY_H, format!("{:#}", h().unwrap_err()));
}

#[test]
#[cfg_attr(not(backtrace), ignore)]
fn test_debug() {
    assert_eq!(EXPECTED_DEBUG_F, format!("{:?}", f().unwrap_err()));
    assert_eq!(EXPECTED_DEBUG_G, format!("{:?}", g().unwrap_err()));
    assert_eq!(EXPECTED_DEBUG_H, format!("{:?}", h().unwrap_err()));
}

#[test]
fn test_altdebug() {
    assert_eq!(EXPECTED_ALTDEBUG_F, format!("{:#?}", f().unwrap_err()));
    assert_eq!(EXPECTED_ALTDEBUG_G, format!("{:#?}", g().unwrap_err()));
    assert_eq!(EXPECTED_ALTDEBUG_H, format!("{:#?}", h().unwrap_err()));
}
<|endoftext|>


<commit_before>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::result::Result;

use storage::backend::{StorageBackend, StorageBackendError};
use self::command::ExecutableCommand;
mod command;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
}

impl ModuleError {
    fn mk(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub type ModuleResult = Result<(), ModuleError>;

pub trait Module {

    fn new(rt : &Runtime) -> Self;
    fn callnames() -> &'static [&'static str];
    fn name(&self) -> &'static str;

    fn execute(&self, rt : &Runtime) -> ModuleResult;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

    fn getCommandBuilder<T, F>() -> F
        where F: FnOnce(StorageBackend) -> T,
              T: ExecutableCommand;

}

<commit_msg>Fix: unused import<commit_after>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::result::Result;

use storage::backend::StorageBackend;
use self::command::ExecutableCommand;
mod command;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
}

impl ModuleError {
    fn mk(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub type ModuleResult = Result<(), ModuleError>;

pub trait Module {

    fn new(rt : &Runtime) -> Self;
    fn callnames() -> &'static [&'static str];
    fn name(&self) -> &'static str;

    fn execute(&self, rt : &Runtime) -> ModuleResult;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

    fn getCommandBuilder<T, F>() -> F
        where F: FnOnce(StorageBackend) -> T,
              T: ExecutableCommand;

}

<|endoftext|>


<commit_before>#![allow(missing_docs)]

pub type AST = Vec<Definition>;
pub type Identifier = String;

// The following structures are used to help simplify building the AST in the grammar. Ideally
// these would not be exposed outside the crate, but the compiler seems to think they are exposed
// as private types when `pub(super)` is used. This is not the case since all of their variants are
// matched into other structures, but I suppose it is not a big deal.

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum BufferRelatedType {
    ArrayBuffer,
    DataView,
    Float32Array,
    Float64Array,
    Int16Array,
    Int32Array,
    Int8Array,
    Uint16Array,
    Uint32Array,
    Uint8Array,
    Uint8ClampedArray,
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum PrimitiveType {
    Boolean,
    Byte,
    Octet,
    UnrestrictedFloat(UnrestrictedFloatType),
    UnsignedInteger(UnsignedIntegerType),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Stringifier {
    Attribute(Attribute),
    Operation(Operation),
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum UnrestrictedFloatType {
    RestrictedDouble,
    RestrictedFloat,
    UnrestrictedDouble,
    UnrestrictedFloat,
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum UnsignedIntegerType {
    SignedLong,
    SignedLongLong,
    SignedShort,
    UnsignedLong,
    UnsignedLongLong,
    UnsignedShort,
}

// Publically available AST structures

#[derive(Clone, Debug, PartialEq)]
pub struct Argument {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub default: Option<DefaultValue>,
    pub name: Identifier,
    pub optional: bool,
    pub type_: Box<Type>,
    pub variadic: bool,
}

#[derive(Clone, Debug, PartialEq)]
pub struct ArgumentListExtendedAttribute {
    pub arguments: Vec<Argument>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Attribute {
    Regular(RegularAttribute),
    Static(StaticAttribute),
    Stringifier(StringifierAttribute),
}

#[derive(Clone, Debug, PartialEq)]
pub struct Callback {
    pub arguments: Vec<Argument>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub return_type: ReturnType,
}

#[derive(Clone, Debug, PartialEq)]
pub struct CallbackInterface {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub inherits: Option<Identifier>,
    pub members: Vec<InterfaceMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Const {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub nullable: bool,
    pub type_: ConstType,
    pub value: ConstValue,
}

#[allow(variant_size_differences)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum ConstType {
    Boolean,
    Byte,
    Identifier(Identifier),
    Octet,
    RestrictedDouble,
    RestrictedFloat,
    SignedLong,
    SignedLongLong,
    SignedShort,
    UnrestrictedDouble,
    UnrestrictedFloat,
    UnsignedLong,
    UnsignedLongLong,
    UnsignedShort,
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ConstValue {
    BooleanLiteral(bool),
    FloatLiteral(f64),
    IntegerLiteral(i64),
    Null,
}

#[derive(Clone, Debug, PartialEq)]
pub enum DefaultValue {
    ConstValue(ConstValue),
    EmptySequence,
    StringLiteral(String),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Definition {
    Callback(Callback),
    Dictionary(Dictionary),
    Enum(Enum),
    Includes(Includes),
    Interface(Interface),
    Mixin(Mixin),
    Namespace(Namespace),
    Typedef(Typedef),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Dictionary {
    NonPartial(NonPartialDictionary),
    Partial(PartialDictionary),
}

#[derive(Clone, Debug, PartialEq)]
pub struct DictionaryMember {
    pub default: Option<DefaultValue>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub required: bool,
    pub type_: Box<Type>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Enum {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: String,
    pub variants: Vec<String>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct ExplicitStringifierOperation {
    pub arguments: Vec<Argument>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Option<Identifier>,
    pub return_type: ReturnType,
}

#[derive(Clone, Debug, PartialEq)]
pub enum ExtendedAttribute {
    ArgumentList(ArgumentListExtendedAttribute),
    Identifier(IdentifierExtendedAttribute),
    IdentifierList(IdentifierListExtendedAttribute),
    NamedArgumentList(NamedArgumentListExtendedAttribute),
    NoArguments(Other),
    // Other(OtherExtendedAttribute),
}

#[derive(Clone, Debug, PartialEq)]
pub struct IdentifierExtendedAttribute {
    pub lhs: Identifier,
    pub rhs: Other,
}

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct IdentifierListExtendedAttribute {
    pub lhs: Identifier,
    pub rhs: Vec<Identifier>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct ImplicitStringifierOperation {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Includes {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub includee: Identifier,
    pub includer: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Interface {
    Callback(CallbackInterface),
    NonPartial(NonPartialInterface),
    Partial(PartialInterface),
}

#[derive(Clone, Debug, PartialEq)]
pub enum InterfaceMember {
    Attribute(Attribute),
    Const(Const),
    Iterable(Iterable),
    Maplike(Maplike),
    Operation(Operation),
    Setlike(Setlike),
}

#[derive(Clone, Debug, PartialEq)]
pub struct Iterable {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub key_type: Option<Box<Type>>,
    pub value_type: Box<Type>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Maplike {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub key_type: Box<Type>,
    pub read_only: bool,
    pub value_type: Box<Type>,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Mixin {
    NonPartial(NonPartialMixin),
    Partial(PartialMixin),
}

#[derive(Clone, Debug, PartialEq)]
pub enum MixinMember {
    Attribute(Attribute),
    Const(Const),
    Operation(Operation),
}

#[derive(Clone, Debug, PartialEq)]
pub struct NamedArgumentListExtendedAttribute {
    pub lhs_name: Identifier,
    pub rhs_arguments: Vec<Argument>,
    pub rhs_name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Namespace {
    NonPartial(NonPartialNamespace),
    Partial(PartialNamespace),
}

#[derive(Clone, Debug, PartialEq)]
pub enum NamespaceMember {
    Attribute(Attribute),
    Operation(Operation),
}

#[derive(Clone, Debug, PartialEq)]
pub struct NonPartialDictionary {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub inherits: Option<Identifier>,
    pub members: Vec<DictionaryMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct NonPartialInterface {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub inherits: Option<Identifier>,
    pub members: Vec<InterfaceMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct NonPartialMixin {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<MixinMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct NonPartialNamespace {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<NamespaceMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Operation {
    Regular(RegularOperation),
    Special(SpecialOperation),
    Static(StaticOperation),
    Stringifier(StringifierOperation),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Other {
    Any,
    ArrayBuffer,
    Attribute,
    Boolean,
    Byte,
    ByteString,
    Callback,
    Const,
    DOMString,
    DataView,
    Deleter,
    Dictionary,
    Double,
    Enum,
    False,
    Float,
    Float32Array,
    Float64Array,
    FrozenArray,
    Getter,
    Includes,
    Inherit,
    Int16Array,
    Int32Array,
    Int8Array,
    Interface,
    Iterable,
    Long,
    Maplike,
    Namespace,
    NegativeInfinity,
    NaN,
    Null,
    Object,
    Octet,
    Optional,
    Or,
    Partial,
    PositiveInfinity,
    Required,
    Sequence,
    Setlike,
    Setter,
    Short,
    Static,
    Stringifier,
    True,
    Typedef,
    USVString,
    Uint16Array,
    Uint32Array,
    Uint8Array,
    Uint8ClampedArray,
    Unrestricted,
    Unsigned,
    Void,

    FloatLiteral(f64),
    Identifier(Identifier),
    IntegerLiteral(i64),
    OtherLiteral(char),
    StringLiteral(String),

    Colon,
    Ellipsis,
    Equals,
    GreaterThan,
    Hyphen,
    LessThan,
    Period,
    QuestionMark,
    Semicolon,
}

#[derive(Clone, Debug, PartialEq)]
pub enum OtherExtendedAttribute {
    Nested {
        group_type: OtherExtendedAttributeGroupType,
        inner: Option<Box<ExtendedAttribute>>,
        rest: Option<Box<ExtendedAttribute>>,
    },
    Other {
        other: Option<Other>,
        rest: Option<Box<ExtendedAttribute>>,
    },
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum OtherExtendedAttributeGroupType {
    Brace,
    Bracket,
    Parenthesis,
}

#[derive(Clone, Debug, PartialEq)]
pub struct PartialDictionary {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<DictionaryMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct PartialInterface {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<InterfaceMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct PartialMixin {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<MixinMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct PartialNamespace {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<NamespaceMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct RegularAttribute {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub inherits: bool,
    pub name: Identifier,
    pub read_only: bool,
    pub type_: Box<Type>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct RegularOperation {
    pub arguments: Vec<Argument>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Option<Identifier>,
    pub return_type: ReturnType,
}

#[derive(Clone, Debug, PartialEq)]
pub enum ReturnType {
    NonVoid(Box<Type>),
    Void,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Setlike {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub read_only: bool,
    pub type_: Box<Type>,
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Special {
    Deleter,
    Getter,
    Setter,
}

#[derive(Clone, Debug, PartialEq)]
pub struct SpecialOperation {
    pub arguments: Vec<Argument>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Option<Identifier>,
    pub return_type: ReturnType,
    pub special_keywords: Vec<Special>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct StaticAttribute {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub read_only: bool,
    pub type_: Box<Type>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct StaticOperation {
    pub arguments: Vec<Argument>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Option<Identifier>,
    pub return_type: ReturnType,
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum StringType {
    ByteString,
    DOMString,
    USVString,
}

#[derive(Clone, Debug, PartialEq)]
pub struct StringifierAttribute {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub read_only: bool,
    pub type_: Box<Type>,
}

#[allow(variant_size_differences)]
#[derive(Clone, Debug, PartialEq)]
pub enum StringifierOperation {
    Explicit(ExplicitStringifierOperation),
    Implicit(ImplicitStringifierOperation),
}

#[derive(Clone, Debug, PartialEq)]
pub struct Type {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub kind: TypeKind,
    pub nullable: bool,
}

#[derive(Clone, Debug, PartialEq)]
pub enum TypeKind {
    Any,
    ArrayBuffer,
    Boolean,
    Byte,
    ByteString,
    DOMString,
    DataView,
    Error,
    Float32Array,
    Float64Array,
    FrozenArray(Box<Type>),
    Identifier(Identifier),
    Int16Array,
    Int32Array,
    Int8Array,
    Octet,
    Object,
    Promise(ReturnType),
    Record(StringType, Box<Type>),
    RestrictedDouble,
    RestrictedFloat,
    Sequence(Box<Type>),
    SignedLong,
    SignedLongLong,
    SignedShort,
    Symbol,
    USVString,
    Uint16Array,
    Uint32Array,
    Uint8Array,
    Uint8ClampedArray,
    Union(Vec<Box<Type>>),
    UnrestrictedDouble,
    UnrestrictedFloat,
    UnsignedLong,
    UnsignedLongLong,
    UnsignedShort,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Typedef {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub type_: Box<Type>,
}

/// Consumes a vector of ASTs that are flattened into a single AST. This is helpful if you want to
/// merge ASTs from multiple files and be able to use the visitor pattern across all of them.
pub fn flatten_asts(asts: Vec<AST>) -> AST {
    asts.into_iter().flat_map(|ast| ast).collect()
}

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

    #[test]
    fn test_flatten_asts() {
        let ast1 = vec![
            Definition::Interface(Interface::NonPartial(NonPartialInterface {
                extended_attributes: vec![],
                inherits: None,
                members: vec![],
                name: "Node".to_string(),
            })),
        ];
        let ast2 = vec![
            Definition::Typedef(Typedef {
                extended_attributes: vec![],
                name: "Typedef".to_string(),
                type_: Box::new(Type {
                    extended_attributes: vec![],
                    kind: TypeKind::Any,
                    nullable: false,
                }),
            }),
        ];

        assert_eq!(
            flatten_asts(vec![ast1.clone(), ast2.clone()]),
            vec![ast1[0].clone(), ast2[0].clone()]
        );
    }
}
<commit_msg>add notes about grammar only types<commit_after>#![allow(missing_docs)]

pub type AST = Vec<Definition>;
pub type Identifier = String;

// The following structures are used to help simplify building the AST in the grammar. Ideally
// these would not be exposed outside the crate, but the compiler seems to think they are exposed
// as private types when `pub(super)` is used. This is not the case since all of their variants are
// matched into other structures, but I suppose it is not a big deal.

/// Do not use - for grammar use only.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub(super) enum BufferRelatedType {
    ArrayBuffer,
    DataView,
    Float32Array,
    Float64Array,
    Int16Array,
    Int32Array,
    Int8Array,
    Uint16Array,
    Uint32Array,
    Uint8Array,
    Uint8ClampedArray,
}

/// Do not use - for grammar use only.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum PrimitiveType {
    Boolean,
    Byte,
    Octet,
    UnrestrictedFloat(UnrestrictedFloatType),
    UnsignedInteger(UnsignedIntegerType),
}

/// Do not use - for grammar use only.
#[derive(Clone, Debug, PartialEq)]
pub enum Stringifier {
    Attribute(Attribute),
    Operation(Operation),
}

/// Do not use - for grammar use only.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum UnrestrictedFloatType {
    RestrictedDouble,
    RestrictedFloat,
    UnrestrictedDouble,
    UnrestrictedFloat,
}

/// Do not use - for grammar use only.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum UnsignedIntegerType {
    SignedLong,
    SignedLongLong,
    SignedShort,
    UnsignedLong,
    UnsignedLongLong,
    UnsignedShort,
}

// Publically available AST structures

#[derive(Clone, Debug, PartialEq)]
pub struct Argument {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub default: Option<DefaultValue>,
    pub name: Identifier,
    pub optional: bool,
    pub type_: Box<Type>,
    pub variadic: bool,
}

#[derive(Clone, Debug, PartialEq)]
pub struct ArgumentListExtendedAttribute {
    pub arguments: Vec<Argument>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Attribute {
    Regular(RegularAttribute),
    Static(StaticAttribute),
    Stringifier(StringifierAttribute),
}

#[derive(Clone, Debug, PartialEq)]
pub struct Callback {
    pub arguments: Vec<Argument>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub return_type: ReturnType,
}

#[derive(Clone, Debug, PartialEq)]
pub struct CallbackInterface {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub inherits: Option<Identifier>,
    pub members: Vec<InterfaceMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Const {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub nullable: bool,
    pub type_: ConstType,
    pub value: ConstValue,
}

#[allow(variant_size_differences)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum ConstType {
    Boolean,
    Byte,
    Identifier(Identifier),
    Octet,
    RestrictedDouble,
    RestrictedFloat,
    SignedLong,
    SignedLongLong,
    SignedShort,
    UnrestrictedDouble,
    UnrestrictedFloat,
    UnsignedLong,
    UnsignedLongLong,
    UnsignedShort,
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ConstValue {
    BooleanLiteral(bool),
    FloatLiteral(f64),
    IntegerLiteral(i64),
    Null,
}

#[derive(Clone, Debug, PartialEq)]
pub enum DefaultValue {
    ConstValue(ConstValue),
    EmptySequence,
    StringLiteral(String),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Definition {
    Callback(Callback),
    Dictionary(Dictionary),
    Enum(Enum),
    Includes(Includes),
    Interface(Interface),
    Mixin(Mixin),
    Namespace(Namespace),
    Typedef(Typedef),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Dictionary {
    NonPartial(NonPartialDictionary),
    Partial(PartialDictionary),
}

#[derive(Clone, Debug, PartialEq)]
pub struct DictionaryMember {
    pub default: Option<DefaultValue>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub required: bool,
    pub type_: Box<Type>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Enum {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: String,
    pub variants: Vec<String>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct ExplicitStringifierOperation {
    pub arguments: Vec<Argument>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Option<Identifier>,
    pub return_type: ReturnType,
}

#[derive(Clone, Debug, PartialEq)]
pub enum ExtendedAttribute {
    ArgumentList(ArgumentListExtendedAttribute),
    Identifier(IdentifierExtendedAttribute),
    IdentifierList(IdentifierListExtendedAttribute),
    NamedArgumentList(NamedArgumentListExtendedAttribute),
    NoArguments(Other),
    // Other(OtherExtendedAttribute),
}

#[derive(Clone, Debug, PartialEq)]
pub struct IdentifierExtendedAttribute {
    pub lhs: Identifier,
    pub rhs: Other,
}

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct IdentifierListExtendedAttribute {
    pub lhs: Identifier,
    pub rhs: Vec<Identifier>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct ImplicitStringifierOperation {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Includes {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub includee: Identifier,
    pub includer: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Interface {
    Callback(CallbackInterface),
    NonPartial(NonPartialInterface),
    Partial(PartialInterface),
}

#[derive(Clone, Debug, PartialEq)]
pub enum InterfaceMember {
    Attribute(Attribute),
    Const(Const),
    Iterable(Iterable),
    Maplike(Maplike),
    Operation(Operation),
    Setlike(Setlike),
}

#[derive(Clone, Debug, PartialEq)]
pub struct Iterable {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub key_type: Option<Box<Type>>,
    pub value_type: Box<Type>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Maplike {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub key_type: Box<Type>,
    pub read_only: bool,
    pub value_type: Box<Type>,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Mixin {
    NonPartial(NonPartialMixin),
    Partial(PartialMixin),
}

#[derive(Clone, Debug, PartialEq)]
pub enum MixinMember {
    Attribute(Attribute),
    Const(Const),
    Operation(Operation),
}

#[derive(Clone, Debug, PartialEq)]
pub struct NamedArgumentListExtendedAttribute {
    pub lhs_name: Identifier,
    pub rhs_arguments: Vec<Argument>,
    pub rhs_name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Namespace {
    NonPartial(NonPartialNamespace),
    Partial(PartialNamespace),
}

#[derive(Clone, Debug, PartialEq)]
pub enum NamespaceMember {
    Attribute(Attribute),
    Operation(Operation),
}

#[derive(Clone, Debug, PartialEq)]
pub struct NonPartialDictionary {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub inherits: Option<Identifier>,
    pub members: Vec<DictionaryMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct NonPartialInterface {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub inherits: Option<Identifier>,
    pub members: Vec<InterfaceMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct NonPartialMixin {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<MixinMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct NonPartialNamespace {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<NamespaceMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Operation {
    Regular(RegularOperation),
    Special(SpecialOperation),
    Static(StaticOperation),
    Stringifier(StringifierOperation),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Other {
    Any,
    ArrayBuffer,
    Attribute,
    Boolean,
    Byte,
    ByteString,
    Callback,
    Const,
    DOMString,
    DataView,
    Deleter,
    Dictionary,
    Double,
    Enum,
    False,
    Float,
    Float32Array,
    Float64Array,
    FrozenArray,
    Getter,
    Includes,
    Inherit,
    Int16Array,
    Int32Array,
    Int8Array,
    Interface,
    Iterable,
    Long,
    Maplike,
    Namespace,
    NegativeInfinity,
    NaN,
    Null,
    Object,
    Octet,
    Optional,
    Or,
    Partial,
    PositiveInfinity,
    Required,
    Sequence,
    Setlike,
    Setter,
    Short,
    Static,
    Stringifier,
    True,
    Typedef,
    USVString,
    Uint16Array,
    Uint32Array,
    Uint8Array,
    Uint8ClampedArray,
    Unrestricted,
    Unsigned,
    Void,

    FloatLiteral(f64),
    Identifier(Identifier),
    IntegerLiteral(i64),
    OtherLiteral(char),
    StringLiteral(String),

    Colon,
    Ellipsis,
    Equals,
    GreaterThan,
    Hyphen,
    LessThan,
    Period,
    QuestionMark,
    Semicolon,
}

#[derive(Clone, Debug, PartialEq)]
pub enum OtherExtendedAttribute {
    Nested {
        group_type: OtherExtendedAttributeGroupType,
        inner: Option<Box<ExtendedAttribute>>,
        rest: Option<Box<ExtendedAttribute>>,
    },
    Other {
        other: Option<Other>,
        rest: Option<Box<ExtendedAttribute>>,
    },
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum OtherExtendedAttributeGroupType {
    Brace,
    Bracket,
    Parenthesis,
}

#[derive(Clone, Debug, PartialEq)]
pub struct PartialDictionary {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<DictionaryMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct PartialInterface {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<InterfaceMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct PartialMixin {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<MixinMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct PartialNamespace {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub members: Vec<NamespaceMember>,
    pub name: Identifier,
}

#[derive(Clone, Debug, PartialEq)]
pub struct RegularAttribute {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub inherits: bool,
    pub name: Identifier,
    pub read_only: bool,
    pub type_: Box<Type>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct RegularOperation {
    pub arguments: Vec<Argument>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Option<Identifier>,
    pub return_type: ReturnType,
}

#[derive(Clone, Debug, PartialEq)]
pub enum ReturnType {
    NonVoid(Box<Type>),
    Void,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Setlike {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub read_only: bool,
    pub type_: Box<Type>,
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Special {
    Deleter,
    Getter,
    Setter,
}

#[derive(Clone, Debug, PartialEq)]
pub struct SpecialOperation {
    pub arguments: Vec<Argument>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Option<Identifier>,
    pub return_type: ReturnType,
    pub special_keywords: Vec<Special>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct StaticAttribute {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub read_only: bool,
    pub type_: Box<Type>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct StaticOperation {
    pub arguments: Vec<Argument>,
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Option<Identifier>,
    pub return_type: ReturnType,
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum StringType {
    ByteString,
    DOMString,
    USVString,
}

#[derive(Clone, Debug, PartialEq)]
pub struct StringifierAttribute {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub read_only: bool,
    pub type_: Box<Type>,
}

#[allow(variant_size_differences)]
#[derive(Clone, Debug, PartialEq)]
pub enum StringifierOperation {
    Explicit(ExplicitStringifierOperation),
    Implicit(ImplicitStringifierOperation),
}

#[derive(Clone, Debug, PartialEq)]
pub struct Type {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub kind: TypeKind,
    pub nullable: bool,
}

#[derive(Clone, Debug, PartialEq)]
pub enum TypeKind {
    Any,
    ArrayBuffer,
    Boolean,
    Byte,
    ByteString,
    DOMString,
    DataView,
    Error,
    Float32Array,
    Float64Array,
    FrozenArray(Box<Type>),
    Identifier(Identifier),
    Int16Array,
    Int32Array,
    Int8Array,
    Octet,
    Object,
    Promise(ReturnType),
    Record(StringType, Box<Type>),
    RestrictedDouble,
    RestrictedFloat,
    Sequence(Box<Type>),
    SignedLong,
    SignedLongLong,
    SignedShort,
    Symbol,
    USVString,
    Uint16Array,
    Uint32Array,
    Uint8Array,
    Uint8ClampedArray,
    Union(Vec<Box<Type>>),
    UnrestrictedDouble,
    UnrestrictedFloat,
    UnsignedLong,
    UnsignedLongLong,
    UnsignedShort,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Typedef {
    pub extended_attributes: Vec<Box<ExtendedAttribute>>,
    pub name: Identifier,
    pub type_: Box<Type>,
}

/// Consumes a vector of ASTs that are flattened into a single AST. This is helpful if you want to
/// merge ASTs from multiple files and be able to use the visitor pattern across all of them.
pub fn flatten_asts(asts: Vec<AST>) -> AST {
    asts.into_iter().flat_map(|ast| ast).collect()
}

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

    #[test]
    fn test_flatten_asts() {
        let ast1 = vec![
            Definition::Interface(Interface::NonPartial(NonPartialInterface {
                extended_attributes: vec![],
                inherits: None,
                members: vec![],
                name: "Node".to_string(),
            })),
        ];
        let ast2 = vec![
            Definition::Typedef(Typedef {
                extended_attributes: vec![],
                name: "Typedef".to_string(),
                type_: Box::new(Type {
                    extended_attributes: vec![],
                    kind: TypeKind::Any,
                    nullable: false,
                }),
            }),
        ];

        assert_eq!(
            flatten_asts(vec![ast1.clone(), ast2.clone()]),
            vec![ast1[0].clone(), ast2[0].clone()]
        );
    }
}
<|endoftext|>


<commit_before>use ascii::{AsciiChar, AsciiStr};
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::convert::AsRef;
use std::iter::{ExactSizeIterator, Iterator};
use std::ops::{Index, IndexMut, Range, RangeFull, RangeFrom, RangeTo};
use std::slice::{Iter, IterMut};
use ::{PASCAL_STRING_BUF_SIZE, PascalString};

/// A borrowed slice from a `PascalString`. Does not own its data.
#[derive(Eq, Hash, PartialEq, PartialOrd)]
pub struct PascalStr {
    /// The `AsciiStr`, borrowed from the original `PascalString`
    string: AsciiStr
}

impl PascalStr {
    /// Get a pointer to the first byte of the string buffer.
    #[inline]
    pub fn as_ptr(&self) -> *const AsciiChar {
        self.string.as_ptr()
    }

    /// Get a mutable pointer to the first byte of the string buffer.
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut AsciiChar {
        self.string.as_mut_ptr()
    }

    /// Get the `PascalStr` as an immutable `&str` reference.
    #[inline]
    pub fn as_str(&self) -> &str {
        self.string.as_str()
    }

    /// Returns the number of characters used in the string.
    #[inline]
    pub fn len(&self) -> usize {
        self.string.len()
    }

    /// Returns true if the string has a length of 0
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns true if the string has a length of 255.
    ///
    /// When this value is true, no more elements can be pushed onto the string.
    #[inline]
    pub fn is_full(&self) -> bool {
        self.len() == PASCAL_STRING_BUF_SIZE
    }

    /// Get an immutable iterator to the internal character array.
    #[inline]
    pub fn chars<'a>(&'a self) -> Chars<'a> {
        Chars(self.string.as_slice().iter())
    }

    /// Get a mutable iterator to the internal character array.
    #[inline]
    pub fn chars_mut<'a>(&'a mut self) -> CharsMut<'a> {
        CharsMut(self.string.as_mut_slice().iter_mut())
    }
}

impl AsciiExt for PascalStr {
    type Owned = PascalString;

    fn is_ascii(&self) -> bool {
        true
    }

    fn to_ascii_uppercase(&self) -> Self::Owned {
        let bytes: &[u8] = self.as_ref();
        let mut upper = PascalString::from(bytes).unwrap();
        upper.make_ascii_uppercase();
        upper
    }

    fn to_ascii_lowercase(&self) -> Self::Owned {
        let bytes: &[u8] = self.as_ref();
        let mut lower = PascalString::from(bytes).unwrap();
        lower.make_ascii_lowercase();
        lower
    }

    fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
        self.string.eq_ignore_ascii_case(&other.string)
    }

    fn make_ascii_uppercase(&mut self) {
        self.string.make_ascii_uppercase()
    }

    fn make_ascii_lowercase(&mut self) {
        self.string.make_ascii_lowercase()
    }
}

impl ToOwned for PascalStr {
    type Owned = PascalString;
    fn to_owned(&self) -> Self::Owned {
        PascalString::from(&self.string).unwrap()
    }
}

impl AsRef<str> for PascalStr {
    fn as_ref(&self) -> &str {
        self.string.as_ref()
    }
}

impl AsRef<[u8]> for PascalStr {
    fn as_ref(&self) -> &[u8] {
        self.string.as_ref()
    }
}

impl AsRef<AsciiStr> for PascalStr {
    fn as_ref(&self) -> &AsciiStr {
        &self.string
    }
}

impl AsMut<AsciiStr> for PascalStr {
    fn as_mut(&mut self) -> &mut AsciiStr {
        &mut self.string
    }
}

impl AsRef<[AsciiChar]> for PascalStr {
    fn as_ref(&self) -> &[AsciiChar] {
        self.string.as_ref()
    }
}

impl AsMut<[AsciiChar]> for PascalStr {
    fn as_mut(&mut self) -> &mut [AsciiChar] {
        self.string.as_mut()
    }
}

impl Index<u8> for PascalStr {
    type Output = AsciiChar;
    fn index(&self, index: u8) -> &Self::Output {
        let index = index as usize;
        assert!(index < self.len());
        &self.string[index]
    }
}

impl IndexMut<u8> for PascalStr {
    fn index_mut(&mut self, index: u8) -> &mut Self::Output {
        let index = index as usize;
        assert!(index < self.len());
        &mut self.string[index]
    }
}

impl Index<usize> for PascalStr {
    type Output = AsciiChar;
    fn index(&self, index: usize) -> &Self::Output {
        assert!(index < self.len());
        &self.string[index]
    }
}

impl IndexMut<usize> for PascalStr {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        assert!(index < self.len());
        &mut self.string[index]
    }
}

impl Index<RangeFull> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, _: RangeFull) -> &Self::Output {
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[..]
    }
}

impl IndexMut<RangeFull> for PascalStr {
    fn index_mut(&mut self, _: RangeFull) -> &mut Self::Output {
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[..]
    }
}

impl Index<Range<u8>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: Range<u8>) -> &Self::Output {
        assert!((range.end as usize) < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[range.start as usize..range.end as usize]
    }
}

impl IndexMut<Range<u8>> for PascalStr {
    fn index_mut(&mut self, range: Range<u8>) -> &mut Self::Output {
        assert!((range.end as usize) < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[range.start as usize..range.end as usize]
    }
}

impl Index<Range<usize>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: Range<usize>) -> &Self::Output {
        assert!(range.end < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[range.start..range.end]
    }
}

impl IndexMut<Range<usize>> for PascalStr {
    fn index_mut(&mut self, range: Range<usize>) -> &mut Self::Output {
        assert!(range.end < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[range.start..range.end]
    }
}

impl Index<RangeFrom<u8>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: RangeFrom<u8>) -> &Self::Output {
        assert!((range.start as usize) < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[range.start as usize..]
    }
}

impl IndexMut<RangeFrom<u8>> for PascalStr {
    fn index_mut(&mut self, range: RangeFrom<u8>) -> &mut Self::Output {
        assert!((range.start as usize) < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[range.start as usize..]
    }
}

impl Index<RangeFrom<usize>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: RangeFrom<usize>) -> &Self::Output {
        assert!(range.start < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[range.start..]
    }
}

impl IndexMut<RangeFrom<usize>> for PascalStr {
    fn index_mut(&mut self, range: RangeFrom<usize>) -> &mut Self::Output {
        assert!(range.start < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[range.start..]
    }
}

impl Index<RangeTo<u8>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: RangeTo<u8>) -> &Self::Output {
        assert!((range.end as usize) < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[..range.end as usize]
    }
}

impl IndexMut<RangeTo<u8>> for PascalStr {
    fn index_mut(&mut self, range: RangeTo<u8>) -> &mut Self::Output {
        assert!((range.end as usize) < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[..range.end as usize]
    }
}

impl Index<RangeTo<usize>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: RangeTo<usize>) -> &Self::Output {
        assert!(range.end < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[..range.end]
    }
}

impl IndexMut<RangeTo<usize>> for PascalStr {
    fn index_mut(&mut self, range: RangeTo<usize>) -> &mut Self::Output {
        assert!(range.end < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[..range.end]
    }
}

/// An immutable iterator over the buffer of a `PascalStr`.
pub struct Chars<'a>(Iter<'a, AsciiChar>);

impl<'a> Iterator for Chars<'a> {
    type Item = &'a AsciiChar;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

impl<'a> ExactSizeIterator for Chars<'a> {
    fn len(&self) -> usize {
        self.0.len()
    }
}

/// A mutable iterator over the buffer of a `PascalStr`.
pub struct CharsMut<'a>(IterMut<'a, AsciiChar>);

impl<'a> Iterator for CharsMut<'a> {
    type Item = &'a mut AsciiChar;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

impl<'a> ExactSizeIterator for CharsMut<'a> {
    fn len(&self) -> usize {
        self.0.len()
    }
}
<commit_msg>Add PascalStr::as_cstr<commit_after>use ascii::{AsciiChar, AsciiStr};
use std::ascii::AsciiExt;
use std::borrow::{Cow, ToOwned};
use std::convert::AsRef;
use std::ffi::{CStr, CString};
use std::iter::{ExactSizeIterator, Iterator};
use std::ops::{Index, IndexMut, Range, RangeFull, RangeFrom, RangeTo};
use std::slice::{Iter, IterMut};
use ::{PASCAL_STRING_BUF_SIZE, PascalString};

/// A borrowed slice from a `PascalString`. Does not own its data.
#[derive(Eq, Hash, PartialEq, PartialOrd)]
pub struct PascalStr {
    /// The `AsciiStr`, borrowed from the original `PascalString`
    string: AsciiStr
}

impl PascalStr {
    /// Get a pointer to the first byte of the string buffer.
    #[inline]
    pub fn as_ptr(&self) -> *const AsciiChar {
        self.string.as_ptr()
    }

    /// Get a mutable pointer to the first byte of the string buffer.
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut AsciiChar {
        self.string.as_mut_ptr()
    }

    /// Get the `PascalStr` as an immutable `&str` reference.
    #[inline]
    pub fn as_str(&self) -> &str {
        self.string.as_str()
    }

    /// Get this string as a `CStr`.
    ///
    /// Returns `None` if the string contains any interior nulls. If this string is full, then a new `CString` will
    /// be allocated to hold the trailing null byte.
    #[inline]
    pub fn as_cstr(&self) -> Option<Cow<CStr>> {
        if self.chars().any(|&c| c == AsciiChar::Null) {
            None
        } else if self.is_full() {
            let str_clone = self.to_owned();
            Some(Cow::Owned(CString::new(str_clone).unwrap()))
        } else {
            Some(Cow::Borrowed(CStr::from_bytes_with_nul(self.as_ref()).unwrap()))
        }
    }

    /// Returns the number of characters used in the string.
    #[inline]
    pub fn len(&self) -> usize {
        self.string.len()
    }

    /// Returns true if the string has a length of 0
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns true if the string has a length of 255.
    ///
    /// When this value is true, no more elements can be pushed onto the string.
    #[inline]
    pub fn is_full(&self) -> bool {
        self.len() == PASCAL_STRING_BUF_SIZE
    }

    /// Get an immutable iterator to the internal character array.
    #[inline]
    pub fn chars<'a>(&'a self) -> Chars<'a> {
        Chars(self.string.as_slice().iter())
    }

    /// Get a mutable iterator to the internal character array.
    #[inline]
    pub fn chars_mut<'a>(&'a mut self) -> CharsMut<'a> {
        CharsMut(self.string.as_mut_slice().iter_mut())
    }
}

impl AsciiExt for PascalStr {
    type Owned = PascalString;

    fn is_ascii(&self) -> bool {
        true
    }

    fn to_ascii_uppercase(&self) -> Self::Owned {
        let bytes: &[u8] = self.as_ref();
        let mut upper = PascalString::from(bytes).unwrap();
        upper.make_ascii_uppercase();
        upper
    }

    fn to_ascii_lowercase(&self) -> Self::Owned {
        let bytes: &[u8] = self.as_ref();
        let mut lower = PascalString::from(bytes).unwrap();
        lower.make_ascii_lowercase();
        lower
    }

    fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
        self.string.eq_ignore_ascii_case(&other.string)
    }

    fn make_ascii_uppercase(&mut self) {
        self.string.make_ascii_uppercase()
    }

    fn make_ascii_lowercase(&mut self) {
        self.string.make_ascii_lowercase()
    }
}

impl ToOwned for PascalStr {
    type Owned = PascalString;
    fn to_owned(&self) -> Self::Owned {
        PascalString::from(&self.string).unwrap()
    }
}

impl AsRef<str> for PascalStr {
    fn as_ref(&self) -> &str {
        self.string.as_ref()
    }
}

impl AsRef<[u8]> for PascalStr {
    fn as_ref(&self) -> &[u8] {
        self.string.as_ref()
    }
}

impl AsRef<AsciiStr> for PascalStr {
    fn as_ref(&self) -> &AsciiStr {
        &self.string
    }
}

impl AsMut<AsciiStr> for PascalStr {
    fn as_mut(&mut self) -> &mut AsciiStr {
        &mut self.string
    }
}

impl AsRef<[AsciiChar]> for PascalStr {
    fn as_ref(&self) -> &[AsciiChar] {
        self.string.as_ref()
    }
}

impl AsMut<[AsciiChar]> for PascalStr {
    fn as_mut(&mut self) -> &mut [AsciiChar] {
        self.string.as_mut()
    }
}

impl Index<u8> for PascalStr {
    type Output = AsciiChar;
    fn index(&self, index: u8) -> &Self::Output {
        let index = index as usize;
        assert!(index < self.len());
        &self.string[index]
    }
}

impl IndexMut<u8> for PascalStr {
    fn index_mut(&mut self, index: u8) -> &mut Self::Output {
        let index = index as usize;
        assert!(index < self.len());
        &mut self.string[index]
    }
}

impl Index<usize> for PascalStr {
    type Output = AsciiChar;
    fn index(&self, index: usize) -> &Self::Output {
        assert!(index < self.len());
        &self.string[index]
    }
}

impl IndexMut<usize> for PascalStr {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        assert!(index < self.len());
        &mut self.string[index]
    }
}

impl Index<RangeFull> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, _: RangeFull) -> &Self::Output {
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[..]
    }
}

impl IndexMut<RangeFull> for PascalStr {
    fn index_mut(&mut self, _: RangeFull) -> &mut Self::Output {
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[..]
    }
}

impl Index<Range<u8>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: Range<u8>) -> &Self::Output {
        assert!((range.end as usize) < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[range.start as usize..range.end as usize]
    }
}

impl IndexMut<Range<u8>> for PascalStr {
    fn index_mut(&mut self, range: Range<u8>) -> &mut Self::Output {
        assert!((range.end as usize) < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[range.start as usize..range.end as usize]
    }
}

impl Index<Range<usize>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: Range<usize>) -> &Self::Output {
        assert!(range.end < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[range.start..range.end]
    }
}

impl IndexMut<Range<usize>> for PascalStr {
    fn index_mut(&mut self, range: Range<usize>) -> &mut Self::Output {
        assert!(range.end < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[range.start..range.end]
    }
}

impl Index<RangeFrom<u8>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: RangeFrom<u8>) -> &Self::Output {
        assert!((range.start as usize) < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[range.start as usize..]
    }
}

impl IndexMut<RangeFrom<u8>> for PascalStr {
    fn index_mut(&mut self, range: RangeFrom<u8>) -> &mut Self::Output {
        assert!((range.start as usize) < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[range.start as usize..]
    }
}

impl Index<RangeFrom<usize>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: RangeFrom<usize>) -> &Self::Output {
        assert!(range.start < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[range.start..]
    }
}

impl IndexMut<RangeFrom<usize>> for PascalStr {
    fn index_mut(&mut self, range: RangeFrom<usize>) -> &mut Self::Output {
        assert!(range.start < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[range.start..]
    }
}

impl Index<RangeTo<u8>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: RangeTo<u8>) -> &Self::Output {
        assert!((range.end as usize) < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[..range.end as usize]
    }
}

impl IndexMut<RangeTo<u8>> for PascalStr {
    fn index_mut(&mut self, range: RangeTo<u8>) -> &mut Self::Output {
        assert!((range.end as usize) < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[..range.end as usize]
    }
}

impl Index<RangeTo<usize>> for PascalStr {
    type Output = [AsciiChar];
    fn index(&self, range: RangeTo<usize>) -> &Self::Output {
        assert!(range.end < self.len());
        let char_array: &[AsciiChar] = self.string.as_ref();
        &char_array[..range.end]
    }
}

impl IndexMut<RangeTo<usize>> for PascalStr {
    fn index_mut(&mut self, range: RangeTo<usize>) -> &mut Self::Output {
        assert!(range.end < self.len());
        let char_array: &mut [AsciiChar] = self.string.as_mut();
        &mut char_array[..range.end]
    }
}

/// An immutable iterator over the buffer of a `PascalStr`.
pub struct Chars<'a>(Iter<'a, AsciiChar>);

impl<'a> Iterator for Chars<'a> {
    type Item = &'a AsciiChar;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

impl<'a> ExactSizeIterator for Chars<'a> {
    fn len(&self) -> usize {
        self.0.len()
    }
}

/// A mutable iterator over the buffer of a `PascalStr`.
pub struct CharsMut<'a>(IterMut<'a, AsciiChar>);

impl<'a> Iterator for CharsMut<'a> {
    type Item = &'a mut AsciiChar;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

impl<'a> ExactSizeIterator for CharsMut<'a> {
    fn len(&self) -> usize {
        self.0.len()
    }
}
<|endoftext|>


<commit_before>// Regression tests from American Fuzzy Lop test cases.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

extern crate mp4parse;

use std::io::Cursor;

/// https://github.com/mozilla/mp4parse-rust/issues/2
#[test]
fn fuzz_2() {
    let mut c = Cursor::new(b"\x00\x00\x00\x04\xa6\x00\x04\xa6".to_vec());
    let mut context = mp4parse::MediaContext::new();
    let _ = mp4parse::read_box(&mut c, &mut context);
}

/// https://github.com/mozilla/mp4parse-rust/issues/4
#[test]
fn fuzz_4() {
    let mut c = Cursor::new(b"\x00\x00\x00\x01\x30\x30\x30\x30\x00\x00\x00\x00\x00\x00\x00\x00".to_vec());
    let mut context = mp4parse::MediaContext::new();
    let _ = mp4parse::read_box(&mut c, &mut context);
}
<commit_msg>Add regression test from fuzzing.<commit_after>// Regression tests from American Fuzzy Lop test cases.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

extern crate mp4parse;

use std::io::Cursor;

/// https://github.com/mozilla/mp4parse-rust/issues/2
#[test]
fn fuzz_2() {
    let mut c = Cursor::new(b"\x00\x00\x00\x04\xa6\x00\x04\xa6".to_vec());
    let mut context = mp4parse::MediaContext::new();
    let _ = mp4parse::read_box(&mut c, &mut context);
}

/// https://github.com/mozilla/mp4parse-rust/issues/4
#[test]
fn fuzz_4() {
    let mut c = Cursor::new(b"\x00\x00\x00\x01\x30\x30\x30\x30\x00\x00\x00\x00\x00\x00\x00\x00".to_vec());
    let mut context = mp4parse::MediaContext::new();
    let _ = mp4parse::read_box(&mut c, &mut context);
}

/// https://github.com/mozilla/mp4parse-rust/issues/5
#[test]
fn fuzz_5() {
    let mut c =
    Cursor::new(b"\x30\x30\x30\x30\x66\x74\x79\x70\x30\x30\x30\x30\x30\x30\x30\x30".to_vec());
    let mut context = mp4parse::MediaContext::new();
    let _ = mp4parse::read_box(&mut c, &mut context);
}
<|endoftext|>


<commit_before>extern crate trustines;

mod memory {
    use trustines::memory::Memory;

    #[test]
    fn read8_basic() {
        let mut m = Memory::new();
        m.mem[0] = 5;
        m.mem[1] = 10;
        assert_eq!(5,m.read8(0).unwrap());
        assert_eq!(10,m.read8(1).unwrap());
    }
    #[test]
    fn write8_basic() {
        let mut m = Memory::new();
        m.write8(0,5);
        assert_eq!(5,m.mem[0]);

        m.write8(1,10);
        assert_eq!(5,m.mem[0]);
        assert_eq!(10,m.mem[1]);
    }

    #[test]
    fn read16_basic() {
        let mut m = Memory::new();
        m.mem[0] = 2;
        m.mem[1] = 1;
        assert_eq!(258,m.read16(0).unwrap());
        assert_eq!(1,m.read16(1).unwrap());
    }
    #[test]
    fn write16_basic() {
        let mut m = Memory::new();
        m.write16(0,258);
        assert_eq!(2,m.mem[0]);
        assert_eq!(1,m.mem[1]);
    }
    #[test]
    fn readwrite8() {
        let mut m = Memory::new();
        m.write8(0,5);
        m.write8(1,10);
        assert_eq!(5,m.read8(0).unwrap());
        assert_eq!(10,m.read8(1).unwrap());
    }
    #[test]
    fn readwrite16() {
        let mut m = Memory::new();
        m.write16(0,258);
        m.write16(2,300);
        assert_eq!(258,m.read16(0).unwrap());
        assert_eq!(300,m.read16(2).unwrap());
    }
}

<commit_msg>added test stubs for addressing mode tests<commit_after>extern crate trustines;

mod memory {
    use trustines::memory::Memory;

    #[test]
    fn read8_basic() {
        let mut m = Memory::new();
        m.mem[0] = 5;
        m.mem[1] = 10;
        assert_eq!(5,m.read8(0).unwrap());
        assert_eq!(10,m.read8(1).unwrap());
    }
    #[test]
    fn write8_basic() {
        let mut m = Memory::new();
        m.write8(0,5);
        assert_eq!(5,m.mem[0]);

        m.write8(1,10);
        assert_eq!(5,m.mem[0]);
        assert_eq!(10,m.mem[1]);
    }

    #[test]
    fn read16_basic() {
        let mut m = Memory::new();
        m.mem[0] = 2;
        m.mem[1] = 1;
        assert_eq!(258,m.read16(0).unwrap());
        assert_eq!(1,m.read16(1).unwrap());
    }
    #[test]
    fn write16_basic() {
        let mut m = Memory::new();
        m.write16(0,258);
        assert_eq!(2,m.mem[0]);
        assert_eq!(1,m.mem[1]);
    }
    #[test]
    fn readwrite8() {
        let mut m = Memory::new();
        m.write8(0,5);
        m.write8(1,10);
        assert_eq!(5,m.read8(0).unwrap());
        assert_eq!(10,m.read8(1).unwrap());
    }
    #[test]
    fn readwrite16() {
        let mut m = Memory::new();
        m.write16(0,258);
        m.write16(2,300);
        assert_eq!(258,m.read16(0).unwrap());
        assert_eq!(300,m.read16(2).unwrap());
    }
}

mod address_mode {
    #[test]
    fn absolute() {
    }
    #[test]
    fn absolute_x() {
    }
    #[test]
    fn absolute_y() {
    }
    #[test]
    fn accumulator() {
    }
    #[test]
    fn immediate() {
    }
    #[test]
    fn implied() {
    }
    #[test]
    fn indirect() {
    }
    #[test]
    fn indexed_indirect() {
    }
    #[test]
    fn indirect_indexed() {
    }
    #[test]
    fn relative() {
    }
    #[test]
    fn zeropage() {
    }
    #[test]
    fn zeropage_x() {
    }
    #[test]
    fn zeropage_y() {
    }
}

<|endoftext|>