<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;

use crate::conversion::parse::type_converter::Annotated;
use crate::{
    conversion::{
        api::{ApiDetail, ParseResults, TypeApiDetails, TypedefKind, UnanalyzedApi},
        ConvertError,
    },
    types::make_ident,
    types::Namespace,
    types::TypeName,
};
use autocxx_parser::TypeConfig;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{parse_quote, Fields, Ident, Item, Type, TypePath, UseTree};

use super::{super::utilities::generate_utilities, type_converter::TypeConverter};

use super::parse_foreign_mod::ParseForeignMod;

/// Parses a bindgen mod in order to understand the APIs within it.
pub(crate) struct ParseBindgen<'a> {
    type_config: &'a TypeConfig,
    results: ParseResults,
    /// Here we track the last struct which bindgen told us about.
    /// Any subsequent "extern 'C'" blocks are methods belonging to that type,
    /// even if the 'this' is actually recorded as void in the
    /// function signature.
    latest_virtual_this_type: Option<TypeName>,
}

impl<'a> ParseBindgen<'a> {
    pub(crate) fn new(type_config: &'a TypeConfig) -> Self {
        ParseBindgen {
            type_config,
            results: ParseResults {
                apis: Vec::new(),
                type_converter: TypeConverter::new(),
            },
            latest_virtual_this_type: None,
        }
    }

    /// Parses items found in the `bindgen` output and returns a set of
    /// `Api`s together with some other data.
    pub(crate) fn parse_items(
        mut self,
        items: Vec<Item>,
        exclude_utilities: bool,
    ) -> Result<ParseResults, ConvertError> {
        let items = Self::find_items_in_root(items)?;
        if !exclude_utilities {
            generate_utilities(&mut self.results.apis);
        }
        let root_ns = Namespace::new();
        self.parse_mod_items(items, root_ns);
        Ok(self.results)
    }

    fn find_items_in_root(items: Vec<Item>) -> Result<Vec<Item>, ConvertError> {
        for item in items {
            match item {
                Item::Mod(root_mod) => {
                    // With namespaces enabled, bindgen always puts everything
                    // in a mod called 'root'. We don't want to pass that
                    // onto cxx, so jump right into it.
                    assert!(root_mod.ident == "root");
                    if let Some((_, items)) = root_mod.content {
                        return Ok(items);
                    }
                }
                _ => return Err(ConvertError::UnexpectedOuterItem),
            }
        }
        Ok(Vec::new())
    }

    /// Interpret the bindgen-generated .rs for a particular
    /// mod, which corresponds to a C++ namespace.
    fn parse_mod_items(&mut self, items: Vec<Item>, ns: Namespace) {
        // This object maintains some state specific to this namespace, i.e.
        // this particular mod.
        let mut mod_converter = ParseForeignMod::new(ns.clone());
        for item in items {
            let r = self.parse_item(item, &mut mod_converter, &ns);
            match r {
                Err(err) if err.is_ignorable() => {
                    eprintln!("Ignored item discovered whilst parsing: {}", err)
                }
                Err(_) => r.unwrap(),
                Ok(_) => {}
            }
        }
        mod_converter.finished(&mut self.results.apis);
    }

    fn parse_item(
        &mut self,
        item: Item,
        mod_converter: &mut ParseForeignMod,
        ns: &Namespace,
    ) -> Result<(), ConvertError> {
        match item {
            Item::ForeignMod(fm) => mod_converter
                .convert_foreign_mod_items(fm.items, self.latest_virtual_this_type.clone()),
            Item::Struct(s) => {
                if s.ident.to_string().ends_with("__bindgen_vtable") {
                    return Ok(());
                }
                let tyname = TypeName::new(ns, &s.ident.to_string());
                let is_forward_declaration = Self::spot_forward_declaration(&s.fields);
                // cxx::bridge can't cope with type aliases to generic
                // types at the moment.
                self.parse_type(
                    tyname.clone(),
                    is_forward_declaration,
                    HashSet::new(),
                    Some(Item::Struct(s)),
                );
                self.latest_virtual_this_type = Some(tyname);
                Ok(())
            }
            Item::Enum(e) => {
                let tyname = TypeName::new(ns, &e.ident.to_string());
                self.parse_type(tyname, false, HashSet::new(), Some(Item::Enum(e)));
                Ok(())
            }
            Item::Impl(imp) => {
                // We *mostly* ignore all impl blocks generated by bindgen.
                // Methods also appear in 'extern "C"' blocks which
                // we will convert instead. At that time we'll also construct
                // synthetic impl blocks.
                // We do however record which methods were spotted, since
                // we have no other way of working out which functions are
                // static methods vs plain functions.
                mod_converter.convert_impl_items(imp);
                Ok(())
            }
            Item::Mod(itm) => {
                if let Some((_, items)) = itm.content {
                    let new_ns = ns.push(itm.ident.to_string());
                    self.parse_mod_items(items, new_ns);
                }
                Ok(())
            }
            Item::Use(use_item) => {
                let mut segs = Vec::new();
                let mut tree = &use_item.tree;
                loop {
                    match tree {
                        UseTree::Path(up) => {
                            segs.push(up.ident.clone());
                            tree = &up.tree;
                        }
                        UseTree::Name(un) if un.ident == "root" => break, // we do not add this to any API since we generate equivalent
                        // use statements in our codegen phase.
                        UseTree::Rename(urn) => {
                            let id = &urn.ident;
                            let tyname = TypeName::new(ns, &id.to_string());
                            let other_id = &urn.rename;
                            if segs.remove(0) != "self" {
                                panic!("Path didn't start with self");
                            }
                            if segs.remove(0) != "super" {
                                panic!("Path didn't start with self::super");
                            }
                            // This is similar to the path encountered within 'tree'
                            // but without the self::super prefix which is unhelpful
                            // in our output mod, because we prefer relative paths
                            // (we're nested in another mod)
                            let newpath: TypePath = parse_quote! {
                                #(#segs)::* :: #id
                            };
                            let other_tyname = TypeName::from_type_path(&newpath);
                            if tyname == other_tyname {
                                return Err(ConvertError::InfinitelyRecursiveTypedef(tyname));
                            }
                            self.results
                                .type_converter
                                .insert_typedef(tyname, Type::Path(newpath.clone()));
                            let mut deps = HashSet::new();
                            deps.insert(other_tyname);
                            self.results.apis.push(UnanalyzedApi {
                                id: other_id.clone(),
                                ns: ns.clone(),
                                deps,
                                detail: ApiDetail::Typedef {
                                    payload: TypedefKind::Use(parse_quote! {
                                        pub use #newpath as #other_id;
                                    }),
                                },
                            });
                            break;
                        }
                        _ => panic!("Unexpected 'use' syntax encountered"),
                    }
                }
                Ok(())
            }
            Item::Const(const_item) => {
                // The following puts this constant into
                // the global namespace which is bug
                // https://github.com/google/autocxx/issues/133
                self.results.apis.push(UnanalyzedApi {
                    id: const_item.ident.clone(),
                    ns: ns.clone(),
                    deps: HashSet::new(),
                    detail: ApiDetail::Const { const_item },
                });
                Ok(())
            }
            Item::Type(mut ity) => {
                let tyname = TypeName::new(ns, &ity.ident.to_string());
                let type_conversion_results =
                    self.results.type_converter.convert_type(*ity.ty, ns, false);
                match type_conversion_results {
                    Err(ConvertError::OpaqueTypeFound) => {
                        self.add_opaque_type(ity.ident, ns.clone());
                        Ok(())
                    }
                    Err(err) => Err(err),
                    Ok(Annotated {
                        ty: syn::Type::Path(ref typ),
                        ..
                    }) if TypeName::from_type_path(typ) == tyname => {
                        Err(ConvertError::InfinitelyRecursiveTypedef(tyname))
                    }
                    Ok(mut final_type) => {
                        ity.ty = Box::new(final_type.ty.clone());
                        self.results
                            .type_converter
                            .insert_typedef(tyname, final_type.ty);
                        self.results.apis.append(&mut final_type.extra_apis);
                        self.results.apis.push(UnanalyzedApi {
                            id: ity.ident.clone(),
                            ns: ns.clone(),
                            deps: final_type.types_encountered,
                            detail: ApiDetail::Typedef {
                                payload: TypedefKind::Type(ity),
                            },
                        });
                        Ok(())
                    }
                }
            }
            _ => Err(ConvertError::UnexpectedItemInMod),
        }
    }

    fn spot_forward_declaration(s: &Fields) -> bool {
        s.iter()
            .filter_map(|f| f.ident.as_ref())
            .any(|id| id == "_unused")
    }

    fn add_opaque_type(&mut self, id: Ident, ns: Namespace) {
        self.results.apis.push(UnanalyzedApi {
            id,
            ns,
            deps: HashSet::new(),
            detail: ApiDetail::OpaqueTypedef,
        });
    }

    /// Record the Api for a type, e.g. enum or struct.
    /// Code generated includes the bindgen entry itself,
    /// various entries for the cxx::bridge to ensure cxx
    /// is aware of the type, and 'use' statements for the final
    /// output mod hierarchy. All are stored in the Api which
    /// this adds.
    fn parse_type(
        &mut self,
        tyname: TypeName,
        is_forward_declaration: bool,
        deps: HashSet<TypeName>,
        bindgen_mod_item: Option<Item>,
    ) {
        let final_ident = make_ident(tyname.get_final_ident());
        if self.type_config.is_on_blocklist(&tyname.to_cpp_name()) {
            return;
        }
        let tynamestring = tyname.to_cpp_name();
        let mut for_extern_c_ts = if tyname.has_namespace() {
            let ns_string = tyname
                .ns_segment_iter()
                .cloned()
                .collect::<Vec<String>>()
                .join("::");
            quote! {
                #[namespace = #ns_string]
            }
        } else {
            TokenStream2::new()
        };

        let mut fulltypath: Vec<_> = ["bindgen", "root"].iter().map(make_ident).collect();
        for_extern_c_ts.extend(quote! {
            type #final_ident = super::bindgen::root::
        });
        for segment in tyname.ns_segment_iter() {
            let id = make_ident(segment);
            for_extern_c_ts.extend(quote! {
                #id::
            });
            fulltypath.push(id);
        }
        for_extern_c_ts.extend(quote! {
            #final_ident;
        });
        fulltypath.push(final_ident.clone());
        let api = UnanalyzedApi {
            ns: tyname.get_namespace().clone(),
            id: final_ident.clone(),
            deps,
            detail: ApiDetail::Type {
                ty_details: TypeApiDetails {
                    fulltypath,
                    final_ident,
                    tynamestring,
                },
                for_extern_c_ts,
                is_forward_declaration,
                bindgen_mod_item,
                analysis: (),
            },
        };
        self.results.apis.push(api);
        self.results.type_converter.push(tyname);
    }
}
<commit_msg>Fix typedefs from 'use'.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;

use crate::conversion::parse::type_converter::Annotated;
use crate::{
    conversion::{
        api::{ApiDetail, ParseResults, TypeApiDetails, TypedefKind, UnanalyzedApi},
        ConvertError,
    },
    types::make_ident,
    types::Namespace,
    types::TypeName,
};
use autocxx_parser::TypeConfig;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{parse_quote, Fields, Ident, Item, Type, TypePath, UseTree};

use super::{super::utilities::generate_utilities, type_converter::TypeConverter};

use super::parse_foreign_mod::ParseForeignMod;

/// Parses a bindgen mod in order to understand the APIs within it.
pub(crate) struct ParseBindgen<'a> {
    type_config: &'a TypeConfig,
    results: ParseResults,
    /// Here we track the last struct which bindgen told us about.
    /// Any subsequent "extern 'C'" blocks are methods belonging to that type,
    /// even if the 'this' is actually recorded as void in the
    /// function signature.
    latest_virtual_this_type: Option<TypeName>,
}

impl<'a> ParseBindgen<'a> {
    pub(crate) fn new(type_config: &'a TypeConfig) -> Self {
        ParseBindgen {
            type_config,
            results: ParseResults {
                apis: Vec::new(),
                type_converter: TypeConverter::new(),
            },
            latest_virtual_this_type: None,
        }
    }

    /// Parses items found in the `bindgen` output and returns a set of
    /// `Api`s together with some other data.
    pub(crate) fn parse_items(
        mut self,
        items: Vec<Item>,
        exclude_utilities: bool,
    ) -> Result<ParseResults, ConvertError> {
        let items = Self::find_items_in_root(items)?;
        if !exclude_utilities {
            generate_utilities(&mut self.results.apis);
        }
        let root_ns = Namespace::new();
        self.parse_mod_items(items, root_ns);
        Ok(self.results)
    }

    fn find_items_in_root(items: Vec<Item>) -> Result<Vec<Item>, ConvertError> {
        for item in items {
            match item {
                Item::Mod(root_mod) => {
                    // With namespaces enabled, bindgen always puts everything
                    // in a mod called 'root'. We don't want to pass that
                    // onto cxx, so jump right into it.
                    assert!(root_mod.ident == "root");
                    if let Some((_, items)) = root_mod.content {
                        return Ok(items);
                    }
                }
                _ => return Err(ConvertError::UnexpectedOuterItem),
            }
        }
        Ok(Vec::new())
    }

    /// Interpret the bindgen-generated .rs for a particular
    /// mod, which corresponds to a C++ namespace.
    fn parse_mod_items(&mut self, items: Vec<Item>, ns: Namespace) {
        // This object maintains some state specific to this namespace, i.e.
        // this particular mod.
        let mut mod_converter = ParseForeignMod::new(ns.clone());
        for item in items {
            let r = self.parse_item(item, &mut mod_converter, &ns);
            match r {
                Err(err) if err.is_ignorable() => {
                    eprintln!("Ignored item discovered whilst parsing: {}", err)
                }
                Err(_) => r.unwrap(),
                Ok(_) => {}
            }
        }
        mod_converter.finished(&mut self.results.apis);
    }

    fn parse_item(
        &mut self,
        item: Item,
        mod_converter: &mut ParseForeignMod,
        ns: &Namespace,
    ) -> Result<(), ConvertError> {
        match item {
            Item::ForeignMod(fm) => mod_converter
                .convert_foreign_mod_items(fm.items, self.latest_virtual_this_type.clone()),
            Item::Struct(s) => {
                if s.ident.to_string().ends_with("__bindgen_vtable") {
                    return Ok(());
                }
                let tyname = TypeName::new(ns, &s.ident.to_string());
                let is_forward_declaration = Self::spot_forward_declaration(&s.fields);
                // cxx::bridge can't cope with type aliases to generic
                // types at the moment.
                self.parse_type(
                    tyname.clone(),
                    is_forward_declaration,
                    HashSet::new(),
                    Some(Item::Struct(s)),
                );
                self.latest_virtual_this_type = Some(tyname);
                Ok(())
            }
            Item::Enum(e) => {
                let tyname = TypeName::new(ns, &e.ident.to_string());
                self.parse_type(tyname, false, HashSet::new(), Some(Item::Enum(e)));
                Ok(())
            }
            Item::Impl(imp) => {
                // We *mostly* ignore all impl blocks generated by bindgen.
                // Methods also appear in 'extern "C"' blocks which
                // we will convert instead. At that time we'll also construct
                // synthetic impl blocks.
                // We do however record which methods were spotted, since
                // we have no other way of working out which functions are
                // static methods vs plain functions.
                mod_converter.convert_impl_items(imp);
                Ok(())
            }
            Item::Mod(itm) => {
                if let Some((_, items)) = itm.content {
                    let new_ns = ns.push(itm.ident.to_string());
                    self.parse_mod_items(items, new_ns);
                }
                Ok(())
            }
            Item::Use(use_item) => {
                let mut segs = Vec::new();
                let mut tree = &use_item.tree;
                loop {
                    match tree {
                        UseTree::Path(up) => {
                            segs.push(up.ident.clone());
                            tree = &up.tree;
                        }
                        UseTree::Name(un) if un.ident == "root" => break, // we do not add this to any API since we generate equivalent
                        // use statements in our codegen phase.
                        UseTree::Rename(urn) => {
                            let old_id = &urn.ident;
                            let new_id = &urn.rename;
                            let new_tyname = TypeName::new(ns, &new_id.to_string());
                            if segs.remove(0) != "self" {
                                panic!("Path didn't start with self");
                            }
                            if segs.remove(0) != "super" {
                                panic!("Path didn't start with self::super");
                            }
                            // This is similar to the path encountered within 'tree'
                            // but without the self::super prefix which is unhelpful
                            // in our output mod, because we prefer relative paths
                            // (we're nested in another mod)
                            let old_path: TypePath = parse_quote! {
                                #(#segs)::* :: #old_id
                            };
                            let old_tyname = TypeName::from_type_path(&old_path);
                            if new_tyname == old_tyname {
                                return Err(ConvertError::InfinitelyRecursiveTypedef(new_tyname));
                            }
                            self.results
                                .type_converter
                                .insert_typedef(new_tyname, Type::Path(old_path.clone()));
                            let mut deps = HashSet::new();
                            deps.insert(old_tyname);
                            self.results.apis.push(UnanalyzedApi {
                                id: new_id.clone(),
                                ns: ns.clone(),
                                deps,
                                detail: ApiDetail::Typedef {
                                    payload: TypedefKind::Use(parse_quote! {
                                        pub use #old_path as #new_id;
                                    }),
                                },
                            });
                            break;
                        }
                        _ => panic!("Unexpected 'use' syntax encountered"),
                    }
                }
                Ok(())
            }
            Item::Const(const_item) => {
                // The following puts this constant into
                // the global namespace which is bug
                // https://github.com/google/autocxx/issues/133
                self.results.apis.push(UnanalyzedApi {
                    id: const_item.ident.clone(),
                    ns: ns.clone(),
                    deps: HashSet::new(),
                    detail: ApiDetail::Const { const_item },
                });
                Ok(())
            }
            Item::Type(mut ity) => {
                let tyname = TypeName::new(ns, &ity.ident.to_string());
                let type_conversion_results =
                    self.results.type_converter.convert_type(*ity.ty, ns, false);
                match type_conversion_results {
                    Err(ConvertError::OpaqueTypeFound) => {
                        self.add_opaque_type(ity.ident, ns.clone());
                        Ok(())
                    }
                    Err(err) => Err(err),
                    Ok(Annotated {
                        ty: syn::Type::Path(ref typ),
                        ..
                    }) if TypeName::from_type_path(typ) == tyname => {
                        Err(ConvertError::InfinitelyRecursiveTypedef(tyname))
                    }
                    Ok(mut final_type) => {
                        ity.ty = Box::new(final_type.ty.clone());
                        self.results
                            .type_converter
                            .insert_typedef(tyname, final_type.ty);
                        self.results.apis.append(&mut final_type.extra_apis);
                        self.results.apis.push(UnanalyzedApi {
                            id: ity.ident.clone(),
                            ns: ns.clone(),
                            deps: final_type.types_encountered,
                            detail: ApiDetail::Typedef {
                                payload: TypedefKind::Type(ity),
                            },
                        });
                        Ok(())
                    }
                }
            }
            _ => Err(ConvertError::UnexpectedItemInMod),
        }
    }

    fn spot_forward_declaration(s: &Fields) -> bool {
        s.iter()
            .filter_map(|f| f.ident.as_ref())
            .any(|id| id == "_unused")
    }

    fn add_opaque_type(&mut self, id: Ident, ns: Namespace) {
        self.results.apis.push(UnanalyzedApi {
            id,
            ns,
            deps: HashSet::new(),
            detail: ApiDetail::OpaqueTypedef,
        });
    }

    /// Record the Api for a type, e.g. enum or struct.
    /// Code generated includes the bindgen entry itself,
    /// various entries for the cxx::bridge to ensure cxx
    /// is aware of the type, and 'use' statements for the final
    /// output mod hierarchy. All are stored in the Api which
    /// this adds.
    fn parse_type(
        &mut self,
        tyname: TypeName,
        is_forward_declaration: bool,
        deps: HashSet<TypeName>,
        bindgen_mod_item: Option<Item>,
    ) {
        let final_ident = make_ident(tyname.get_final_ident());
        if self.type_config.is_on_blocklist(&tyname.to_cpp_name()) {
            return;
        }
        let tynamestring = tyname.to_cpp_name();
        let mut for_extern_c_ts = if tyname.has_namespace() {
            let ns_string = tyname
                .ns_segment_iter()
                .cloned()
                .collect::<Vec<String>>()
                .join("::");
            quote! {
                #[namespace = #ns_string]
            }
        } else {
            TokenStream2::new()
        };

        let mut fulltypath: Vec<_> = ["bindgen", "root"].iter().map(make_ident).collect();
        for_extern_c_ts.extend(quote! {
            type #final_ident = super::bindgen::root::
        });
        for segment in tyname.ns_segment_iter() {
            let id = make_ident(segment);
            for_extern_c_ts.extend(quote! {
                #id::
            });
            fulltypath.push(id);
        }
        for_extern_c_ts.extend(quote! {
            #final_ident;
        });
        fulltypath.push(final_ident.clone());
        let api = UnanalyzedApi {
            ns: tyname.get_namespace().clone(),
            id: final_ident.clone(),
            deps,
            detail: ApiDetail::Type {
                ty_details: TypeApiDetails {
                    fulltypath,
                    final_ident,
                    tynamestring,
                },
                for_extern_c_ts,
                is_forward_declaration,
                bindgen_mod_item,
                analysis: (),
            },
        };
        self.results.apis.push(api);
        self.results.type_converter.push(tyname);
    }
}
<|endoftext|>


<commit_before>use std::hash::Hash;
use std::iter::Iterator;

use ::{Graph, Target};
use ::hidden::base::{Arc, ArcId, StateId, Vertex};

/// Immutable handle to a graph vertex ("node handle").
///
/// This zipper-like type enables traversal of a graph along the vertex's
/// incoming and outgoing edges.
pub struct Node<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: StateId,
}

/// Creates a new `Node` for the given graph and gamestate. This method is not
/// exported by the crate because it exposes implementation details. It is used
/// to provide a public cross-module interface for creating new `Node`s.
pub fn make_node<'a, T, S, A>(graph: &'a Graph<T, S, A>, id: StateId) -> Node<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        Node { graph: graph, id: id, }
    }

impl<'a, T, S, A> Node<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    fn children(&self) -> &'a [ArcId] {
        &self.graph.get_vertex(self.id).children
    }

    /// Returns an immutable ID that is guaranteed to identify this vertex
    /// uniquely within its graph. This ID may change when the graph is mutated.
    pub fn get_id(&self) -> usize {
        self.id.as_usize()
    }

    fn parents(&self) -> &'a [ArcId] {
        &self.graph.get_vertex(self.id).parents
    }

    /// Returns the data at this vertex.
    pub fn get_data(&self) -> &'a S {
        &self.graph.get_vertex(self.id).data
    }

    /// Returns true iff this vertex has no outgoing edges (regardless of
    /// whether they are expanded).
    pub fn is_leaf(&self) -> bool {
        self.children().is_empty()
    }

    /// Returns true iff this vertex has no incoming edges.
    pub fn is_root(&self) -> bool {
        self.parents().is_empty()
    }

    /// Returns a traversible list of outgoing edges.
    pub fn get_child_list(&self) -> ChildList<'a, T, S, A> {
        ChildList { graph: self.graph, id: self.id, }
    }

    /// Returns a traversible list of incoming edges.
    pub fn get_parent_list(&self) -> ParentList<'a, T, S, A> {
        ParentList { graph: self.graph, id: self.id, }
    }
}

/// A traversible list of a vertex's outgoing edges.
pub struct ChildList<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: StateId,
}

/// Creates a new `ChildList` for the given graph and gamestate. This method is
/// not exported by the crate because it exposes implementation details. It is
/// used to provide a public cross-module interface for creating new
/// `ChildList`s.
pub fn make_child_list<'a, T, S, A>(graph: &'a Graph<T, S, A>, id: StateId) -> ChildList<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        ChildList { graph: graph, id: id, }
    }

impl<'a, T, S, A> ChildList<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    fn vertex(&self) -> &'a Vertex<S> {
        self.graph.get_vertex(self.id)
    }

    /// Returns the number of edges.
    pub fn len(&self) -> usize {
        self.vertex().children.len()
    }

    /// Returns true iff there are no outgoing edges.
    pub fn is_empty(&self) -> bool {
        self.vertex().children.is_empty()
    }

    /// Returns a node handle for the vertex these edges originate from.
    pub fn get_source_node(&self) -> Node<'a, T, S, A> {
        Node { graph: self.graph, id: self.id, }
    }

    /// Returns an edge handle for the `i`th edge.
    pub fn get_edge(&self, i: usize) -> Edge<'a, T, S, A> {
        Edge { graph: self.graph, id: self.vertex().children[i], }
    }

    /// Returns an iterator over child edges.
    pub fn iter(&self) -> ChildListIter<'a, T, S, A> {
        ChildListIter { graph: self.graph, id: self.id, i: 0, }
    }
}

pub struct ChildListIter<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: StateId,
    i: usize,
}

impl <'a, T, S, A> ChildListIter<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        fn children(&self) -> &'a [ArcId] {
            &self.graph.get_vertex(self.id).children
        }
    }

impl<'a, T, S, A> Iterator for ChildListIter<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        type Item = Edge<'a, T, S, A>;

        fn next(&mut self) -> Option<Edge<'a, T, S, A>> {
            let cs = self.children();
            if self.i >= cs.len() {
                None
            } else {
                let e = make_edge(self.graph, cs[self.i]);
                self.i += 1;
                Some(e)
            }
        }

        fn size_hint(&self) -> (usize, Option<usize>) {
            let l = self.children().len();
            if l <= self.i {
                (0, Some(0))
            } else {
                (l - self.i, Some(l - self.i))
            }
        }
    }

/// A traversible list of a vertex's incoming edges.
pub struct ParentList<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: StateId,
}

/// Creates a new `ParentList` for the given graph and gamestate. This method is
/// not exported by the crate because it exposes implementation details. It is
/// used to provide a public cross-module interface for creating new
/// `ParentList`s.
pub fn make_parent_list<'a, T, S, A>(graph: &'a Graph<T, S, A>, id: StateId) -> ParentList<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        ParentList { graph: graph, id: id, }
    }

impl<'a, T, S, A> ParentList<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    fn vertex(&self) -> &'a Vertex<S> {
        self.graph.get_vertex(self.id)
    }

    /// Returns the number of edges.
    pub fn len(&self) -> usize {
        self.vertex().parents.len()
    }

    /// Returns true iff there are no incoming edges.
    pub fn is_empty(&self) -> bool {
        self.vertex().parents.is_empty()
    }

    /// Returns a node handle for the vertex these edges point to.
    pub fn target_node(&self) -> Node<'a, T, S, A> {
        Node { graph: self.graph, id: self.id, }
    }

    /// Returns an edge handle for the `i`th edge.
    pub fn get_edge(&self, i: usize) -> Edge<'a, T, S, A> {
        Edge { graph: self.graph, id: self.vertex().parents[i] }
    }

    /// Returns an iterator over parent edges.
    pub fn iter(&self) -> ParentListIter<'a, T, S, A> {
        ParentListIter { graph: self.graph, id: self.id, i: 0, }
    }
}

pub struct ParentListIter<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: StateId,
    i: usize,
}

impl<'a, T, S, A> ParentListIter<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    fn parents(&self) -> &'a [ArcId] {
        &self.graph.get_vertex(self.id).parents
    }
}

impl<'a, T, S, A> Iterator for ParentListIter<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        type Item = Edge<'a, T, S, A>;

        fn next(&mut self) -> Option<Edge<'a, T, S, A>> {
            let ps = self.parents();
            if ps.len() <= self.i {
                None
            } else {
                Some(make_edge(self.graph, ps[self.i]))
            }
        }

        fn size_hint(&self) -> (usize, Option<usize>) {
            let l = self.parents().len();
            if l <= self.i {
                (0, Some(0))
            } else {
                (l - self.i, Some(l - self.i))
            }
        }
    }

/// Immutable handle to a graph edge ("edge handle").
///
/// This zipper-like type enables traversal of a graph along the edge's source
/// and target vertices.
pub struct Edge<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: ArcId,
}

/// Creates a new `Edge` for the given graph and gamestate. This method is not
/// exported by the crate because it exposes implementation details. It is used
/// to provide a public cross-module interface for creating new `Edge`s.
pub fn make_edge<'a, T, S, A>(graph: &'a Graph<T, S, A>, id: ArcId) -> Edge<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        Edge { graph: graph, id: id, }
    }

impl<'a, T, S, A> Edge<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    fn arc(&self) -> &'a Arc<A> {
        self.graph.get_arc(self.id)
    }

    /// Returns an immutable ID that is guaranteed to identify this edge
    /// uniquely within its graph.  This ID may change when the graph is
    /// mutated.
    pub fn get_id(&self) -> usize {
        self.id.as_usize()
    }

    /// Returns the data at this edge.
    pub fn get_data(&self) -> &'a A {
        &self.arc().data
    }

    /// Returns a node handle for this edge's source vertex.
    pub fn get_source(&self) -> Node<'a, T, S, A> {
        Node { graph: self.graph, id: self.arc().source, }
    }

    /// Returns the target of this edge. If the edge is unexpanded, no data will
    /// be available. If it is expanded, a node handle will be available.
    pub fn get_target(&self) -> Target<Node<'a, T, S, A>, ()> {
        match self.arc().target {
            Target::Unexpanded(_) => Target::Unexpanded(()),
            Target::Expanded(id) => Target::Expanded(Node { graph: self.graph, id: id, }),
        }
    }
}
<commit_msg>Fix bug in Iterator impl for ParentListIter.<commit_after>use std::hash::Hash;
use std::iter::Iterator;

use ::{Graph, Target};
use ::hidden::base::{Arc, ArcId, StateId, Vertex};

/// Immutable handle to a graph vertex ("node handle").
///
/// This zipper-like type enables traversal of a graph along the vertex's
/// incoming and outgoing edges.
pub struct Node<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: StateId,
}

/// Creates a new `Node` for the given graph and gamestate. This method is not
/// exported by the crate because it exposes implementation details. It is used
/// to provide a public cross-module interface for creating new `Node`s.
pub fn make_node<'a, T, S, A>(graph: &'a Graph<T, S, A>, id: StateId) -> Node<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        Node { graph: graph, id: id, }
    }

impl<'a, T, S, A> Node<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    fn children(&self) -> &'a [ArcId] {
        &self.graph.get_vertex(self.id).children
    }

    /// Returns an immutable ID that is guaranteed to identify this vertex
    /// uniquely within its graph. This ID may change when the graph is mutated.
    pub fn get_id(&self) -> usize {
        self.id.as_usize()
    }

    fn parents(&self) -> &'a [ArcId] {
        &self.graph.get_vertex(self.id).parents
    }

    /// Returns the data at this vertex.
    pub fn get_data(&self) -> &'a S {
        &self.graph.get_vertex(self.id).data
    }

    /// Returns true iff this vertex has no outgoing edges (regardless of
    /// whether they are expanded).
    pub fn is_leaf(&self) -> bool {
        self.children().is_empty()
    }

    /// Returns true iff this vertex has no incoming edges.
    pub fn is_root(&self) -> bool {
        self.parents().is_empty()
    }

    /// Returns a traversible list of outgoing edges.
    pub fn get_child_list(&self) -> ChildList<'a, T, S, A> {
        ChildList { graph: self.graph, id: self.id, }
    }

    /// Returns a traversible list of incoming edges.
    pub fn get_parent_list(&self) -> ParentList<'a, T, S, A> {
        ParentList { graph: self.graph, id: self.id, }
    }
}

/// A traversible list of a vertex's outgoing edges.
pub struct ChildList<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: StateId,
}

/// Creates a new `ChildList` for the given graph and gamestate. This method is
/// not exported by the crate because it exposes implementation details. It is
/// used to provide a public cross-module interface for creating new
/// `ChildList`s.
pub fn make_child_list<'a, T, S, A>(graph: &'a Graph<T, S, A>, id: StateId) -> ChildList<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        ChildList { graph: graph, id: id, }
    }

impl<'a, T, S, A> ChildList<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    fn vertex(&self) -> &'a Vertex<S> {
        self.graph.get_vertex(self.id)
    }

    /// Returns the number of edges.
    pub fn len(&self) -> usize {
        self.vertex().children.len()
    }

    /// Returns true iff there are no outgoing edges.
    pub fn is_empty(&self) -> bool {
        self.vertex().children.is_empty()
    }

    /// Returns a node handle for the vertex these edges originate from.
    pub fn get_source_node(&self) -> Node<'a, T, S, A> {
        Node { graph: self.graph, id: self.id, }
    }

    /// Returns an edge handle for the `i`th edge.
    pub fn get_edge(&self, i: usize) -> Edge<'a, T, S, A> {
        Edge { graph: self.graph, id: self.vertex().children[i], }
    }

    /// Returns an iterator over child edges.
    pub fn iter(&self) -> ChildListIter<'a, T, S, A> {
        ChildListIter { graph: self.graph, id: self.id, i: 0, }
    }
}

pub struct ChildListIter<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: StateId,
    i: usize,
}

impl <'a, T, S, A> ChildListIter<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        fn children(&self) -> &'a [ArcId] {
            &self.graph.get_vertex(self.id).children
        }
    }

impl<'a, T, S, A> Iterator for ChildListIter<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        type Item = Edge<'a, T, S, A>;

        fn next(&mut self) -> Option<Edge<'a, T, S, A>> {
            let cs = self.children();
            if self.i >= cs.len() {
                None
            } else {
                let e = make_edge(self.graph, cs[self.i]);
                self.i += 1;
                Some(e)
            }
        }

        fn size_hint(&self) -> (usize, Option<usize>) {
            let l = self.children().len();
            if l <= self.i {
                (0, Some(0))
            } else {
                (l - self.i, Some(l - self.i))
            }
        }
    }

/// A traversible list of a vertex's incoming edges.
pub struct ParentList<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: StateId,
}

/// Creates a new `ParentList` for the given graph and gamestate. This method is
/// not exported by the crate because it exposes implementation details. It is
/// used to provide a public cross-module interface for creating new
/// `ParentList`s.
pub fn make_parent_list<'a, T, S, A>(graph: &'a Graph<T, S, A>, id: StateId) -> ParentList<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        ParentList { graph: graph, id: id, }
    }

impl<'a, T, S, A> ParentList<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    fn vertex(&self) -> &'a Vertex<S> {
        self.graph.get_vertex(self.id)
    }

    /// Returns the number of edges.
    pub fn len(&self) -> usize {
        self.vertex().parents.len()
    }

    /// Returns true iff there are no incoming edges.
    pub fn is_empty(&self) -> bool {
        self.vertex().parents.is_empty()
    }

    /// Returns a node handle for the vertex these edges point to.
    pub fn target_node(&self) -> Node<'a, T, S, A> {
        Node { graph: self.graph, id: self.id, }
    }

    /// Returns an edge handle for the `i`th edge.
    pub fn get_edge(&self, i: usize) -> Edge<'a, T, S, A> {
        Edge { graph: self.graph, id: self.vertex().parents[i] }
    }

    /// Returns an iterator over parent edges.
    pub fn iter(&self) -> ParentListIter<'a, T, S, A> {
        ParentListIter { graph: self.graph, id: self.id, i: 0, }
    }
}

pub struct ParentListIter<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: StateId,
    i: usize,
}

impl<'a, T, S, A> ParentListIter<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    fn parents(&self) -> &'a [ArcId] {
        &self.graph.get_vertex(self.id).parents
    }
}

impl<'a, T, S, A> Iterator for ParentListIter<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        type Item = Edge<'a, T, S, A>;

        fn next(&mut self) -> Option<Edge<'a, T, S, A>> {
            let ps = self.parents();
            if self.i >= ps.len() {
                None
            } else {
                let e = make_edge(self.graph, ps[self.i]);
                self.i += 1;
                Some(e)
            }
        }

        fn size_hint(&self) -> (usize, Option<usize>) {
            let l = self.parents().len();
            if l <= self.i {
                (0, Some(0))
            } else {
                (l - self.i, Some(l - self.i))
            }
        }
    }

/// Immutable handle to a graph edge ("edge handle").
///
/// This zipper-like type enables traversal of a graph along the edge's source
/// and target vertices.
pub struct Edge<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    graph: &'a Graph<T, S, A>,
    id: ArcId,
}

/// Creates a new `Edge` for the given graph and gamestate. This method is not
/// exported by the crate because it exposes implementation details. It is used
/// to provide a public cross-module interface for creating new `Edge`s.
pub fn make_edge<'a, T, S, A>(graph: &'a Graph<T, S, A>, id: ArcId) -> Edge<'a, T, S, A>
    where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
        Edge { graph: graph, id: id, }
    }

impl<'a, T, S, A> Edge<'a, T, S, A> where T: Hash + Eq + Clone + 'a, S: 'a, A: 'a {
    fn arc(&self) -> &'a Arc<A> {
        self.graph.get_arc(self.id)
    }

    /// Returns an immutable ID that is guaranteed to identify this edge
    /// uniquely within its graph.  This ID may change when the graph is
    /// mutated.
    pub fn get_id(&self) -> usize {
        self.id.as_usize()
    }

    /// Returns the data at this edge.
    pub fn get_data(&self) -> &'a A {
        &self.arc().data
    }

    /// Returns a node handle for this edge's source vertex.
    pub fn get_source(&self) -> Node<'a, T, S, A> {
        Node { graph: self.graph, id: self.arc().source, }
    }

    /// Returns the target of this edge. If the edge is unexpanded, no data will
    /// be available. If it is expanded, a node handle will be available.
    pub fn get_target(&self) -> Target<Node<'a, T, S, A>, ()> {
        match self.arc().target {
            Target::Unexpanded(_) => Target::Unexpanded(()),
            Target::Expanded(id) => Target::Expanded(Node { graph: self.graph, id: id, }),
        }
    }
}
<|endoftext|>


<commit_before>//! Backend implementation for a glutin headless renderer.

use {Frame, IncompatibleOpenGl, SwapBuffersError};
use debug;
use context;
use backend::{self, Backend};
use std::rc::Rc;
use std::cell::RefCell;
use std::ops::Deref;
use std::os::raw::c_void;
use super::glutin;
use super::glutin::PossiblyCurrent as Pc;
use takeable_option::Takeable;

/// A headless glutin context.
pub struct Headless {
    context: Rc<context::Context>,
    glutin: Rc<RefCell<Takeable<glutin::Context<Pc>>>>,
}

/// An implementation of the `Backend` trait for a glutin headless context.
pub struct GlutinBackend(Rc<RefCell<Takeable<glutin::Context<Pc>>>>);

impl Deref for Headless {
    type Target = context::Context;
    fn deref(&self) -> &context::Context {
        &self.context
    }
}

impl Deref for GlutinBackend {
    type Target = Rc<RefCell<Takeable<glutin::Context<Pc>>>>;
    fn deref(&self) -> &Rc<RefCell<Takeable<glutin::Context<Pc>>>> {
        &self.0
    }
}

unsafe impl Backend for GlutinBackend {
    #[inline]
    fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
        Ok(())
    }

    #[inline]
    unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
        self.0.borrow().get_proc_address(symbol) as *const _
    }

    #[inline]
    fn get_framebuffer_dimensions(&self) -> (u32, u32) {
        (800, 600)      // FIXME: these are random
    }

    #[inline]
    fn is_current(&self) -> bool {
        self.0.borrow().is_current()
    }

    #[inline]
    unsafe fn make_current(&self) {
        let mut gl_window_takeable = self.0.borrow_mut();
        let gl_window = Takeable::take(&mut gl_window_takeable);
        let gl_window_new = gl_window.make_current().unwrap();
        Takeable::insert(&mut gl_window_takeable, gl_window_new);
    }
}

impl backend::Facade for Headless {
    #[inline]
    fn get_context(&self) -> &Rc<context::Context> {
        &self.context
    }
}

impl Headless {
    /// Create a new glium `Headless` context.
    ///
    /// Performs a compatibility check to make sure that all core elements of glium are supported
    /// by the implementation.
    pub fn new(context: glutin::Context<Pc>) -> Result<Self, IncompatibleOpenGl> {
        Self::with_debug(context, Default::default())
    }

    /// Create a new glium `Headless` context.
    ///
    /// This function does the same as `build_glium`, except that the resulting context
    /// will assume that the current OpenGL context will never change.
    pub unsafe fn unchecked(context: glutin::Context<Pc>) -> Result<Self, IncompatibleOpenGl> {
        Self::unchecked_with_debug(context, Default::default())
    }

    /// The same as the `new` constructor, but allows for specifying debug callback behaviour.
    pub fn with_debug(context: glutin::Context<Pc>, debug: debug::DebugCallbackBehavior)
        -> Result<Self, IncompatibleOpenGl>
    {
        Self::new_inner(context, debug, true)
    }

    /// The same as the `unchecked` constructor, but allows for specifying debug callback behaviour.
    pub unsafe fn unchecked_with_debug(
        context: glutin::Context<Pc>,
        debug: debug::DebugCallbackBehavior,
    ) -> Result<Self, IncompatibleOpenGl>
    {
        Self::new_inner(context, debug, false)
    }

    fn new_inner(
        context: glutin::Context<Pc>,
        debug: debug::DebugCallbackBehavior,
        checked: bool,
    ) -> Result<Self, IncompatibleOpenGl>
    {
        let glutin_context = Rc::new(RefCell::new(Takeable::new(context)));
        let glutin_backend = GlutinBackend(glutin_context.clone());
        let context = try!(unsafe { context::Context::new(glutin_backend, checked, debug) });
        Ok(Headless { context: context, glutin: glutin_context })
    }

    /// Start drawing on the backbuffer.
    ///
    /// This function returns a `Frame`, which can be used to draw on it. When the `Frame` is
    /// destroyed, the buffers are swapped.
    ///
    /// Note that destroying a `Frame` is immediate, even if vsync is enabled.
    ///
    /// If the framebuffer dimensions have changed since the last call to `draw`, the inner glutin
    /// context will be resized accordingly before returning the `Frame`.
    #[inline]
    pub fn draw(&self) -> Frame {
        Frame::new(self.context.clone(), self.get_framebuffer_dimensions())
    }
}
<commit_msg>Make the constructors for the headless context accept generic contexts<commit_after>//! Backend implementation for a glutin headless renderer.

use {Frame, IncompatibleOpenGl, SwapBuffersError};
use debug;
use context;
use backend::{self, Backend};
use std::rc::Rc;
use std::cell::RefCell;
use std::ops::Deref;
use std::os::raw::c_void;
use super::glutin;
use super::glutin::{PossiblyCurrent as Pc, ContextCurrentState};
use takeable_option::Takeable;

/// A headless glutin context.
pub struct Headless {
    context: Rc<context::Context>,
    glutin: Rc<RefCell<Takeable<glutin::Context<Pc>>>>,
}

/// An implementation of the `Backend` trait for a glutin headless context.
pub struct GlutinBackend(Rc<RefCell<Takeable<glutin::Context<Pc>>>>);

impl Deref for Headless {
    type Target = context::Context;
    fn deref(&self) -> &context::Context {
        &self.context
    }
}

impl Deref for GlutinBackend {
    type Target = Rc<RefCell<Takeable<glutin::Context<Pc>>>>;
    fn deref(&self) -> &Rc<RefCell<Takeable<glutin::Context<Pc>>>> {
        &self.0
    }
}

unsafe impl Backend for GlutinBackend {
    #[inline]
    fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
        Ok(())
    }

    #[inline]
    unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
        self.0.borrow().get_proc_address(symbol) as *const _
    }

    #[inline]
    fn get_framebuffer_dimensions(&self) -> (u32, u32) {
        (800, 600)      // FIXME: these are random
    }

    #[inline]
    fn is_current(&self) -> bool {
        self.0.borrow().is_current()
    }

    #[inline]
    unsafe fn make_current(&self) {
        let mut gl_window_takeable = self.0.borrow_mut();
        let gl_window = Takeable::take(&mut gl_window_takeable);
        let gl_window_new = gl_window.make_current().unwrap();
        Takeable::insert(&mut gl_window_takeable, gl_window_new);
    }
}

impl backend::Facade for Headless {
    #[inline]
    fn get_context(&self) -> &Rc<context::Context> {
        &self.context
    }
}

impl Headless {
    /// Create a new glium `Headless` context.
    ///
    /// Performs a compatibility check to make sure that all core elements of glium are supported
    /// by the implementation.
    pub fn new<T: ContextCurrentState>(context: glutin::Context<T>) -> Result<Self, IncompatibleOpenGl> {
        Self::with_debug(context, Default::default())
    }

    /// Create a new glium `Headless` context.
    ///
    /// This function does the same as `build_glium`, except that the resulting context
    /// will assume that the current OpenGL context will never change.
    pub unsafe fn unchecked<T: ContextCurrentState>(context: glutin::Context<T>) -> Result<Self, IncompatibleOpenGl> {
        Self::unchecked_with_debug(context, Default::default())
    }

    /// The same as the `new` constructor, but allows for specifying debug callback behaviour.
    pub fn with_debug<T: ContextCurrentState>(context: glutin::Context<T>, debug: debug::DebugCallbackBehavior)
        -> Result<Self, IncompatibleOpenGl>
    {
        Self::new_inner(context, debug, true)
    }

    /// The same as the `unchecked` constructor, but allows for specifying debug callback behaviour.
    pub unsafe fn unchecked_with_debug<T: ContextCurrentState>(
        context: glutin::Context<T>,
        debug: debug::DebugCallbackBehavior,
    ) -> Result<Self, IncompatibleOpenGl>
    {
        Self::new_inner(context, debug, false)
    }

    fn new_inner<T: ContextCurrentState>(
        context: glutin::Context<T>,
        debug: debug::DebugCallbackBehavior,
        checked: bool,
    ) -> Result<Self, IncompatibleOpenGl>
    {
        let context = unsafe {
            context.treat_as_current()
        };
        let glutin_context = Rc::new(RefCell::new(Takeable::new(context)));
        let glutin_backend = GlutinBackend(glutin_context.clone());
        let context = try!(unsafe { context::Context::new(glutin_backend, checked, debug) });
        Ok(Headless { context: context, glutin: glutin_context })
    }

    /// Start drawing on the backbuffer.
    ///
    /// This function returns a `Frame`, which can be used to draw on it. When the `Frame` is
    /// destroyed, the buffers are swapped.
    ///
    /// Note that destroying a `Frame` is immediate, even if vsync is enabled.
    ///
    /// If the framebuffer dimensions have changed since the last call to `draw`, the inner glutin
    /// context will be resized accordingly before returning the `Frame`.
    #[inline]
    pub fn draw(&self) -> Frame {
        Frame::new(self.context.clone(), self.get_framebuffer_dimensions())
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2021 Anatoly Ikorsky
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use proptest::prelude::*;

use std::fmt;

use self::libstrings_bindings::*;

// Use `build.rs` to rebuild this.
#[allow(non_camel_case_types)]
mod libstrings_bindings;

impl fmt::Debug for decimal_t {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("decimal_t")
            .field("intg", &self.intg)
            .field("frac", &self.frac)
            .field("len", &self.len)
            .field("sign", &self.sign)
            .field("buf", &self.as_ref())
            .finish()
    }
}

impl decimal_t {
    pub fn new() -> Self {
        let buf = vec![0x80000000_u32 as i32; 16];
        let mut buf = buf.into_boxed_slice();
        let buf_ptr = buf.as_mut_ptr();
        std::mem::forget(buf);
        Self {
            intg: 0,
            frac: 0,
            len: 16,
            sign: false,
            buf: buf_ptr,
        }
    }

    pub fn as_ref(&self) -> &[i32] {
        unsafe { std::slice::from_raw_parts(self.buf, self.len as usize) }
    }

    pub fn rust_string2decimal(string: &str) -> Result<decimal_t, i32> {
        let mut to = Self::new();
        let result = unsafe {
            let end = &mut (string.as_ptr().add(string.len()) as *const i8);
            c_string2decimal(string.as_ptr() as *const i8, &mut to, end)
        };
        to.len = slice_end(to.as_ref(), 0x80000000_u32 as i32).len() as i32;
        if result == 0 {
            Ok(to)
        } else {
            Err(result)
        }
    }

    pub fn rust_decimal2bin(&self, to: &mut [u8]) -> Result<(), i32> {
        let result =
            unsafe { c_decimal2bin(self, to.as_mut_ptr(), self.intg + self.frac, self.frac) };
        if result == 0 {
            Ok(())
        } else {
            Err(result)
        }
    }

    pub fn rust_bin2decimal(
        from: &[u8],
        precision: i32,
        scale: i32,
        keep_prec: bool,
    ) -> Result<Self, i32> {
        let mut to = Self::new();
        let result = unsafe { c_bin2decimal(from.as_ptr(), &mut to, precision, scale, keep_prec) };
        to.len = slice_end(to.as_ref(), 0x80000000_u32 as i32).len() as i32;
        if result == 0 {
            Ok(to)
        } else {
            Err(result)
        }
    }

    pub fn rust_decimal2string(&self, to: &mut [u8]) -> Result<usize, i32> {
        let mut out_len = to.len() as i32;
        let result = unsafe { c_decimal2string(self, to.as_mut_ptr() as *mut _, &mut out_len) };
        if result == 0 {
            Ok(out_len as usize)
        } else {
            Err(result)
        }
    }
}

fn slice_end<T: PartialEq>(s: &[T], x: T) -> &[T] {
    let end = s.iter().position(|y| *y == x).unwrap_or(s.len());
    &s[..end]
}

proptest! {
    #![proptest_config(ProptestConfig {
        cases: 1 << 14, .. ProptestConfig::default()
    })]
    #[test]
    fn decimal_roundtrip(
        sign: bool,
        frac: bool,
        point in 0_usize..65,
        num in r"[0-9]{1,65}",
    ) {
        let num = {
            let mut out = String::new();
            if sign {
                out.push('-');
            }
            if frac {
                let (integral, fractional) = num.split_at(std::cmp::min(point, num.len()));
                out.push_str(integral);
                out.push('.');
                out.push_str(fractional);
            } else {
                out.push_str(&num);
            }
            out
        };

        let num = dbg!(&num);

        // test string2decimal
        let dec = dbg!(super::Decimal::parse_bytes(num.as_bytes()).unwrap());
        let mysql_dec = dbg!(decimal_t::rust_string2decimal(num).unwrap());
        assert_eq!(dec.intg, mysql_dec.intg as usize);
        assert_eq!(dec.frac, mysql_dec.frac as usize);
        assert_eq!(dec.sign, mysql_dec.sign);
        assert_eq!(dec.buf, mysql_dec.as_ref());

        // test decimal2bin
        let mut bin = Vec::new();
        let mut mysql_bin = vec![0b11111111_u8; 32];
        dec.write_bin(&mut bin).unwrap();
        let size = unsafe {
            c_decimal_bin_size(mysql_dec.intg + mysql_dec.frac, mysql_dec.frac) as usize
        };
        mysql_dec.rust_decimal2bin(&mut mysql_bin).unwrap();
        assert_eq!(dbg!(&bin[..]), dbg!(&mysql_bin[..size]));

        // test bin2decimal
        let dec2 = dbg!(super::Decimal::read_bin(&bin[..], dec.intg + dec.frac, dec.frac, false).unwrap());
        let mysql_dec2 = dbg!(decimal_t::rust_bin2decimal(
            &mysql_bin,
            mysql_dec.intg + mysql_dec.frac,
            mysql_dec.frac,
            false,
        )
        .unwrap());
        assert_eq!(dec2.intg, mysql_dec2.intg as usize);
        assert_eq!(dec2.frac, mysql_dec2.frac as usize);
        assert_eq!(dec2.sign, mysql_dec2.sign);
        assert_eq!(dec2.buf, mysql_dec2.as_ref());

        // test decimal2string
        let string = dec2.to_string();
        let mut mysql_string = vec![0_u8; 128];
        let out_len = mysql_dec2.rust_decimal2string(&mut mysql_string).unwrap();
        assert_eq!(
            string,
            std::str::from_utf8(&mysql_string[..out_len]).unwrap(),
        );

        // test bin2decimal keep_prec
        let dec2 = dbg!(super::Decimal::read_bin(&bin[..], dec.intg + dec.frac, dec.frac, true).unwrap());
        let mysql_dec2 = dbg!(decimal_t::rust_bin2decimal(
            &mysql_bin,
            mysql_dec.intg + mysql_dec.frac,
            mysql_dec.frac,
            true,
        )
        .unwrap());
        assert_eq!(dec2.intg, mysql_dec2.intg as usize);
        assert_eq!(dec2.frac, mysql_dec2.frac as usize);
        assert_eq!(dec2.sign, mysql_dec2.sign);
        assert_eq!(dec2.buf, mysql_dec2.as_ref());

        assert_eq!(dec, dec2);
    }
}
<commit_msg>Fix CI (see rust-lang/rust-bindgen#1651)<commit_after>// Copyright (c) 2021 Anatoly Ikorsky
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use proptest::prelude::*;

use std::fmt;

use self::libstrings_bindings::*;

// Use `build.rs` to rebuild this.
#[allow(non_camel_case_types)]
// this is due to rust-lang/rust-bindgen#1651
#[allow(deref_nullptr)]
mod libstrings_bindings;

impl fmt::Debug for decimal_t {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("decimal_t")
            .field("intg", &self.intg)
            .field("frac", &self.frac)
            .field("len", &self.len)
            .field("sign", &self.sign)
            .field("buf", &self.as_ref())
            .finish()
    }
}

impl decimal_t {
    pub fn new() -> Self {
        let buf = vec![0x80000000_u32 as i32; 16];
        let mut buf = buf.into_boxed_slice();
        let buf_ptr = buf.as_mut_ptr();
        std::mem::forget(buf);
        Self {
            intg: 0,
            frac: 0,
            len: 16,
            sign: false,
            buf: buf_ptr,
        }
    }

    pub fn as_ref(&self) -> &[i32] {
        unsafe { std::slice::from_raw_parts(self.buf, self.len as usize) }
    }

    pub fn rust_string2decimal(string: &str) -> Result<decimal_t, i32> {
        let mut to = Self::new();
        let result = unsafe {
            let end = &mut (string.as_ptr().add(string.len()) as *const i8);
            c_string2decimal(string.as_ptr() as *const i8, &mut to, end)
        };
        to.len = slice_end(to.as_ref(), 0x80000000_u32 as i32).len() as i32;
        if result == 0 {
            Ok(to)
        } else {
            Err(result)
        }
    }

    pub fn rust_decimal2bin(&self, to: &mut [u8]) -> Result<(), i32> {
        let result =
            unsafe { c_decimal2bin(self, to.as_mut_ptr(), self.intg + self.frac, self.frac) };
        if result == 0 {
            Ok(())
        } else {
            Err(result)
        }
    }

    pub fn rust_bin2decimal(
        from: &[u8],
        precision: i32,
        scale: i32,
        keep_prec: bool,
    ) -> Result<Self, i32> {
        let mut to = Self::new();
        let result = unsafe { c_bin2decimal(from.as_ptr(), &mut to, precision, scale, keep_prec) };
        to.len = slice_end(to.as_ref(), 0x80000000_u32 as i32).len() as i32;
        if result == 0 {
            Ok(to)
        } else {
            Err(result)
        }
    }

    pub fn rust_decimal2string(&self, to: &mut [u8]) -> Result<usize, i32> {
        let mut out_len = to.len() as i32;
        let result = unsafe { c_decimal2string(self, to.as_mut_ptr() as *mut _, &mut out_len) };
        if result == 0 {
            Ok(out_len as usize)
        } else {
            Err(result)
        }
    }
}

fn slice_end<T: PartialEq>(s: &[T], x: T) -> &[T] {
    let end = s.iter().position(|y| *y == x).unwrap_or(s.len());
    &s[..end]
}

proptest! {
    #![proptest_config(ProptestConfig {
        cases: 1 << 14, .. ProptestConfig::default()
    })]
    #[test]
    fn decimal_roundtrip(
        sign: bool,
        frac: bool,
        point in 0_usize..65,
        num in r"[0-9]{1,65}",
    ) {
        let num = {
            let mut out = String::new();
            if sign {
                out.push('-');
            }
            if frac {
                let (integral, fractional) = num.split_at(std::cmp::min(point, num.len()));
                out.push_str(integral);
                out.push('.');
                out.push_str(fractional);
            } else {
                out.push_str(&num);
            }
            out
        };

        let num = dbg!(&num);

        // test string2decimal
        let dec = dbg!(super::Decimal::parse_bytes(num.as_bytes()).unwrap());
        let mysql_dec = dbg!(decimal_t::rust_string2decimal(num).unwrap());
        assert_eq!(dec.intg, mysql_dec.intg as usize);
        assert_eq!(dec.frac, mysql_dec.frac as usize);
        assert_eq!(dec.sign, mysql_dec.sign);
        assert_eq!(dec.buf, mysql_dec.as_ref());

        // test decimal2bin
        let mut bin = Vec::new();
        let mut mysql_bin = vec![0b11111111_u8; 32];
        dec.write_bin(&mut bin).unwrap();
        let size = unsafe {
            c_decimal_bin_size(mysql_dec.intg + mysql_dec.frac, mysql_dec.frac) as usize
        };
        mysql_dec.rust_decimal2bin(&mut mysql_bin).unwrap();
        assert_eq!(dbg!(&bin[..]), dbg!(&mysql_bin[..size]));

        // test bin2decimal
        let dec2 = dbg!(super::Decimal::read_bin(&bin[..], dec.intg + dec.frac, dec.frac, false).unwrap());
        let mysql_dec2 = dbg!(decimal_t::rust_bin2decimal(
            &mysql_bin,
            mysql_dec.intg + mysql_dec.frac,
            mysql_dec.frac,
            false,
        )
        .unwrap());
        assert_eq!(dec2.intg, mysql_dec2.intg as usize);
        assert_eq!(dec2.frac, mysql_dec2.frac as usize);
        assert_eq!(dec2.sign, mysql_dec2.sign);
        assert_eq!(dec2.buf, mysql_dec2.as_ref());

        // test decimal2string
        let string = dec2.to_string();
        let mut mysql_string = vec![0_u8; 128];
        let out_len = mysql_dec2.rust_decimal2string(&mut mysql_string).unwrap();
        assert_eq!(
            string,
            std::str::from_utf8(&mysql_string[..out_len]).unwrap(),
        );

        // test bin2decimal keep_prec
        let dec2 = dbg!(super::Decimal::read_bin(&bin[..], dec.intg + dec.frac, dec.frac, true).unwrap());
        let mysql_dec2 = dbg!(decimal_t::rust_bin2decimal(
            &mysql_bin,
            mysql_dec.intg + mysql_dec.frac,
            mysql_dec.frac,
            true,
        )
        .unwrap());
        assert_eq!(dec2.intg, mysql_dec2.intg as usize);
        assert_eq!(dec2.frac, mysql_dec2.frac as usize);
        assert_eq!(dec2.sign, mysql_dec2.sign);
        assert_eq!(dec2.buf, mysql_dec2.as_ref());

        assert_eq!(dec, dec2);
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::str::FromStr;

use analysis::functions::Info as FuncInfo;

#[derive(Eq, Debug, Ord, PartialEq, PartialOrd)]
pub enum Type {
    Copy,
    Free,
    Ref,
    Unref,
}

impl FromStr for Type {
    type Err = ();

    fn from_str(s: &str) -> Result<Type, ()> {
        use self::Type::*;
        match s {
            "copy" => Ok(Copy),
            "free" => Ok(Free),
            "ref" => Ok(Ref),
            "unref" => Ok(Unref),
            _ => Err(()),
        }
    }
}

pub type Infos = BTreeMap<Type, String>; //Type => glib_name

pub fn extract(functions: &mut Vec<FuncInfo>) -> Infos {
    let mut specials = BTreeMap::new();

    functions.retain(|func| {
        match Type::from_str(&*func.name) {
            Ok(type_) => {
                specials.insert(type_, func.glib_name.clone());
                false
            }
            Err(_) => true,
        }
    });

    specials
}
<commit_msg>Mark some special functions as hidden instead of deleting them<commit_after>use std::collections::BTreeMap;
use std::str::FromStr;

use analysis::functions::Info as FuncInfo;
use analysis::functions::Visibility;

#[derive(Clone, Copy, Eq, Debug, Ord, PartialEq, PartialOrd)]
pub enum Type {
    Copy,
    Free,
    Ref,
    Unref,
}

impl FromStr for Type {
    type Err = ();

    fn from_str(s: &str) -> Result<Type, ()> {
        use self::Type::*;
        match s {
            "copy" => Ok(Copy),
            "free" => Ok(Free),
            "ref" => Ok(Ref),
            "unref" => Ok(Unref),
            _ => Err(()),
        }
    }
}

pub type Infos = BTreeMap<Type, String>; //Type => glib_name

pub fn extract(functions: &mut Vec<FuncInfo>) -> Infos {
    let mut specials = BTreeMap::new();

    for func in functions.iter_mut() {
        if let Ok(type_) = Type::from_str(&func.name) {
            func.visibility = visibility(type_);
            specials.insert(type_, func.glib_name.clone());
        }
    }

    specials
}

fn visibility(t: Type) -> Visibility {
    use self::Type::*;
    match t {
        Copy |
            Free |
            Ref |
            Unref => Visibility::Hidden,
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::{mem};

// Bounded package merge algorithm, based on the paper
// "A Fast and Space-Economical Algorithm for Length-Limited Coding
// Jyrki Katajainen, Alistair Moffat, Andrew Turpin".

#[derive(Debug, Clone)]
struct Node {
    weight: usize,
    leaf_counts: Vec<usize>,
}

impl Node {
    fn new(weight: usize, initial_count: usize, capacity: usize) -> Node {
        let mut n = Node {
            weight: weight,
            leaf_counts: Vec::with_capacity(capacity),
        };
        n.leaf_counts.push(initial_count);
        n
    }
}

#[derive(Debug)]
struct Leaf {
    weight: usize,
    index: usize,
}
impl PartialEq for Leaf {
    fn eq(&self, other: &Self) -> bool {
        self.weight == other.weight
    }
}
impl Eq for Leaf { }
impl Ord for Leaf {
    fn cmp(&self, other: &Self) -> Ordering {
        self.weight.cmp(&other.weight)
    }
}
impl PartialOrd for Leaf {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[derive(Debug, Clone)]
struct List {
    lookahead1: Node,
    lookahead2: Node,
    next_leaf_index: usize,
}

/// Calculates the bitlengths for the Huffman tree, based on the counts of each
/// symbol.
pub fn length_limited_code_lengths(frequencies: &[usize], max_bits: i32) -> Vec<u32> {
    let num_freqs = frequencies.len();
    let mut result = vec![0; num_freqs];

    // Count used symbols and place them in the leaves.
    let mut leaves: Vec<_> = frequencies.iter()
        .enumerate()
        .filter(|&(_, &freq)| freq != 0)
        .map(|(i, &freq)| Leaf { weight: freq, index: i })
        .collect();

    // Short circuit some special cases
    if leaves.is_empty() {
        // There are no non-zero frequencies.
        return result;
    }
    if leaves.len() == 1 {
        result[leaves[0].index] = 1;
        return result;
    }
    if leaves.len() == 2 {
        result[leaves[0].index] = 1;
        result[leaves[1].index] = 1;
        return result;
    }

    // Sort the leaves from least frequent to most frequent.
    leaves.sort();

    let max_num_leaves = 2 * leaves.len() - 2;
    let mut lists = vec![
        List {
            lookahead1: Node::new(leaves[0].weight, 1, max_num_leaves),
            lookahead2: Node::new(leaves[1].weight, 2, max_num_leaves),
            next_leaf_index: 2,
        };
        max_bits as usize
    ];

    // In the last list, 2 * numsymbols - 2 active chains need to be created. Two
    // are already created in the initialization. Each boundary_pm run creates one.
    let num_boundary_pm_runs = max_num_leaves - 2;
    for _ in 0..num_boundary_pm_runs {
        boundary_pm_toplevel(&mut lists[..], &leaves);
    }

    let mut a = lists.pop().unwrap().lookahead2.leaf_counts.into_iter().rev().peekable();

    let mut bitlength_value = 1;
    while let Some(leaf_count) = a.next() {
        let next_count = *a.peek().unwrap_or(&0);
        for leaf in &leaves[next_count..leaf_count] {
            result[leaf.index] = bitlength_value;
        }
        bitlength_value += 1;
    }

    result
}

fn lowest_list(lists: &mut [List], leaves: &[Leaf]) {
    // We're in the lowest list, just add another leaf to the lookaheads
    // There will always be more leaves to be added on level 0 so this is safe.
    let mut current_list = &mut lists[0];
    let next_leaf = &leaves[current_list.next_leaf_index];
    current_list.lookahead2.weight = next_leaf.weight;

    current_list.lookahead2.leaf_counts[0] = current_list.lookahead1.leaf_counts.last().unwrap() + 1;
    current_list.next_leaf_index += 1;
}

fn next_leaf(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let mut current_list = &mut lists[current_list_index];

    // The next leaf goes next; counting itself makes the leaf_count increase by one.
    current_list.lookahead2.weight = leaves[current_list.next_leaf_index].weight;
    current_list.lookahead2.leaf_counts.clear();
    current_list.lookahead2.leaf_counts.extend_from_slice(&current_list.lookahead1.leaf_counts);
    let last_index = current_list.lookahead2.leaf_counts.len() - 1;
    current_list.lookahead2.leaf_counts[last_index] += 1;
    current_list.next_leaf_index += 1;
}

fn next_tree(weight_sum: usize, lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    {
        let (head, tail) = lists.split_at_mut(current_list_index);
        let prev_list = head.last_mut().unwrap();
        let current_list = tail.first_mut().unwrap();

        let previous_list_leaf_counts = &prev_list.lookahead2.leaf_counts;

        // Make a tree from the lookaheads from the previous list; that goes next.
        // This is not a leaf node, so the leaf count stays the same.
        current_list.lookahead2.weight = weight_sum;
        current_list.lookahead2.leaf_counts.clear();

        current_list.lookahead2.leaf_counts.extend_from_slice(previous_list_leaf_counts);
        current_list.lookahead2.leaf_counts.push(*current_list.lookahead1.leaf_counts.last().unwrap());
    }

    // The previous list needs two new lookahead nodes.
    boundary_pm(lists, leaves, current_list_index - 1);
    boundary_pm(lists, leaves, current_list_index - 1);
}

fn boundary_pm_toplevel(lists: &mut [List], leaves: &[Leaf]) {
    let last_index = lists.len() - 1;
    boundary_pm(lists, leaves, last_index);
}

fn boundary_pm(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let next_leaf_index = lists[current_list_index].next_leaf_index;

    if current_list_index == 0 && next_leaf_index == leaves.len() {
        // We've added all the leaves to the lowest list, so we're done here
        return;
    }

    mem::swap(&mut lists[current_list_index].lookahead1, &mut lists[current_list_index].lookahead2);

    if current_list_index == 0 {
        lowest_list(lists, leaves);
    } else {
        // We're at a list other than the lowest list.
        let weight_sum = {
            let previous_list = &lists[current_list_index - 1];
            previous_list.lookahead1.weight + previous_list.lookahead2.weight
        };

        if next_leaf_index < leaves.len() && weight_sum > leaves[next_leaf_index].weight {
            next_leaf(lists, leaves, current_list_index);
        } else {
            next_tree(weight_sum, lists, leaves, current_list_index);
        }
    }
}

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

    #[test]
    fn test_from_paper_3() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 3);
        let answer = vec![3, 3, 3, 3, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn test_from_paper_4() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 4);
        let answer = vec![4, 4, 3, 2, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn max_bits_7() {
        let input = [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn max_bits_15() {
        let input = [0, 0, 0, 0, 0, 0, 18, 0, 6, 0, 12, 2, 14, 9, 27, 15, 23, 15, 17, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 15);
        let answer = vec! [0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 4, 6, 4, 4, 3, 4, 3, 3, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn no_frequencies() {
        let input = [0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_one_frequency() {
        let input = [0, 10, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 1, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_two_frequencies() {
        let input = [0, 0, 0, 0, 252, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }
}
<commit_msg>Make max_bits be a usize; makes more sense, less casting<commit_after>use std::cmp::Ordering;
use std::{mem};

// Bounded package merge algorithm, based on the paper
// "A Fast and Space-Economical Algorithm for Length-Limited Coding
// Jyrki Katajainen, Alistair Moffat, Andrew Turpin".

#[derive(Debug, Clone)]
struct Node {
    weight: usize,
    leaf_counts: Vec<usize>,
}

impl Node {
    fn new(weight: usize, initial_count: usize, capacity: usize) -> Node {
        let mut n = Node {
            weight: weight,
            leaf_counts: Vec::with_capacity(capacity),
        };
        n.leaf_counts.push(initial_count);
        n
    }
}

#[derive(Debug)]
struct Leaf {
    weight: usize,
    index: usize,
}
impl PartialEq for Leaf {
    fn eq(&self, other: &Self) -> bool {
        self.weight == other.weight
    }
}
impl Eq for Leaf { }
impl Ord for Leaf {
    fn cmp(&self, other: &Self) -> Ordering {
        self.weight.cmp(&other.weight)
    }
}
impl PartialOrd for Leaf {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[derive(Debug, Clone)]
struct List {
    lookahead1: Node,
    lookahead2: Node,
    next_leaf_index: usize,
}

/// Calculates the bitlengths for the Huffman tree, based on the counts of each
/// symbol.
pub fn length_limited_code_lengths(frequencies: &[usize], max_bits: usize) -> Vec<u32> {
    let num_freqs = frequencies.len();
    let mut result = vec![0; num_freqs];

    // Count used symbols and place them in the leaves.
    let mut leaves: Vec<_> = frequencies.iter()
        .enumerate()
        .filter(|&(_, &freq)| freq != 0)
        .map(|(i, &freq)| Leaf { weight: freq, index: i })
        .collect();

    // Short circuit some special cases
    if leaves.is_empty() {
        // There are no non-zero frequencies.
        return result;
    }
    if leaves.len() == 1 {
        result[leaves[0].index] = 1;
        return result;
    }
    if leaves.len() == 2 {
        result[leaves[0].index] = 1;
        result[leaves[1].index] = 1;
        return result;
    }

    // Sort the leaves from least frequent to most frequent.
    leaves.sort();

    let max_num_leaves = 2 * leaves.len() - 2;
    let mut lists = vec![
        List {
            lookahead1: Node::new(leaves[0].weight, 1, max_num_leaves),
            lookahead2: Node::new(leaves[1].weight, 2, max_num_leaves),
            next_leaf_index: 2,
        };
        max_bits
    ];

    // In the last list, 2 * numsymbols - 2 active chains need to be created. Two
    // are already created in the initialization. Each boundary_pm run creates one.
    let num_boundary_pm_runs = max_num_leaves - 2;
    for _ in 0..num_boundary_pm_runs {
        boundary_pm_toplevel(&mut lists[..], &leaves);
    }

    let mut a = lists.pop().unwrap().lookahead2.leaf_counts.into_iter().rev().peekable();

    let mut bitlength_value = 1;
    while let Some(leaf_count) = a.next() {
        let next_count = *a.peek().unwrap_or(&0);
        for leaf in &leaves[next_count..leaf_count] {
            result[leaf.index] = bitlength_value;
        }
        bitlength_value += 1;
    }

    result
}

fn lowest_list(lists: &mut [List], leaves: &[Leaf]) {
    // We're in the lowest list, just add another leaf to the lookaheads
    // There will always be more leaves to be added on level 0 so this is safe.
    let mut current_list = &mut lists[0];
    let next_leaf = &leaves[current_list.next_leaf_index];
    current_list.lookahead2.weight = next_leaf.weight;

    current_list.lookahead2.leaf_counts[0] = current_list.lookahead1.leaf_counts.last().unwrap() + 1;
    current_list.next_leaf_index += 1;
}

fn next_leaf(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let mut current_list = &mut lists[current_list_index];

    // The next leaf goes next; counting itself makes the leaf_count increase by one.
    current_list.lookahead2.weight = leaves[current_list.next_leaf_index].weight;
    current_list.lookahead2.leaf_counts.clear();
    current_list.lookahead2.leaf_counts.extend_from_slice(&current_list.lookahead1.leaf_counts);
    let last_index = current_list.lookahead2.leaf_counts.len() - 1;
    current_list.lookahead2.leaf_counts[last_index] += 1;
    current_list.next_leaf_index += 1;
}

fn next_tree(weight_sum: usize, lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    {
        let (head, tail) = lists.split_at_mut(current_list_index);
        let prev_list = head.last_mut().unwrap();
        let current_list = tail.first_mut().unwrap();

        let previous_list_leaf_counts = &prev_list.lookahead2.leaf_counts;

        // Make a tree from the lookaheads from the previous list; that goes next.
        // This is not a leaf node, so the leaf count stays the same.
        current_list.lookahead2.weight = weight_sum;
        current_list.lookahead2.leaf_counts.clear();

        current_list.lookahead2.leaf_counts.extend_from_slice(previous_list_leaf_counts);
        current_list.lookahead2.leaf_counts.push(*current_list.lookahead1.leaf_counts.last().unwrap());
    }

    // The previous list needs two new lookahead nodes.
    boundary_pm(lists, leaves, current_list_index - 1);
    boundary_pm(lists, leaves, current_list_index - 1);
}

fn boundary_pm_toplevel(lists: &mut [List], leaves: &[Leaf]) {
    let last_index = lists.len() - 1;
    boundary_pm(lists, leaves, last_index);
}

fn boundary_pm(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let next_leaf_index = lists[current_list_index].next_leaf_index;

    if current_list_index == 0 && next_leaf_index == leaves.len() {
        // We've added all the leaves to the lowest list, so we're done here
        return;
    }

    mem::swap(&mut lists[current_list_index].lookahead1, &mut lists[current_list_index].lookahead2);

    if current_list_index == 0 {
        lowest_list(lists, leaves);
    } else {
        // We're at a list other than the lowest list.
        let weight_sum = {
            let previous_list = &lists[current_list_index - 1];
            previous_list.lookahead1.weight + previous_list.lookahead2.weight
        };

        if next_leaf_index < leaves.len() && weight_sum > leaves[next_leaf_index].weight {
            next_leaf(lists, leaves, current_list_index);
        } else {
            next_tree(weight_sum, lists, leaves, current_list_index);
        }
    }
}

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

    #[test]
    fn test_from_paper_3() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 3);
        let answer = vec![3, 3, 3, 3, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn test_from_paper_4() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 4);
        let answer = vec![4, 4, 3, 2, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn max_bits_7() {
        let input = [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn max_bits_15() {
        let input = [0, 0, 0, 0, 0, 0, 18, 0, 6, 0, 12, 2, 14, 9, 27, 15, 23, 15, 17, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 15);
        let answer = vec! [0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 4, 6, 4, 4, 3, 4, 3, 3, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn no_frequencies() {
        let input = [0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_one_frequency() {
        let input = [0, 10, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 1, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_two_frequencies() {
        let input = [0, 0, 0, 0, 252, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }
}
<|endoftext|>