<commit_before>//! Template declaration and instantiation related things.
//!
//! The nomenclature surrounding templates is often confusing, so here are a few
//! brief definitions:
//!
//! * "Template definition": a class/struct/alias/function definition that takes
//! generic template parameters. For example:
//!
//! ```c++
//! template<typename T>
//! class List<T> {
//!     // ...
//! };
//! ```
//!
//! * "Template instantiation": an instantiation is a use of a template with
//! concrete template arguments. For example, `List<int>`.
//!
//! * "Template specialization": an alternative template definition providing a
//! custom definition for instantiations with the matching template
//! arguments. This C++ feature is unsupported by bindgen. For example:
//!
//! ```c++
//! template<>
//! class List<int> {
//!     // Special layout for int lists...
//! };
//! ```

use super::context::{BindgenContext, ItemId, TypeId};
use super::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalPath};
use super::traversal::{EdgeKind, Trace, Tracer};
use clang;
use parse::ClangItemParser;

/// Template declaration (and such declaration's template parameters) related
/// methods.
///
/// This trait's methods distinguish between `None` and `Some([])` for
/// declarations that are not templates and template declarations with zero
/// parameters, in general.
///
/// Consider this example:
///
/// ```c++
/// template <typename T, typename U>
/// class Foo {
///     T use_of_t;
///     U use_of_u;
///
///     template <typename V>
///     using Bar = V*;
///
///     class Inner {
///         T        x;
///         U        y;
///         Bar<int> z;
///     };
///
///     template <typename W>
///     class Lol {
///         // No use of W, but here's a use of T.
///         T t;
///     };
///
///     template <typename X>
///     class Wtf {
///         // X is not used because W is not used.
///         Lol<X> lololol;
///     };
/// };
///
/// class Qux {
///     int y;
/// };
/// ```
///
/// The following table depicts the results of each trait method when invoked on
/// each of the declarations above:
///
/// +------+----------------------+--------------------------+------------------------+----
/// |Decl. | self_template_params | num_self_template_params | all_template_parameters| ...
/// +------+----------------------+--------------------------+------------------------+----
/// |Foo   | [T, U]               | 2                        | [T, U]                 | ...
/// |Bar   | [V]                  | 1                        | [T, U, V]              | ...
/// |Inner | []                   | 0                        | [T, U]                 | ...
/// |Lol   | [W]                  | 1                        | [T, U, W]              | ...
/// |Wtf   | [X]                  | 1                        | [T, U, X]              | ...
/// |Qux   | []                   | 0                        | []                     | ...
/// +------+----------------------+--------------------------+------------------------+----
///
/// ----+------+-----+----------------------+
/// ... |Decl. | ... | used_template_params |
/// ----+------+-----+----------------------+
/// ... |Foo   | ... | [T, U]               |
/// ... |Bar   | ... | [V]                  |
/// ... |Inner | ... | []                   |
/// ... |Lol   | ... | [T]                  |
/// ... |Wtf   | ... | [T]                  |
/// ... |Qux   | ... | []                   |
/// ----+------+-----+----------------------+
pub trait TemplateParameters {
    /// Get the set of `ItemId`s that make up this template declaration's free
    /// template parameters.
    ///
    /// Note that these might *not* all be named types: C++ allows
    /// constant-value template parameters as well as template-template
    /// parameters. Of course, Rust does not allow generic parameters to be
    /// anything but types, so we must treat them as opaque, and avoid
    /// instantiating them.
    fn self_template_params(&self, ctx: &BindgenContext)
        -> Vec<TypeId>;

    /// Get the number of free template parameters this template declaration
    /// has.
    fn num_self_template_params(&self, ctx: &BindgenContext) -> usize {
        self.self_template_params(ctx).len()
    }

    /// Get the complete set of template parameters that can affect this
    /// declaration.
    ///
    /// Note that this item doesn't need to be a template declaration itself for
    /// `Some` to be returned here (in contrast to `self_template_params`). If
    /// this item is a member of a template declaration, then the parent's
    /// template parameters are included here.
    ///
    /// In the example above, `Inner` depends on both of the `T` and `U` type
    /// parameters, even though it is not itself a template declaration and
    /// therefore has no type parameters itself. Perhaps it helps to think about
    /// how we would fully reference such a member type in C++:
    /// `Foo<int,char>::Inner`. `Foo` *must* be instantiated with template
    /// arguments before we can gain access to the `Inner` member type.
    fn all_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>
    where
        Self: ItemAncestors,
    {
        let ancestors: Vec<_> = self.ancestors(ctx).collect();
        ancestors.into_iter().rev().flat_map(|id| {
            id.self_template_params(ctx).into_iter()
        }).collect()
    }

    /// Get only the set of template parameters that this item uses. This is a
    /// subset of `all_template_params` and does not necessarily contain any of
    /// `self_template_params`.
    fn used_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>
    where
        Self: AsRef<ItemId>,
    {
        assert!(
            ctx.in_codegen_phase(),
            "template parameter usage is not computed until codegen"
        );

        let id = *self.as_ref();
        ctx.resolve_item(id).all_template_params(ctx)
                    .into_iter()
                    .filter(|p| ctx.uses_template_parameter(id, *p))
                    .collect()
    }
}

/// A trait for things which may or may not be a named template type parameter.
pub trait AsTemplateParam {
    /// Any extra information the implementor might need to make this decision.
    type Extra;

    /// Convert this thing to the item id of a named template type parameter.
    fn as_template_param(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> Option<TypeId>;

    /// Is this a named template type parameter?
    fn is_template_param(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> bool {
        self.as_template_param(ctx, extra).is_some()
    }
}

/// A concrete instantiation of a generic template.
#[derive(Clone, Debug)]
pub struct TemplateInstantiation {
    /// The template definition which this is instantiating.
    definition: TypeId,
    /// The concrete template arguments, which will be substituted in the
    /// definition for the generic template parameters.
    args: Vec<TypeId>,
}

impl TemplateInstantiation {
    /// Construct a new template instantiation from the given parts.
    pub fn new<I>(definition: TypeId, args: I) -> TemplateInstantiation
    where
        I: IntoIterator<Item = TypeId>,
    {
        TemplateInstantiation {
            definition,
            args: args.into_iter().collect(),
        }
    }

    /// Get the template definition for this instantiation.
    pub fn template_definition(&self) -> TypeId {
        self.definition
    }

    /// Get the concrete template arguments used in this instantiation.
    pub fn template_arguments(&self) -> &[TypeId] {
        &self.args[..]
    }

    /// Parse a `TemplateInstantiation` from a clang `Type`.
    pub fn from_ty(
        ty: &clang::Type,
        ctx: &mut BindgenContext,
    ) -> Option<TemplateInstantiation> {
        use clang_sys::*;

        let template_args = ty.template_args()
            .map_or(vec![], |args| {
                match ty.canonical_type().template_args() {
                    Some(canonical_args) => {
                        let arg_count = args.len();
                        args.chain(canonical_args.skip(arg_count))
                            .filter(|t| t.kind() != CXType_Invalid)
                            .map(|t| {
                                Item::from_ty_or_ref(t, t.declaration(), None, ctx)
                            }).collect()
                    }
                    None => {
                        args.filter(|t| t.kind() != CXType_Invalid)
                            .map(|t| {
                                Item::from_ty_or_ref(t, t.declaration(), None, ctx)
                            }).collect()
                    }
                }
            });

        let declaration = ty.declaration();
        let definition =
            if declaration.kind() == CXCursor_TypeAliasTemplateDecl {
                Some(declaration)
            } else {
                declaration.specialized().or_else(|| {
                    let mut template_ref = None;
                    ty.declaration().visit(|child| {
                    if child.kind() == CXCursor_TemplateRef {
                        template_ref = Some(child);
                        return CXVisit_Break;
                    }

                    // Instantiations of template aliases might have the
                    // TemplateRef to the template alias definition arbitrarily
                    // deep, so we need to recurse here and not only visit
                    // direct children.
                    CXChildVisit_Recurse
                });

                    template_ref.and_then(|cur| cur.referenced())
                })
            };

        let definition = match definition {
            Some(def) => def,
            None => {
                if !ty.declaration().is_builtin() {
                    warn!(
                        "Could not find template definition for template \
                           instantiation"
                    );
                }
                return None;
            }
        };

        let template_definition =
            Item::from_ty_or_ref(definition.cur_type(), definition, None, ctx);

        Some(TemplateInstantiation::new(
            template_definition,
            template_args,
        ))
    }
}

impl IsOpaque for TemplateInstantiation {
    type Extra = Item;

    /// Is this an opaque template instantiation?
    fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool {
        if self.template_definition().is_opaque(ctx, &()) {
            return true;
        }

        // TODO(#774): This doesn't properly handle opaque instantiations where
        // an argument is itself an instantiation because `canonical_name` does
        // not insert the template arguments into the name, ie it for nested
        // template arguments it creates "Foo" instead of "Foo<int>". The fully
        // correct fix is to make `canonical_{name,path}` include template
        // arguments properly.

        let mut path = item.canonical_path(ctx);
        let args: Vec<_> = self.template_arguments()
            .iter()
            .map(|arg| {
                let arg_path = arg.canonical_path(ctx);
                arg_path[1..].join("::")
            })
            .collect();
        {
            let last = path.last_mut().unwrap();
            last.push('<');
            last.push_str(&args.join(", "));
            last.push('>');
        }

        ctx.opaque_by_name(&path)
    }
}

impl Trace for TemplateInstantiation {
    type Extra = ();

    fn trace<T>(&self, _ctx: &BindgenContext, tracer: &mut T, _: &())
    where
        T: Tracer,
    {
        tracer.visit_kind(self.definition.into(), EdgeKind::TemplateDeclaration);
        for arg in self.template_arguments() {
            tracer.visit_kind(arg.into(), EdgeKind::TemplateArgument);
        }
    }
}
<commit_msg>Require TemplateParameters to be Sized.<commit_after>//! Template declaration and instantiation related things.
//!
//! The nomenclature surrounding templates is often confusing, so here are a few
//! brief definitions:
//!
//! * "Template definition": a class/struct/alias/function definition that takes
//! generic template parameters. For example:
//!
//! ```c++
//! template<typename T>
//! class List<T> {
//!     // ...
//! };
//! ```
//!
//! * "Template instantiation": an instantiation is a use of a template with
//! concrete template arguments. For example, `List<int>`.
//!
//! * "Template specialization": an alternative template definition providing a
//! custom definition for instantiations with the matching template
//! arguments. This C++ feature is unsupported by bindgen. For example:
//!
//! ```c++
//! template<>
//! class List<int> {
//!     // Special layout for int lists...
//! };
//! ```

use super::context::{BindgenContext, ItemId, TypeId};
use super::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalPath};
use super::traversal::{EdgeKind, Trace, Tracer};
use clang;
use parse::ClangItemParser;

/// Template declaration (and such declaration's template parameters) related
/// methods.
///
/// This trait's methods distinguish between `None` and `Some([])` for
/// declarations that are not templates and template declarations with zero
/// parameters, in general.
///
/// Consider this example:
///
/// ```c++
/// template <typename T, typename U>
/// class Foo {
///     T use_of_t;
///     U use_of_u;
///
///     template <typename V>
///     using Bar = V*;
///
///     class Inner {
///         T        x;
///         U        y;
///         Bar<int> z;
///     };
///
///     template <typename W>
///     class Lol {
///         // No use of W, but here's a use of T.
///         T t;
///     };
///
///     template <typename X>
///     class Wtf {
///         // X is not used because W is not used.
///         Lol<X> lololol;
///     };
/// };
///
/// class Qux {
///     int y;
/// };
/// ```
///
/// The following table depicts the results of each trait method when invoked on
/// each of the declarations above:
///
/// +------+----------------------+--------------------------+------------------------+----
/// |Decl. | self_template_params | num_self_template_params | all_template_parameters| ...
/// +------+----------------------+--------------------------+------------------------+----
/// |Foo   | [T, U]               | 2                        | [T, U]                 | ...
/// |Bar   | [V]                  | 1                        | [T, U, V]              | ...
/// |Inner | []                   | 0                        | [T, U]                 | ...
/// |Lol   | [W]                  | 1                        | [T, U, W]              | ...
/// |Wtf   | [X]                  | 1                        | [T, U, X]              | ...
/// |Qux   | []                   | 0                        | []                     | ...
/// +------+----------------------+--------------------------+------------------------+----
///
/// ----+------+-----+----------------------+
/// ... |Decl. | ... | used_template_params |
/// ----+------+-----+----------------------+
/// ... |Foo   | ... | [T, U]               |
/// ... |Bar   | ... | [V]                  |
/// ... |Inner | ... | []                   |
/// ... |Lol   | ... | [T]                  |
/// ... |Wtf   | ... | [T]                  |
/// ... |Qux   | ... | []                   |
/// ----+------+-----+----------------------+
pub trait TemplateParameters : Sized {
    /// Get the set of `ItemId`s that make up this template declaration's free
    /// template parameters.
    ///
    /// Note that these might *not* all be named types: C++ allows
    /// constant-value template parameters as well as template-template
    /// parameters. Of course, Rust does not allow generic parameters to be
    /// anything but types, so we must treat them as opaque, and avoid
    /// instantiating them.
    fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>;

    /// Get the number of free template parameters this template declaration
    /// has.
    fn num_self_template_params(&self, ctx: &BindgenContext) -> usize {
        self.self_template_params(ctx).len()
    }

    /// Get the complete set of template parameters that can affect this
    /// declaration.
    ///
    /// Note that this item doesn't need to be a template declaration itself for
    /// `Some` to be returned here (in contrast to `self_template_params`). If
    /// this item is a member of a template declaration, then the parent's
    /// template parameters are included here.
    ///
    /// In the example above, `Inner` depends on both of the `T` and `U` type
    /// parameters, even though it is not itself a template declaration and
    /// therefore has no type parameters itself. Perhaps it helps to think about
    /// how we would fully reference such a member type in C++:
    /// `Foo<int,char>::Inner`. `Foo` *must* be instantiated with template
    /// arguments before we can gain access to the `Inner` member type.
    fn all_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>
    where
        Self: ItemAncestors,
    {
        let ancestors: Vec<_> = self.ancestors(ctx).collect();
        ancestors.into_iter().rev().flat_map(|id| {
            id.self_template_params(ctx).into_iter()
        }).collect()
    }

    /// Get only the set of template parameters that this item uses. This is a
    /// subset of `all_template_params` and does not necessarily contain any of
    /// `self_template_params`.
    fn used_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>
    where
        Self: AsRef<ItemId>,
    {
        assert!(
            ctx.in_codegen_phase(),
            "template parameter usage is not computed until codegen"
        );

        let id = *self.as_ref();
        ctx.resolve_item(id).all_template_params(ctx)
                    .into_iter()
                    .filter(|p| ctx.uses_template_parameter(id, *p))
                    .collect()
    }
}

/// A trait for things which may or may not be a named template type parameter.
pub trait AsTemplateParam {
    /// Any extra information the implementor might need to make this decision.
    type Extra;

    /// Convert this thing to the item id of a named template type parameter.
    fn as_template_param(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> Option<TypeId>;

    /// Is this a named template type parameter?
    fn is_template_param(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> bool {
        self.as_template_param(ctx, extra).is_some()
    }
}

/// A concrete instantiation of a generic template.
#[derive(Clone, Debug)]
pub struct TemplateInstantiation {
    /// The template definition which this is instantiating.
    definition: TypeId,
    /// The concrete template arguments, which will be substituted in the
    /// definition for the generic template parameters.
    args: Vec<TypeId>,
}

impl TemplateInstantiation {
    /// Construct a new template instantiation from the given parts.
    pub fn new<I>(definition: TypeId, args: I) -> TemplateInstantiation
    where
        I: IntoIterator<Item = TypeId>,
    {
        TemplateInstantiation {
            definition,
            args: args.into_iter().collect(),
        }
    }

    /// Get the template definition for this instantiation.
    pub fn template_definition(&self) -> TypeId {
        self.definition
    }

    /// Get the concrete template arguments used in this instantiation.
    pub fn template_arguments(&self) -> &[TypeId] {
        &self.args[..]
    }

    /// Parse a `TemplateInstantiation` from a clang `Type`.
    pub fn from_ty(
        ty: &clang::Type,
        ctx: &mut BindgenContext,
    ) -> Option<TemplateInstantiation> {
        use clang_sys::*;

        let template_args = ty.template_args()
            .map_or(vec![], |args| {
                match ty.canonical_type().template_args() {
                    Some(canonical_args) => {
                        let arg_count = args.len();
                        args.chain(canonical_args.skip(arg_count))
                            .filter(|t| t.kind() != CXType_Invalid)
                            .map(|t| {
                                Item::from_ty_or_ref(t, t.declaration(), None, ctx)
                            }).collect()
                    }
                    None => {
                        args.filter(|t| t.kind() != CXType_Invalid)
                            .map(|t| {
                                Item::from_ty_or_ref(t, t.declaration(), None, ctx)
                            }).collect()
                    }
                }
            });

        let declaration = ty.declaration();
        let definition =
            if declaration.kind() == CXCursor_TypeAliasTemplateDecl {
                Some(declaration)
            } else {
                declaration.specialized().or_else(|| {
                    let mut template_ref = None;
                    ty.declaration().visit(|child| {
                    if child.kind() == CXCursor_TemplateRef {
                        template_ref = Some(child);
                        return CXVisit_Break;
                    }

                    // Instantiations of template aliases might have the
                    // TemplateRef to the template alias definition arbitrarily
                    // deep, so we need to recurse here and not only visit
                    // direct children.
                    CXChildVisit_Recurse
                });

                    template_ref.and_then(|cur| cur.referenced())
                })
            };

        let definition = match definition {
            Some(def) => def,
            None => {
                if !ty.declaration().is_builtin() {
                    warn!(
                        "Could not find template definition for template \
                           instantiation"
                    );
                }
                return None;
            }
        };

        let template_definition =
            Item::from_ty_or_ref(definition.cur_type(), definition, None, ctx);

        Some(TemplateInstantiation::new(
            template_definition,
            template_args,
        ))
    }
}

impl IsOpaque for TemplateInstantiation {
    type Extra = Item;

    /// Is this an opaque template instantiation?
    fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool {
        if self.template_definition().is_opaque(ctx, &()) {
            return true;
        }

        // TODO(#774): This doesn't properly handle opaque instantiations where
        // an argument is itself an instantiation because `canonical_name` does
        // not insert the template arguments into the name, ie it for nested
        // template arguments it creates "Foo" instead of "Foo<int>". The fully
        // correct fix is to make `canonical_{name,path}` include template
        // arguments properly.

        let mut path = item.canonical_path(ctx);
        let args: Vec<_> = self.template_arguments()
            .iter()
            .map(|arg| {
                let arg_path = arg.canonical_path(ctx);
                arg_path[1..].join("::")
            })
            .collect();
        {
            let last = path.last_mut().unwrap();
            last.push('<');
            last.push_str(&args.join(", "));
            last.push('>');
        }

        ctx.opaque_by_name(&path)
    }
}

impl Trace for TemplateInstantiation {
    type Extra = ();

    fn trace<T>(&self, _ctx: &BindgenContext, tracer: &mut T, _: &())
    where
        T: Tracer,
    {
        tracer.visit_kind(self.definition.into(), EdgeKind::TemplateDeclaration);
        for arg in self.template_arguments() {
            tracer.visit_kind(arg.into(), EdgeKind::TemplateArgument);
        }
    }
}
<|endoftext|>


<commit_before>
pub fn median_of(slice: &[f64]) -> f64 {
    let n = slice.len();
    let mut copy = vec!(0f64; n);
    copy.copy_from_slice(&slice);
    copy.sort_by(|a,b| a.partial_cmp(b).unwrap());
    let middle: usize = n / 2;

    let result = if n % 2 == 1 {
        slice[middle]
    } else {
        (slice[middle] + slice[middle - 1])/2.0
    };

    result.clone()
}

#[cfg(test)]
pub mod tests {
    const EPSILON: f64 = 0.00001;
    use super::*;

    #[test]
    fn median_of_odd_length_vector() {
        let data: Vec<f64> = vec!(1.0, 2.0, 3.0);

        let median = median_of(&data);

        assert!((median - 2.0).abs() < EPSILON);
    }

    #[test]
    fn median_of_even_length_vector() {
        let data: Vec<f64> = vec!(1.0, 2.0, 3.0, 4.0);

        let median = median_of(&data);

        assert_eq!(median, 2.5);
        assert!((median - 2.5).abs() < EPSILON);
    }
}
<commit_msg>Create a groups function<commit_after>
pub fn median_of(slice: &[f64]) -> f64 {
    let n = slice.len();
    let mut copy = vec!(0f64; n);
    copy.copy_from_slice(&slice);
    copy.sort_by(|a,b| a.partial_cmp(b).unwrap());
    let middle: usize = n / 2;

    let result = if n % 2 == 1 {
        slice[middle]
    } else {
        (slice[middle] + slice[middle - 1])/2.0
    };

    result.clone()
}

pub fn groups(slice: Vec<f64>, group_size: usize) -> Vec<Vec<f64>> {
    let mut groups: Vec<Vec<f64>> = vec!();

    for end_index in group_size .. slice.len() + 1 {
        let mut group: Vec<f64> = vec!();
        for index in (end_index - group_size) .. end_index {
            group.push(slice[index])
        }
        groups.push(group)
    }

    groups
}

#[cfg(test)]
pub mod tests {
    const EPSILON: f64 = 0.00001;
    use super::*;

    #[test]
    fn median_of_odd_length_vector() {
        let data: Vec<f64> = vec!(1.0, 2.0, 3.0);

        let median = median_of(&data);

        assert!((median - 2.0).abs() < EPSILON);
    }

    #[test]
    fn median_of_even_length_vector() {
        let data: Vec<f64> = vec!(1.0, 2.0, 3.0, 4.0);

        let median = median_of(&data);

        assert_eq!(median, 2.5);
        assert!((median - 2.5).abs() < EPSILON);
    }

    #[test]
    fn groups_of_2_for_a_vector() {
        let data: Vec<f64> = vec!(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);

        let gs = groups(data, 2);

        assert_eq!(vec![
            vec!(1.0, 2.0),
            vec!(2.0, 3.0),
            vec!(3.0, 4.0),
            vec!(4.0, 5.0),
            vec!(5.0, 6.0)], gs);
    }

    #[test]
    fn groups_of_3_for_a_vector() {
        let data: Vec<f64> = vec!(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);

        let gs = groups(data, 3);

        assert_eq!(vec![
            vec!(1.0, 2.0, 3.0),
            vec!(2.0, 3.0, 4.0),
            vec!(3.0, 4.0, 5.0),
            vec!(4.0, 5.0, 6.0)], gs);
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Read;

use jeebie::utils::combine_as_u16;

/// A struct representing data contained in a gameboy cartridge (a.k.a. ROM).
/// Each Cartridge has an header with metadata (name, available hw on cart like rumble, ram, etc.)
/// Data contained in a cartridge is exposed as a Vec<u8> but should be accessed via the MMU.
#[derive(Debug)]
pub struct Cartridge {
    pub size: usize,
    pub name: String,
    pub data: Vec<u8>,
}

impl Cartridge {
    /// Creates a Cartridge by loading the file at the specified path.
    pub fn new_with_path(path: &str) -> Cartridge {
        Cartridge::new_with_vec(Cartridge::load_rom_file(path))
    }

    /// Creates a new Cartridge struct from a vector buffer.
    pub fn new_with_vec(data: Vec<u8>) -> Cartridge {
        let name_data : Vec<u8> = (&data[0x134..0x143]).to_vec();

        // read name data as ASCII string
        let name : String = name_data.into_iter()
            .map(| c | { c as char })
            .collect();

        let cgb_flag = data[0x143];

        let licensee_code_data : Vec<u8> = (&data[0x144..0x145]).to_vec();

        // read licensee code as ASCII string
        let name : String = licensee_code_data.into_iter()
            .map(| c | { c as char })
            .collect();

        let sgb_flag = data[0x146];

        let mbc_type = data[0x147];
        let rom_size = data[0x148];
        let ram_size = data[0x149];

        let dest_code = data[0x14A];
        let lic_code = data[0x14B];
        let version = data[0x14C];

        // only header_checksum is verified in real hardware
        let header_checksum = data[0x14D];
        let checksum = combine_as_u16(data[0x14E], data[0x14F]);

        // TODO: process the read data and save it in the cart struct
        Cartridge {
            size: data.len(),
            name: name,
            data: data,
        }
    }

    /// Loads binary data from a file into a vector buffer.
    fn load_rom_file(path: &str) -> Vec<u8> {
        let mut buf: Vec<u8> = vec![];

        if let Ok(mut file) = File::open(path) {
            match file.read_to_end(&mut buf) {
                Ok(_) => {},
                Err(e) => println!("{:?}", e),
            }
        }
        buf
    }
}
<commit_msg>Added error handling when loading cartridge<commit_after>use std::fs::File;
use std::io::{Read, Error};

use jeebie::utils::combine_as_u16;

/// A struct representing data contained in a gameboy cartridge (a.k.a. ROM).
/// Each Cartridge has an header with metadata (name, available hw on cart like rumble, ram, etc.)
/// Data contained in a cartridge is exposed as a Vec<u8> but should be accessed via the MMU.
#[derive(Debug)]
pub struct Cartridge {
    pub size: usize,
    pub name: String,
    pub licensee: String,
    pub data: Vec<u8>,
}

impl Cartridge {
    /// Creates a Cartridge by loading the file at the specified path.
    pub fn new_with_path(path: &str) -> Result<Cartridge, Error> {
        let data = try!(Cartridge::load_rom_file(path));
        let cart = Cartridge::new_with_vec(data);
        Ok(cart)
    }

    /// Creates a new Cartridge struct from a vector buffer.
    pub fn new_with_vec(data: Vec<u8>) -> Cartridge {
        let name_data : Vec<u8> = (&data[0x134..0x143]).to_vec();

        // read name data as ASCII string
        let name : String = name_data.into_iter()
            .map(| c | { c as char })
            .collect();

        let cgb_flag = data[0x143];

        let licensee_code_data : Vec<u8> = (&data[0x144..0x145]).to_vec();

        // read licensee code as ASCII string
        let licensee : String = licensee_code_data.into_iter()
            .map(| c | { c as char })
            .collect();

        let sgb_flag = data[0x146];

        let mbc_type = data[0x147];
        let rom_size = data[0x148];
        let ram_size = data[0x149];

        let dest_code = data[0x14A];
        let lic_code = data[0x14B];
        let version = data[0x14C];

        // only header_checksum is verified in real hardware
        let header_checksum = data[0x14D];
        let checksum = combine_as_u16(data[0x14E], data[0x14F]);

        // TODO: process the read data and save it in the cart struct
        Cartridge {
            size: data.len(),
            name: name,
            licensee: licensee,
            data: data,
        }
    }

    /// Loads binary data from a file into a vector buffer.
    fn load_rom_file(path: &str) -> Result<Vec<u8>, Error> {
        let mut buf: Vec<u8> = vec![];
        let mut file = try!(File::open(path));
        try!(file.read_to_end(&mut buf));
        Ok(buf)
    }
}
<|endoftext|>


<commit_before>use query::DocResult;
use std::str;

//#[derive(PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq)]
pub enum SegmentType {
    // BuildState is really simple state tracker to prevent misuse of api
    ObjectKey,
    Array,
    Word,
    DocSeq,
    ArrayPath,
}

#[derive(Debug, Clone)]
pub struct Segment {
    type_: SegmentType,
    offset: usize,
}

#[derive(Debug, Clone)]
pub struct KeyBuilder {
    pub array_depth: usize,
    pub segments: Vec<Segment>,
    fullkey: String,
}

impl KeyBuilder {
    pub fn new() -> KeyBuilder {
        let mut kb = KeyBuilder{
            array_depth: 0,
             // Magic reserve numbers that are completely arbitrary
            segments: Vec::with_capacity(10),
            fullkey: String::with_capacity(100),
        };
        // First char is keyspace identifier. W means Word keyspace
        kb.fullkey.push('W');
        return kb;
    }

    // NOTE vmx 2016-10-28: This one is just a port of the C++ prototype, but not yet needed here
    //fn segments_count(&self) -> usize {
    //    self.segments.len()
    //}

    pub fn key(&self) -> String {
        self.fullkey.clone()
    }

    pub fn push_object_key(&mut self, key: String) {
        debug_assert!(self.segments.len() == 0 ||
                      self.segments.last().unwrap().type_ == SegmentType::ObjectKey ||
                      self.segments.last().unwrap().type_ == SegmentType::Array);
        self.segments.push(Segment{ type_: SegmentType::ObjectKey, offset: self.fullkey.len() });
        self.fullkey.push('.');
        for cc in key.chars() {
            // Escape chars that conflict with delimiters
            if "\\$.!#".contains(cc) {
                self.fullkey.push('\\');
            }
            self.fullkey.push(cc);
        }
    }

    pub fn push_array(&mut self) {
        debug_assert!(self.segments.len() == 0 ||
                      self.segments.last().unwrap().type_ == SegmentType::ObjectKey ||
                      self.segments.last().unwrap().type_ == SegmentType::Array);
        self.segments.push(Segment{ type_: SegmentType::Array, offset: self.fullkey.len() });
        self.fullkey.push('$');
        self.array_depth += 1;
    }

    pub fn push_word(&mut self, stemmed_word: &str) {
        debug_assert!(self.segments.len() > 0);
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::ObjectKey ||
                      self.segments.last().unwrap().type_ == SegmentType::Array);
        self.segments.push(Segment{ type_: SegmentType::Word, offset: self.fullkey.len() });
        self.fullkey.push('!');
        self.fullkey += stemmed_word;
    }

    pub fn push_doc_seq(&mut self, seq: u64) {
        debug_assert!(self.segments.len() > 0);
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::Word);
        self.segments.push(Segment{ type_: SegmentType::DocSeq, offset: self.fullkey.len() });
        self.fullkey.push('#');
        self.fullkey.push_str(seq.to_string().as_str());
    }

    pub fn push_array_path(&mut self, path: &Vec<u64>) {
        debug_assert!(self.segments.len() > 0);
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::DocSeq);
        self.segments.push(Segment{ type_: SegmentType::ArrayPath, offset: self.fullkey.len() });
        if path.is_empty() {
            self.fullkey.push(',');
        }
        for i in path {
            self.fullkey.push(',');
            self.fullkey.push_str(i.to_string().as_str());
        }
    }

    pub fn pop_object_key(&mut self) {
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::ObjectKey);
        self.fullkey.truncate(self.segments.last().unwrap().offset);
        self.segments.pop();
    }

    pub fn pop_array(&mut self) {
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::Array);
        self.fullkey.truncate(self.segments.last().unwrap().offset);
        self.array_depth -= 1;
        self.segments.pop();
    }

    pub fn pop_word(&mut self) {
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::Word);
        self.fullkey.truncate(self.segments.last().unwrap().offset);
        self.segments.pop();
    }

    pub fn pop_doc_seq(&mut self) {
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::DocSeq);
        self.fullkey.truncate(self.segments.last().unwrap().offset);
        self.segments.pop();
    }

    pub fn pop_array_path(&mut self) {
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::ArrayPath);
        self.fullkey.truncate(self.segments.last().unwrap().offset);
        self.segments.pop();
    }

    pub fn last_pushed_segment_type(&self) -> Option<SegmentType> {
        self.segments.last().and_then(|segment| Some(segment.type_.clone()))
    }

    /* splits key into key path parts parsed seq strs
        ex "W.foo$.bar$.baz!word#123,0,0" -> ("W.foo$.bar$.bar!word", 123, "0,0") */
    fn split_keypath_seq_arraypath_from_key(str: &str) -> (&str, &str, &str) {
        let n = str.rfind("#").unwrap();
        assert!(n != 0);
        assert!(n != str.len() - 1);
        let seq_array_path_str = &str[(n + 1)..];
        let m = seq_array_path_str.find(",").unwrap();

        (&str[..n], &seq_array_path_str[..m], &seq_array_path_str[m + 1..])
    }

    /* parses a seq and array path portion (ex "123,0,0,10) of a key into a doc result */
    pub fn parse_doc_result_from_key(str: &str) -> DocResult {

        let mut dr = DocResult::new();
        let (_path_str, seq_str, array_path_str) = KeyBuilder::split_keypath_seq_arraypath_from_key(&str);
        dr.seq = seq_str.parse().unwrap();
        if !array_path_str.is_empty() {
            for numstr in array_path_str.split(",") {
                dr.array_path.push(numstr.parse().unwrap());
            }
        }
        dr
    }

    pub fn compare_keys(akey: &str, bkey: &str) -> i32 {
        use std::cmp::Ordering;
        assert!(akey.starts_with('W'));
        assert!(bkey.starts_with('W'));
        let (apath_str, aseq_str, aarray_path_str) = KeyBuilder::split_keypath_seq_arraypath_from_key(&akey);
        let (bpath_str, bseq_str, barray_path_str) = KeyBuilder::split_keypath_seq_arraypath_from_key(&bkey);

        match apath_str[1..].cmp(&bpath_str[1..]) {
            Ordering::Less    =>  -1,
            Ordering::Greater =>   1,
            Ordering::Equal   => {
                let aseq: u64 = aseq_str.parse().unwrap();
                let bseq: u64 = bseq_str.parse().unwrap();;
                if aseq < bseq {
                    -1
                } else if aseq > bseq {
                    1
                } else {
                    match aarray_path_str.cmp(barray_path_str) {
                        Ordering::Less    => -1,
                        Ordering::Greater =>  1,
                        Ordering::Equal   =>  0,
                    }
                }
            },
        }
    }

}

#[cfg(test)]
mod tests {
    use super::{KeyBuilder, SegmentType};
    use query::DocResult;

    #[test]
    fn test_new_key_builder() {
        let kb = KeyBuilder::new();
        assert_eq!(kb.key(), "W", "Initial value is set");
    }

    #[test]
    fn test_segments_push() {
        let mut kb = KeyBuilder::new();
        assert_eq!(kb.segments.len(), 0, "No segments so far");
        assert_eq!(kb.key(), "W", "Key for segments is correct");

        kb.push_object_key("first".to_string());
        assert_eq!(kb.segments.len(), 1, "One segment");
        assert_eq!(kb.key(), "W.first", "Key for one segments is correct");

        kb.push_object_key("second".to_string());
        assert_eq!(kb.segments.len(), 2, "Two segments");
        assert_eq!(kb.key(), "W.first.second", "Key for two segments is correct");

        kb.push_array();
        assert_eq!(kb.segments.len(), 3, "Three segments ");
        assert_eq!(kb.key(), "W.first.second$", "Key for three segments is correct");

        kb.push_word("astemmedword");
        assert_eq!(kb.segments.len(), 4, "Four segments");
        assert_eq!(kb.key(), "W.first.second$!astemmedword", "Key for four segments is correct");

        kb.push_doc_seq(123);
        assert_eq!(kb.segments.len(), 5, "Five segments");
        assert_eq!(kb.key(), "W.first.second$!astemmedword#123",
                   "Key for five segments is correct");
    }

    #[test]
    #[should_panic(expected = "assertion failed: self.segments.len() > 0")]
    fn test_segments_push_doc_seq_panic() {
        let mut kb = KeyBuilder::new();
        kb.push_doc_seq(456);
    }

        #[test]
    #[should_panic(expected = "assertion failed: self.segments.len() > 0")]
    fn test_segments_push_word_panic() {
        let mut kb = KeyBuilder::new();
        kb.push_word("astemmedword");
    }

    #[test]
    fn test_segments_pop() {
        let mut kb = KeyBuilder::new();
        kb.push_object_key("first".to_string());
        kb.push_object_key("second".to_string());
        kb.push_array();
        kb.push_word("astemmedword");
        kb.push_doc_seq(123);
        kb.push_array_path(&vec![0]);

        assert_eq!(kb.segments.len(), 6, "six segments");
        assert_eq!(kb.key(), "W.first.second$!astemmedword#123,0",
                   "Key for six segments is correct");

        kb.pop_array_path();
        assert_eq!(kb.segments.len(), 5, "Five segments");
        assert_eq!(kb.key(), "W.first.second$!astemmedword#123",
                   "Key for five segments is correct");

        kb.pop_doc_seq();
        assert_eq!(kb.segments.len(), 4, "Four segments");
        assert_eq!(kb.key(), "W.first.second$!astemmedword", "Key for four segments is correct");

        kb.pop_word();
        assert_eq!(kb.segments.len(), 3, "Three segments ");
        assert_eq!(kb.key(), "W.first.second$", "Key for three segments is correct");

        kb.pop_array();
        assert_eq!(kb.segments.len(), 2, "Two segments");
        assert_eq!(kb.key(), "W.first.second", "Key for two segments is correct");

        kb.pop_object_key();
        assert_eq!(kb.segments.len(), 1, "One segment");
        assert_eq!(kb.key(), "W.first", "Key for one segments is correct");

        kb.pop_object_key();
        assert_eq!(kb.segments.len(), 0, "No segments so far");
        assert_eq!(kb.key(), "W", "Key for segments is correct");
    }

    #[test]
    fn test_last_pushed_segment_type() {
        let mut kb = KeyBuilder::new();
        assert_eq!(kb.last_pushed_segment_type(), None, "No segments");

        kb.push_object_key("first".to_string());
        assert_eq!(kb.last_pushed_segment_type(), Some(SegmentType::ObjectKey),
                   "Last segment is an object key");

        kb.push_object_key("second".to_string());
        assert_eq!(kb.last_pushed_segment_type(), Some(SegmentType::ObjectKey),
                   "Last segment is an object key");

        kb.push_array();
        assert_eq!(kb.last_pushed_segment_type(), Some(SegmentType::Array),
                   "Last segment is an array");

        kb.push_word("astemmedword");
        assert_eq!(kb.last_pushed_segment_type(), Some(SegmentType::Word),
                   "Last segment is a word");

        kb.push_doc_seq(123);
        assert_eq!(kb.last_pushed_segment_type(), Some(SegmentType::DocSeq),
                   "Last segment is a doc sequence");
    }

    #[test]
    fn test_doc_result_parse() {
        let key = "W.foo$.bar$!word#123,1,0".to_string();
        let (keypathstr, seqstr, arraypathstr) = KeyBuilder::split_keypath_seq_arraypath_from_key(&key);
        assert_eq!(keypathstr, "W.foo$.bar$!word");
        assert_eq!(seqstr, "123");
        assert_eq!(arraypathstr, "1,0");

        // make sure escaped commas and # in key path don't cause problems
        let key1 = "W.foo\\#$.bar\\,$!word#123,2,0".to_string();
        let (keypathstr1, seqstr1, arraypathstr1) = KeyBuilder::split_keypath_seq_arraypath_from_key(&key1);
        assert_eq!(keypathstr1, "W.foo\\#$.bar\\,$!word");
        assert_eq!(seqstr1, "123");
        assert_eq!(arraypathstr1, "2,0");

        let mut dr = DocResult::new();
        dr.seq = 123;
        dr.array_path = vec![1,0];

        assert!(dr == KeyBuilder::parse_doc_result_from_key(&key));
    }
}
<commit_msg>fixed comment<commit_after>use query::DocResult;
use std::str;

//#[derive(PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq)]
pub enum SegmentType {
    // BuildState is really simple state tracker to prevent misuse of api
    ObjectKey,
    Array,
    Word,
    DocSeq,
    ArrayPath,
}

#[derive(Debug, Clone)]
pub struct Segment {
    type_: SegmentType,
    offset: usize,
}

#[derive(Debug, Clone)]
pub struct KeyBuilder {
    pub array_depth: usize,
    pub segments: Vec<Segment>,
    fullkey: String,
}

impl KeyBuilder {
    pub fn new() -> KeyBuilder {
        let mut kb = KeyBuilder{
            array_depth: 0,
             // Magic reserve numbers that are completely arbitrary
            segments: Vec::with_capacity(10),
            fullkey: String::with_capacity(100),
        };
        // First char is keyspace identifier. W means Word keyspace
        kb.fullkey.push('W');
        return kb;
    }

    // NOTE vmx 2016-10-28: This one is just a port of the C++ prototype, but not yet needed here
    //fn segments_count(&self) -> usize {
    //    self.segments.len()
    //}

    pub fn key(&self) -> String {
        self.fullkey.clone()
    }

    pub fn push_object_key(&mut self, key: String) {
        debug_assert!(self.segments.len() == 0 ||
                      self.segments.last().unwrap().type_ == SegmentType::ObjectKey ||
                      self.segments.last().unwrap().type_ == SegmentType::Array);
        self.segments.push(Segment{ type_: SegmentType::ObjectKey, offset: self.fullkey.len() });
        self.fullkey.push('.');
        for cc in key.chars() {
            // Escape chars that conflict with delimiters
            if "\\$.!#".contains(cc) {
                self.fullkey.push('\\');
            }
            self.fullkey.push(cc);
        }
    }

    pub fn push_array(&mut self) {
        debug_assert!(self.segments.len() == 0 ||
                      self.segments.last().unwrap().type_ == SegmentType::ObjectKey ||
                      self.segments.last().unwrap().type_ == SegmentType::Array);
        self.segments.push(Segment{ type_: SegmentType::Array, offset: self.fullkey.len() });
        self.fullkey.push('$');
        self.array_depth += 1;
    }

    pub fn push_word(&mut self, stemmed_word: &str) {
        debug_assert!(self.segments.len() > 0);
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::ObjectKey ||
                      self.segments.last().unwrap().type_ == SegmentType::Array);
        self.segments.push(Segment{ type_: SegmentType::Word, offset: self.fullkey.len() });
        self.fullkey.push('!');
        self.fullkey += stemmed_word;
    }

    pub fn push_doc_seq(&mut self, seq: u64) {
        debug_assert!(self.segments.len() > 0);
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::Word);
        self.segments.push(Segment{ type_: SegmentType::DocSeq, offset: self.fullkey.len() });
        self.fullkey.push('#');
        self.fullkey.push_str(seq.to_string().as_str());
    }

    pub fn push_array_path(&mut self, path: &Vec<u64>) {
        debug_assert!(self.segments.len() > 0);
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::DocSeq);
        self.segments.push(Segment{ type_: SegmentType::ArrayPath, offset: self.fullkey.len() });
        if path.is_empty() {
            self.fullkey.push(',');
        }
        for i in path {
            self.fullkey.push(',');
            self.fullkey.push_str(i.to_string().as_str());
        }
    }

    pub fn pop_object_key(&mut self) {
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::ObjectKey);
        self.fullkey.truncate(self.segments.last().unwrap().offset);
        self.segments.pop();
    }

    pub fn pop_array(&mut self) {
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::Array);
        self.fullkey.truncate(self.segments.last().unwrap().offset);
        self.array_depth -= 1;
        self.segments.pop();
    }

    pub fn pop_word(&mut self) {
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::Word);
        self.fullkey.truncate(self.segments.last().unwrap().offset);
        self.segments.pop();
    }

    pub fn pop_doc_seq(&mut self) {
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::DocSeq);
        self.fullkey.truncate(self.segments.last().unwrap().offset);
        self.segments.pop();
    }

    pub fn pop_array_path(&mut self) {
        debug_assert!(self.segments.last().unwrap().type_ == SegmentType::ArrayPath);
        self.fullkey.truncate(self.segments.last().unwrap().offset);
        self.segments.pop();
    }

    pub fn last_pushed_segment_type(&self) -> Option<SegmentType> {
        self.segments.last().and_then(|segment| Some(segment.type_.clone()))
    }

    /* splits key into key path, seq and array path
        ex "W.foo$.bar$.baz!word#123,0,0" -> ("W.foo$.bar$.bar!word", "123", "0,0") */
    fn split_keypath_seq_arraypath_from_key(str: &str) -> (&str, &str, &str) {
        let n = str.rfind("#").unwrap();
        assert!(n != 0);
        assert!(n != str.len() - 1);
        let seq_array_path_str = &str[(n + 1)..];
        let m = seq_array_path_str.find(",").unwrap();

        (&str[..n], &seq_array_path_str[..m], &seq_array_path_str[m + 1..])
    }

    /* parses a seq and array path portion (ex "123,0,0,10) of a key into a doc result */
    pub fn parse_doc_result_from_key(str: &str) -> DocResult {

        let mut dr = DocResult::new();
        let (_path_str, seq_str, array_path_str) = KeyBuilder::split_keypath_seq_arraypath_from_key(&str);
        dr.seq = seq_str.parse().unwrap();
        if !array_path_str.is_empty() {
            for numstr in array_path_str.split(",") {
                dr.array_path.push(numstr.parse().unwrap());
            }
        }
        dr
    }

    pub fn compare_keys(akey: &str, bkey: &str) -> i32 {
        use std::cmp::Ordering;
        assert!(akey.starts_with('W'));
        assert!(bkey.starts_with('W'));
        let (apath_str, aseq_str, aarray_path_str) = KeyBuilder::split_keypath_seq_arraypath_from_key(&akey);
        let (bpath_str, bseq_str, barray_path_str) = KeyBuilder::split_keypath_seq_arraypath_from_key(&bkey);

        match apath_str[1..].cmp(&bpath_str[1..]) {
            Ordering::Less    =>  -1,
            Ordering::Greater =>   1,
            Ordering::Equal   => {
                let aseq: u64 = aseq_str.parse().unwrap();
                let bseq: u64 = bseq_str.parse().unwrap();;
                if aseq < bseq {
                    -1
                } else if aseq > bseq {
                    1
                } else {
                    match aarray_path_str.cmp(barray_path_str) {
                        Ordering::Less    => -1,
                        Ordering::Greater =>  1,
                        Ordering::Equal   =>  0,
                    }
                }
            },
        }
    }

}

#[cfg(test)]
mod tests {
    use super::{KeyBuilder, SegmentType};
    use query::DocResult;

    #[test]
    fn test_new_key_builder() {
        let kb = KeyBuilder::new();
        assert_eq!(kb.key(), "W", "Initial value is set");
    }

    #[test]
    fn test_segments_push() {
        let mut kb = KeyBuilder::new();
        assert_eq!(kb.segments.len(), 0, "No segments so far");
        assert_eq!(kb.key(), "W", "Key for segments is correct");

        kb.push_object_key("first".to_string());
        assert_eq!(kb.segments.len(), 1, "One segment");
        assert_eq!(kb.key(), "W.first", "Key for one segments is correct");

        kb.push_object_key("second".to_string());
        assert_eq!(kb.segments.len(), 2, "Two segments");
        assert_eq!(kb.key(), "W.first.second", "Key for two segments is correct");

        kb.push_array();
        assert_eq!(kb.segments.len(), 3, "Three segments ");
        assert_eq!(kb.key(), "W.first.second$", "Key for three segments is correct");

        kb.push_word("astemmedword");
        assert_eq!(kb.segments.len(), 4, "Four segments");
        assert_eq!(kb.key(), "W.first.second$!astemmedword", "Key for four segments is correct");

        kb.push_doc_seq(123);
        assert_eq!(kb.segments.len(), 5, "Five segments");
        assert_eq!(kb.key(), "W.first.second$!astemmedword#123",
                   "Key for five segments is correct");
    }

    #[test]
    #[should_panic(expected = "assertion failed: self.segments.len() > 0")]
    fn test_segments_push_doc_seq_panic() {
        let mut kb = KeyBuilder::new();
        kb.push_doc_seq(456);
    }

        #[test]
    #[should_panic(expected = "assertion failed: self.segments.len() > 0")]
    fn test_segments_push_word_panic() {
        let mut kb = KeyBuilder::new();
        kb.push_word("astemmedword");
    }

    #[test]
    fn test_segments_pop() {
        let mut kb = KeyBuilder::new();
        kb.push_object_key("first".to_string());
        kb.push_object_key("second".to_string());
        kb.push_array();
        kb.push_word("astemmedword");
        kb.push_doc_seq(123);
        kb.push_array_path(&vec![0]);

        assert_eq!(kb.segments.len(), 6, "six segments");
        assert_eq!(kb.key(), "W.first.second$!astemmedword#123,0",
                   "Key for six segments is correct");

        kb.pop_array_path();
        assert_eq!(kb.segments.len(), 5, "Five segments");
        assert_eq!(kb.key(), "W.first.second$!astemmedword#123",
                   "Key for five segments is correct");

        kb.pop_doc_seq();
        assert_eq!(kb.segments.len(), 4, "Four segments");
        assert_eq!(kb.key(), "W.first.second$!astemmedword", "Key for four segments is correct");

        kb.pop_word();
        assert_eq!(kb.segments.len(), 3, "Three segments ");
        assert_eq!(kb.key(), "W.first.second$", "Key for three segments is correct");

        kb.pop_array();
        assert_eq!(kb.segments.len(), 2, "Two segments");
        assert_eq!(kb.key(), "W.first.second", "Key for two segments is correct");

        kb.pop_object_key();
        assert_eq!(kb.segments.len(), 1, "One segment");
        assert_eq!(kb.key(), "W.first", "Key for one segments is correct");

        kb.pop_object_key();
        assert_eq!(kb.segments.len(), 0, "No segments so far");
        assert_eq!(kb.key(), "W", "Key for segments is correct");
    }

    #[test]
    fn test_last_pushed_segment_type() {
        let mut kb = KeyBuilder::new();
        assert_eq!(kb.last_pushed_segment_type(), None, "No segments");

        kb.push_object_key("first".to_string());
        assert_eq!(kb.last_pushed_segment_type(), Some(SegmentType::ObjectKey),
                   "Last segment is an object key");

        kb.push_object_key("second".to_string());
        assert_eq!(kb.last_pushed_segment_type(), Some(SegmentType::ObjectKey),
                   "Last segment is an object key");

        kb.push_array();
        assert_eq!(kb.last_pushed_segment_type(), Some(SegmentType::Array),
                   "Last segment is an array");

        kb.push_word("astemmedword");
        assert_eq!(kb.last_pushed_segment_type(), Some(SegmentType::Word),
                   "Last segment is a word");

        kb.push_doc_seq(123);
        assert_eq!(kb.last_pushed_segment_type(), Some(SegmentType::DocSeq),
                   "Last segment is a doc sequence");
    }

    #[test]
    fn test_doc_result_parse() {
        let key = "W.foo$.bar$!word#123,1,0".to_string();
        let (keypathstr, seqstr, arraypathstr) = KeyBuilder::split_keypath_seq_arraypath_from_key(&key);
        assert_eq!(keypathstr, "W.foo$.bar$!word");
        assert_eq!(seqstr, "123");
        assert_eq!(arraypathstr, "1,0");

        // make sure escaped commas and # in key path don't cause problems
        let key1 = "W.foo\\#$.bar\\,$!word#123,2,0".to_string();
        let (keypathstr1, seqstr1, arraypathstr1) = KeyBuilder::split_keypath_seq_arraypath_from_key(&key1);
        assert_eq!(keypathstr1, "W.foo\\#$.bar\\,$!word");
        assert_eq!(seqstr1, "123");
        assert_eq!(arraypathstr1, "2,0");

        let mut dr = DocResult::new();
        dr.seq = 123;
        dr.array_path = vec![1,0];

        assert!(dr == KeyBuilder::parse_doc_result_from_key(&key));
    }
}
<|endoftext|>


<commit_before>//! Main module to handle the layout.
//! This is where the i3-specific code is.

use std::sync::{Mutex, MutexGuard, TryLockError};
use std::ptr;

use super::container::{Container, Handle, ContainerType};
use super::node::{Node};
use super::super::rustwlc::handle::{WlcView, WlcOutput};

pub type TreeResult = Result<(), TryLockError<MutexGuard<'static, Tree>>>;

const ERR_BAD_TREE: &'static str = "Layout tree was in an invalid configuration";

pub struct Tree {
    root: Node,
    active_container: *const Node,
}

impl Tree {
    fn get_active_container(&self) -> Option<&Node> {
        if self.active_container.is_null() {
            None
        } else {
            unsafe {
                Some(&*self.active_container)
            }
        }
    }

    fn get_active_output(&self) -> Option<&Node> {
        if let Some(node) = self.get_active_container() {
            node.get_ancestor_of_type(ContainerType::Output)
        } else {
            None
        }
    }

    fn get_current_workspace(&self) -> Option<&mut Node> {
        if let Some(container) = self.get_active_container() {
            //if let Some(child) = container.get_ancestor_of_type(ContainerType::Workspace) {
            //return child.get_children()[0].get_parent()

            //}
            // NOTE hack here, remove commented code above to make this work properly
            let parent = container.get_parent().expect(ERR_BAD_TREE);
            for child in parent.get_children_mut() {
                if child == container {
                    return Some(child);
                }
            }
        }
        return None
    }

    fn get_workspace_by_name(&self, name: &str) -> Option<&Node> {
        for child in self.root.get_children()[0].get_children() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    fn get_workspace_by_name_mut(&mut self, name: &str) -> Option<&mut Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    fn add_output(&mut self, wlc_output: WlcOutput) {
        self.root.new_child(Container::new_output(wlc_output));
    }

    fn add_workspace(&mut self, name: &str) {
        let workspace = Container::new_workspace(name.to_string());
        let mut index = 0;
        if let Some(output) = self.get_active_output() {
            for (cur_index, child) in self.root.get_children().iter().enumerate() {
                if child == output {
                    index = cur_index;
                    break;
                }
            }
        }
        self.root.get_children_mut()[index].new_child(workspace);
    }

    fn add_view(&self, wlc_view: WlcView) {
        if let Some(current_workspace) = self.get_current_workspace() {
            trace!("Adding view {:?} to {:?}", wlc_view, current_workspace);
            current_workspace.new_child(Container::new_view(wlc_view));
        }
    }

    fn remove_view(&self, wlc_view: &WlcView) {
        if let Some(view) = self.root.find_view_by_handle(&wlc_view) {
            let parent = view.get_parent().expect(ERR_BAD_TREE);
            parent.remove_child(view);
        }
    }
}

unsafe impl Send for Tree {}

lazy_static! {
    static ref TREE: Mutex<Tree> = {
        Mutex::new(Tree{
            root: Node::new(Container::new_root()),
            active_container: ptr::null(),
        })
    };
}

pub fn add_output(wlc_output: WlcOutput) -> TreeResult {
    {
        let mut tree = try!(TREE.try_lock());
        tree.add_output(wlc_output);
    }
    try!(add_workspace(&"1"));
    try!(switch_workspace(&"1"));
    Ok(())
}

pub fn add_workspace(name: &str) -> TreeResult {
    trace!("Adding new workspace to root");
    let mut tree = try!(TREE.lock());
    tree.add_workspace(name);
    Ok(())
}

pub fn add_view(wlc_view: WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    tree.add_view(wlc_view);
    Ok(())
}

pub fn remove_view(wlc_view: &WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    tree.remove_view(wlc_view);
    Ok(())
}

pub fn switch_workspace(name: &str) -> TreeResult {
    trace!("Switching to workspace {}", name);
    let mut tree = try!(TREE.lock());
    if let Some(old_workspace) = tree.get_current_workspace() {
        // Make all the views in the original workspace to be invisible
        for view in old_workspace.get_children_mut() {
            trace!("Setting {:?} invisible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(0),
                _ => {},
            }
        }
    }
    let current_workspace: *const Node;
    {
        if let Some(_) = tree.get_workspace_by_name(name) {
            trace!("Found workspace {}", name);
        } else {
            trace!("Adding workspace {}", name);
            try!(add_workspace(name));
        }
        let new_current_workspace = tree.get_workspace_by_name_mut(name).expect(ERR_BAD_TREE);
        for view in new_current_workspace.get_children_mut() {
            trace!("Setting {:?} visible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(1),
                _ => {},
            }
        }
        // Set the first view to be focused, so that the view is updated to this new workspace
        if new_current_workspace.get_children().len() > 0 {
            trace!("Focusing view");
            match new_current_workspace.get_children_mut()[0]
                .get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.focus(),
                _ => {},
            }
        } else {
            WlcView::root().focus();
        }
        current_workspace = new_current_workspace as *const Node;
    }
    tree.active_container = current_workspace;
    Ok(())
}
<commit_msg>add_workspace takes a String, not a &str now<commit_after>//! Main module to handle the layout.
//! This is where the i3-specific code is.

use std::sync::{Mutex, MutexGuard, TryLockError};
use std::ptr;

use super::container::{Container, Handle, ContainerType};
use super::node::{Node};
use super::super::rustwlc::handle::{WlcView, WlcOutput};

pub type TreeResult = Result<(), TryLockError<MutexGuard<'static, Tree>>>;

const ERR_BAD_TREE: &'static str = "Layout tree was in an invalid configuration";

pub struct Tree {
    root: Node,
    active_container: *const Node,
}

impl Tree {
    fn get_active_container(&self) -> Option<&Node> {
        if self.active_container.is_null() {
            None
        } else {
            unsafe {
                Some(&*self.active_container)
            }
        }
    }

    fn get_active_output(&self) -> Option<&Node> {
        if let Some(node) = self.get_active_container() {
            node.get_ancestor_of_type(ContainerType::Output)
        } else {
            None
        }
    }

    fn get_current_workspace(&self) -> Option<&mut Node> {
        if let Some(container) = self.get_active_container() {
            //if let Some(child) = container.get_ancestor_of_type(ContainerType::Workspace) {
            //return child.get_children()[0].get_parent()

            //}
            // NOTE hack here, remove commented code above to make this work properly
            let parent = container.get_parent().expect(ERR_BAD_TREE);
            for child in parent.get_children_mut() {
                if child == container {
                    return Some(child);
                }
            }
        }
        return None
    }

    fn get_workspace_by_name(&self, name: &str) -> Option<&Node> {
        for child in self.root.get_children()[0].get_children() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    fn get_workspace_by_name_mut(&mut self, name: &str) -> Option<&mut Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    fn add_output(&mut self, wlc_output: WlcOutput) {
        self.root.new_child(Container::new_output(wlc_output));
    }

    fn add_workspace(&mut self, name: String) {
        let workspace = Container::new_workspace(name.to_string());
        let mut index = 0;
        if let Some(output) = self.get_active_output() {
            for (cur_index, child) in self.root.get_children().iter().enumerate() {
                if child == output {
                    index = cur_index;
                    break;
                }
            }
        }
        self.root.get_children_mut()[index].new_child(workspace);
    }

    fn add_view(&self, wlc_view: WlcView) {
        if let Some(current_workspace) = self.get_current_workspace() {
            trace!("Adding view {:?} to {:?}", wlc_view, current_workspace);
            current_workspace.new_child(Container::new_view(wlc_view));
        }
    }

    fn remove_view(&self, wlc_view: &WlcView) {
        if let Some(view) = self.root.find_view_by_handle(&wlc_view) {
            let parent = view.get_parent().expect(ERR_BAD_TREE);
            parent.remove_child(view);
        }
    }
}

unsafe impl Send for Tree {}

lazy_static! {
    static ref TREE: Mutex<Tree> = {
        Mutex::new(Tree{
            root: Node::new(Container::new_root()),
            active_container: ptr::null(),
        })
    };
}

pub fn add_output(wlc_output: WlcOutput) -> TreeResult {
    {
        let mut tree = try!(TREE.try_lock());
        tree.add_output(wlc_output);
    }
    try!(add_workspace("1".to_string()));
    try!(switch_workspace(&"1"));
    Ok(())
}

pub fn add_workspace(name: String) -> TreeResult {
    trace!("Adding new workspace to root");
    let mut tree = try!(TREE.lock());
    tree.add_workspace(name);
    Ok(())
}

pub fn add_view(wlc_view: WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    tree.add_view(wlc_view);
    Ok(())
}

pub fn remove_view(wlc_view: &WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    tree.remove_view(wlc_view);
    Ok(())
}

pub fn switch_workspace(name: &str) -> TreeResult {
    trace!("Switching to workspace {}", name);
    let mut tree = try!(TREE.lock());
    if let Some(old_workspace) = tree.get_current_workspace() {
        // Make all the views in the original workspace to be invisible
        for view in old_workspace.get_children_mut() {
            trace!("Setting {:?} invisible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(0),
                _ => {},
            }
        }
    }
    let current_workspace: *const Node;
    {
        if let Some(_) = tree.get_workspace_by_name(name) {
            trace!("Found workspace {}", name);
        } else {
            trace!("Adding workspace {}", name);
            try!(add_workspace(name.to_string()));
        }
        let new_current_workspace = tree.get_workspace_by_name_mut(name).expect(ERR_BAD_TREE);
        for view in new_current_workspace.get_children_mut() {
            trace!("Setting {:?} visible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(1),
                _ => {},
            }
        }
        // Set the first view to be focused, so that the view is updated to this new workspace
        if new_current_workspace.get_children().len() > 0 {
            trace!("Focusing view");
            match new_current_workspace.get_children_mut()[0]
                .get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.focus(),
                _ => {},
            }
        } else {
            WlcView::root().focus();
        }
        current_workspace = new_current_workspace as *const Node;
    }
    tree.active_container = current_workspace;
    Ok(())
}
<|endoftext|>


<commit_before>/**
A macro for declaring lazily evaluated statics.
Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.

Forked from https://github.com/rust-lang-nursery/lazy-static.rs

This version uses atomics instead of `std::sync::Once`, so it works also for `#![no_std]` builds.
It requires a nightly Rust version.

# Syntax
```text
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```
Metadata (such as doc comments) is allowed on each ref.
# Semantic
For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)
On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.
Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.
# Example
Using the macro:

```rust
#![feature(const_fn, core_intrinsics)]

#[macro_use]
extern crate once;
use std::collections::HashMap;
lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}
fn times_two(n: u32) -> u32 { n * 2 }
fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```
# Implementation details
The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access.
**/
#[macro_export]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(MAKE TY, $VIS, $(#[$attr])*, $N);
        impl $crate::__core::ops::Deref for $N {
            type Target = $T;
            fn deref<'a>(&'a self) -> &'a $T {
                #[inline(always)]
                fn __static_ref_initialize() -> $T { $e }

                unsafe {
                    use $crate::__core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

                    #[inline(always)]
                    fn require_sync<T: Sync>(_: &T) { }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        use $crate::__core::cell::UnsafeCell;

                        struct SyncCell(UnsafeCell<Option<$T>>);
                        unsafe impl Sync for SyncCell {}

                        static DATA: SyncCell = SyncCell(UnsafeCell::new(None));
                        static INITIALIZED: AtomicUsize = ATOMIC_USIZE_INIT;

                        if INITIALIZED.load(Ordering::Relaxed) != 2 {
                            // not initialized yet

                            // set state to `initializing`
                            match INITIALIZED.compare_and_swap(0, 1, Ordering::Relaxed) {
                                0 => {
                                    // initialize
                                    *DATA.0.get() = Some(__static_ref_initialize());
                                    // set state to `initialized`
                                    INITIALIZED.store(2, Ordering::Relaxed);
                                },
                                1 => {
                                    // currently initializing in another thread, keep spinning
                                    while INITIALIZED.load(Ordering::Relaxed) != 2 {}
                                },
                                2 => {}, // now it's initialized
                                _ => unreachable!(),
                            }
                        }

                        match *DATA.0.get() {
                            Some(ref x) => x,
                            None => unreachable!(),
                        }
                    }

                    let static_ref = __stability();
                    require_sync(static_ref);
                    static_ref
                }
            }
        }
        lazy_static!($($t)*);
    };
    (MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<commit_msg>Remove unused feature it doc test<commit_after>/**
A macro for declaring lazily evaluated statics.
Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.

Forked from https://github.com/rust-lang-nursery/lazy-static.rs

This version uses atomics instead of `std::sync::Once`, so it works also for `#![no_std]` builds.
It requires a nightly Rust version.

# Syntax
```text
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```
Metadata (such as doc comments) is allowed on each ref.
# Semantic
For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)
On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.
Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.
# Example
Using the macro:

```rust
#![feature(const_fn)]

#[macro_use]
extern crate once;
use std::collections::HashMap;
lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}
fn times_two(n: u32) -> u32 { n * 2 }
fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```
# Implementation details
The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access.
**/
#[macro_export]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(MAKE TY, $VIS, $(#[$attr])*, $N);
        impl $crate::__core::ops::Deref for $N {
            type Target = $T;
            fn deref<'a>(&'a self) -> &'a $T {
                #[inline(always)]
                fn __static_ref_initialize() -> $T { $e }

                unsafe {
                    use $crate::__core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

                    #[inline(always)]
                    fn require_sync<T: Sync>(_: &T) { }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        use $crate::__core::cell::UnsafeCell;

                        struct SyncCell(UnsafeCell<Option<$T>>);
                        unsafe impl Sync for SyncCell {}

                        static DATA: SyncCell = SyncCell(UnsafeCell::new(None));
                        static INITIALIZED: AtomicUsize = ATOMIC_USIZE_INIT;

                        if INITIALIZED.load(Ordering::Relaxed) != 2 {
                            // not initialized yet

                            // set state to `initializing`
                            match INITIALIZED.compare_and_swap(0, 1, Ordering::Relaxed) {
                                0 => {
                                    // initialize
                                    *DATA.0.get() = Some(__static_ref_initialize());
                                    // set state to `initialized`
                                    INITIALIZED.store(2, Ordering::Relaxed);
                                },
                                1 => {
                                    // currently initializing in another thread, keep spinning
                                    while INITIALIZED.load(Ordering::Relaxed) != 2 {}
                                },
                                2 => {}, // now it's initialized
                                _ => unreachable!(),
                            }
                        }

                        match *DATA.0.get() {
                            Some(ref x) => x,
                            None => unreachable!(),
                        }
                    }

                    let static_ref = __stability();
                    require_sync(static_ref);
                    static_ref
                }
            }
        }
        lazy_static!($($t)*);
    };
    (MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<|endoftext|>