<commit_before>// Copyright 2013 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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
//
//     http://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.

extern crate xml;

use std::collections::hash_map::Entry;
use std::collections::BTreeSet;
use std::collections::HashSet;
use std::collections::HashMap;
use std::ops::Add;
use std::fmt;
use std::str::FromStr;
use std::slice::Iter;
use std::io;

use self::xml::EventReader as XmlEventReader;
use self::xml::attribute::OwnedAttribute;
use self::xml::reader::XmlEvent;

#[derive(Copy, Clone)]
pub enum Ns { Gl, Glx, Wgl, Egl, Gles1, Gles2 }

pub enum Fallbacks { All, None }

impl Ns {
    pub fn fmt_struct_name(&self) -> &str {
        match *self {
            Ns::Gl  => "Gl",
            Ns::Glx => "Glx",
            Ns::Wgl => "Wgl",
            Ns::Egl => "Egl",
            Ns::Gles1 => "Gles1",
            Ns::Gles2 => "Gles2",
        }
    }
}

impl FromStr for Ns {
    type Err = ();
    fn from_str(s: &str) -> Result<Ns, ()> {
        match s {
            "gl"  => Ok(Ns::Gl),
            "glx" => Ok(Ns::Glx),
            "wgl" => Ok(Ns::Wgl),
            "egl" => Ok(Ns::Egl),
            "gles1" => Ok(Ns::Gles1),
            "gles2" => Ok(Ns::Gles2),
            _     => Err(()),
        }
    }
}

impl fmt::Display for Ns {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Ns::Gl  => write!(fmt, "gl"),
            Ns::Glx => write!(fmt, "glx"),
            Ns::Wgl => write!(fmt, "wgl"),
            Ns::Egl => write!(fmt, "egl"),
            Ns::Gles1 => write!(fmt, "gles1"),
            Ns::Gles2 => write!(fmt, "gles2"),
        }
    }
}

fn trim_str<'a>(s: &'a str, trim: &str) -> &'a str {
    if s.starts_with(trim) { &s[trim.len()..] } else { s }
}

fn trim_enum_prefix<'a>(ident: &'a str, ns: Ns) -> &'a str {
    match ns {
        Ns::Gl | Ns::Gles1 | Ns::Gles2 => trim_str(ident, "GL_"),
        Ns::Glx => trim_str(ident, "GLX_"),
        Ns::Wgl =>  trim_str(ident, "WGL_"),
        Ns::Egl =>  trim_str(ident, "EGL_"),
    }
}

fn trim_cmd_prefix<'a>(ident: &'a str, ns: Ns) -> &'a str {
    match ns {
        Ns::Gl | Ns::Gles1 | Ns::Gles2 => trim_str(ident, "gl"),
        Ns::Glx => trim_str(ident, "glX"),
        Ns::Wgl =>  trim_str(ident, "wgl"),
        Ns::Egl =>  trim_str(ident, "egl"),
    }
}

fn merge_map(a: &mut HashMap<String, Vec<String>>, b: HashMap<String, Vec<String>>) {
    for (k, v) in b.into_iter() {
        match a.entry(k) {
            Entry::Occupied(mut ent) => { ent.get_mut().extend(v.into_iter()); },
            Entry::Vacant(ent) => { ent.insert(v); }
        }
    }
}

pub struct Registry {
    pub groups: Vec<Group>,
    pub enums: Vec<Enum>,
    pub cmds: Vec<Cmd>,
    pub features: Vec<Feature>,
    pub extensions: Vec<Extension>,
    pub aliases: HashMap<String, Vec<String>>,
}

impl Registry {
    /// Generate a registry from the supplied XML string
    pub fn from_xml<R: io::Read>(data: R, ns: Ns, filter: Option<Filter>) -> Registry {
        use std::io::BufReader;
        let data = BufReader::new(data);

        RegistryBuilder {
            ns: ns,
            filter: filter,
            reader: XmlEventReader::new(data),
        }.consume_registry()
    }

    /// Returns a set of all the types used in the supplied registry. This is useful
    /// for working out what conversions are needed for the specific registry.
    pub fn get_tys(&self) -> BTreeSet<String> {
        let mut tys = BTreeSet::new();
        for def in self.cmds.iter() {
            tys.insert(def.proto.ty.clone());
            for param in def.params.iter() {
                tys.insert(param.ty.clone());
            }
        }
        tys
    }

    pub fn enum_iter<'a>(&'a self) -> EnumIterator<'a> {
        EnumIterator {
            seen: HashSet::new(),
            iter: self.enums.iter(),
        }
    }

    pub fn cmd_iter<'a>(&'a self) -> CmdIterator<'a> {
        CmdIterator {
            seen: HashSet::new(),
            iter: self.cmds.iter(),
        }
    }
}

impl Add for Registry {
    type Output = Registry;

    fn add(mut self, other: Registry) -> Registry {
        self.groups.extend(other.groups.into_iter());
        self.enums.extend(other.enums.into_iter());
        self.cmds.extend(other.cmds.into_iter());
        self.features.extend(other.features.into_iter());
        self.extensions.extend(other.extensions.into_iter());
        self.aliases.extend(other.aliases.into_iter());
        self
    }
}

pub struct EnumIterator<'a> {
    seen: HashSet<String>,
    iter: Iter<'a, Enum>,
}

impl<'a> Iterator for EnumIterator<'a> {
    type Item = &'a Enum;

    fn next(&mut self) -> Option<&'a Enum> {
        self.iter.next().and_then(|def| {
            if !self.seen.contains(&def.ident) {
                self.seen.insert(def.ident.clone());
                Some(def)
            } else {
                self.next()
            }
        })
    }
}

pub struct CmdIterator<'a> {
    seen: HashSet<String>,
    iter: Iter<'a, Cmd>,
}

impl<'a> Iterator for CmdIterator<'a> {
    type Item = &'a Cmd;

    fn next(&mut self) -> Option<&'a Cmd> {
        self.iter.next().and_then(|def| {
            if !self.seen.contains(&def.proto.ident) {
                self.seen.insert(def.proto.ident.clone());
                Some(def)
            } else {
                self.next()
            }
        })
    }
}

pub struct Group {
    pub name: String,
    pub enums: Vec<String>,
}

pub struct EnumNs {
    pub namespace: String,
    pub group: Option<String>,
    pub ty: Option<String>,
    pub start: Option<String>,
    pub end: Option<String>,
    pub vendor: Option<String>,
    pub comment: Option<String>,
    pub defs: Vec<Enum>,
}

pub struct Enum {
    pub ident: String,
    pub value: String,
    pub alias: Option<String>,
    pub ty: Option<String>,
}

pub struct CmdNs {
    pub namespace: String,
    pub defs: Vec<Cmd>,
}

pub struct Binding {
    pub ident: String,
    pub ty: String,
    pub group: Option<String>,
}

pub struct Cmd {
    pub proto: Binding,
    pub params: Vec<Binding>,<commit_msg>Remove unused namespace structs<commit_after>// Copyright 2013 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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
//
//     http://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.

extern crate xml;

use std::collections::hash_map::Entry;
use std::collections::BTreeSet;
use std::collections::HashSet;
use std::collections::HashMap;
use std::ops::Add;
use std::fmt;
use std::str::FromStr;
use std::slice::Iter;
use std::io;

use self::xml::EventReader as XmlEventReader;
use self::xml::attribute::OwnedAttribute;
use self::xml::reader::XmlEvent;

#[derive(Copy, Clone)]
pub enum Ns { Gl, Glx, Wgl, Egl, Gles1, Gles2 }

pub enum Fallbacks { All, None }

impl Ns {
    pub fn fmt_struct_name(&self) -> &str {
        match *self {
            Ns::Gl  => "Gl",
            Ns::Glx => "Glx",
            Ns::Wgl => "Wgl",
            Ns::Egl => "Egl",
            Ns::Gles1 => "Gles1",
            Ns::Gles2 => "Gles2",
        }
    }
}

impl FromStr for Ns {
    type Err = ();
    fn from_str(s: &str) -> Result<Ns, ()> {
        match s {
            "gl"  => Ok(Ns::Gl),
            "glx" => Ok(Ns::Glx),
            "wgl" => Ok(Ns::Wgl),
            "egl" => Ok(Ns::Egl),
            "gles1" => Ok(Ns::Gles1),
            "gles2" => Ok(Ns::Gles2),
            _     => Err(()),
        }
    }
}

impl fmt::Display for Ns {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Ns::Gl  => write!(fmt, "gl"),
            Ns::Glx => write!(fmt, "glx"),
            Ns::Wgl => write!(fmt, "wgl"),
            Ns::Egl => write!(fmt, "egl"),
            Ns::Gles1 => write!(fmt, "gles1"),
            Ns::Gles2 => write!(fmt, "gles2"),
        }
    }
}

fn trim_str<'a>(s: &'a str, trim: &str) -> &'a str {
    if s.starts_with(trim) { &s[trim.len()..] } else { s }
}

fn trim_enum_prefix<'a>(ident: &'a str, ns: Ns) -> &'a str {
    match ns {
        Ns::Gl | Ns::Gles1 | Ns::Gles2 => trim_str(ident, "GL_"),
        Ns::Glx => trim_str(ident, "GLX_"),
        Ns::Wgl =>  trim_str(ident, "WGL_"),
        Ns::Egl =>  trim_str(ident, "EGL_"),
    }
}

fn trim_cmd_prefix<'a>(ident: &'a str, ns: Ns) -> &'a str {
    match ns {
        Ns::Gl | Ns::Gles1 | Ns::Gles2 => trim_str(ident, "gl"),
        Ns::Glx => trim_str(ident, "glX"),
        Ns::Wgl =>  trim_str(ident, "wgl"),
        Ns::Egl =>  trim_str(ident, "egl"),
    }
}

fn merge_map(a: &mut HashMap<String, Vec<String>>, b: HashMap<String, Vec<String>>) {
    for (k, v) in b.into_iter() {
        match a.entry(k) {
            Entry::Occupied(mut ent) => { ent.get_mut().extend(v.into_iter()); },
            Entry::Vacant(ent) => { ent.insert(v); }
        }
    }
}

pub struct Registry {
    pub groups: Vec<Group>,
    pub enums: Vec<Enum>,
    pub cmds: Vec<Cmd>,
    pub features: Vec<Feature>,
    pub extensions: Vec<Extension>,
    pub aliases: HashMap<String, Vec<String>>,
}

impl Registry {
    /// Generate a registry from the supplied XML string
    pub fn from_xml<R: io::Read>(data: R, ns: Ns, filter: Option<Filter>) -> Registry {
        use std::io::BufReader;
        let data = BufReader::new(data);

        RegistryBuilder {
            ns: ns,
            filter: filter,
            reader: XmlEventReader::new(data),
        }.consume_registry()
    }

    /// Returns a set of all the types used in the supplied registry. This is useful
    /// for working out what conversions are needed for the specific registry.
    pub fn get_tys(&self) -> BTreeSet<String> {
        let mut tys = BTreeSet::new();
        for def in self.cmds.iter() {
            tys.insert(def.proto.ty.clone());
            for param in def.params.iter() {
                tys.insert(param.ty.clone());
            }
        }
        tys
    }

    pub fn enum_iter<'a>(&'a self) -> EnumIterator<'a> {
        EnumIterator {
            seen: HashSet::new(),
            iter: self.enums.iter(),
        }
    }

    pub fn cmd_iter<'a>(&'a self) -> CmdIterator<'a> {
        CmdIterator {
            seen: HashSet::new(),
            iter: self.cmds.iter(),
        }
    }
}

impl Add for Registry {
    type Output = Registry;

    fn add(mut self, other: Registry) -> Registry {
        self.groups.extend(other.groups.into_iter());
        self.enums.extend(other.enums.into_iter());
        self.cmds.extend(other.cmds.into_iter());
        self.features.extend(other.features.into_iter());
        self.extensions.extend(other.extensions.into_iter());
        self.aliases.extend(other.aliases.into_iter());
        self
    }
}

pub struct EnumIterator<'a> {
    seen: HashSet<String>,
    iter: Iter<'a, Enum>,
}

impl<'a> Iterator for EnumIterator<'a> {
    type Item = &'a Enum;

    fn next(&mut self) -> Option<&'a Enum> {
        self.iter.next().and_then(|def| {
            if !self.seen.contains(&def.ident) {
                self.seen.insert(def.ident.clone());
                Some(def)
            } else {
                self.next()
            }
        })
    }
}

pub struct CmdIterator<'a> {
    seen: HashSet<String>,
    iter: Iter<'a, Cmd>,
}

impl<'a> Iterator for CmdIterator<'a> {
    type Item = &'a Cmd;

    fn next(&mut self) -> Option<&'a Cmd> {
        self.iter.next().and_then(|def| {
            if !self.seen.contains(&def.proto.ident) {
                self.seen.insert(def.proto.ident.clone());
                Some(def)
            } else {
                self.next()
            }
        })
    }
}

pub struct Group {
    pub name: String,
    pub enums: Vec<String>,
}

pub struct Enum {
    pub ident: String,
    pub value: String,
    pub alias: Option<String>,
    pub ty: Option<String>,
}

pub struct Binding {
    pub ident: String,
    pub ty: String,
    pub group: Option<String>,
}

pub struct Cmd {
    pub proto: Binding,
    pub params: Vec<Binding>,
{'fraction_non_alphanumeric': 0.15954850518608907, 'fraction_numerical': 0.003965832824893227, 'mean_word_length': 2.2218673218673217, 'pattern_counts': {'":': 0, '<': 89, '<?xml version=': 0, '>': 173, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 10}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1746047', 'n_tokens_mistral': 4460, 'n_tokens_neox': 4389, 'n_words': 1128}