<commit_before>use std::collections::BTreeMap;
use std::path::Path;

use inflector::Inflector;

#[derive(Deserialize, Clone, Debug)]
pub struct JsonSchema {
    pub id: Option<String>,
    pub title: Option<String>,
    #[serde(rename = "$schema")]
    pub schema_ref: Option<String>,
    pub description: Option<String>,
    #[serde(rename = "type")]
    pub ty: Option<String>,
    pub properties: Option<BTreeMap<String, JsonSchema>>,
    pub required: Option<Vec<String>>,
    pub definitions: Option<BTreeMap<String, JsonSchema>>,
    pub items: Option<Box<JsonSchema>>,
    #[serde(rename = "patternProperties")]
    pub pattern_properties: Option<BTreeMap<String, JsonSchema>>,
    #[serde(default, rename = "additionalProperties")]
    pub additional_properties: bool,
    #[serde(rename = "$ref")]
    pub definition_ref: Option<String>,
    #[serde(rename = "oneOf")]
    pub one_of: Option<Vec<JsonSchema>>,
}

#[derive(Clone, Debug)]
pub struct JsonObject {
    pub name: String,
    pub fields: Vec<JsonObjectFieldInfo>,
}

#[derive(Clone, Debug)]
pub struct JsonObjectFieldInfo {
    pub name: String,
    pub ty: PropType,
    pub rename: Option<String>,
    pub deserialize_with: Option<&'static str>,
    pub default: bool,
}

#[derive(Clone, Debug)]
pub struct JsonEnum {
    pub name: String,
    pub variants: Vec<JsonEnumVariant>,
}

#[derive(Clone, Debug)]
pub struct JsonEnumVariant {
    pub name: String,
    pub qualified_name: String,
    // TODO: this should be able to support non-containing variants
    pub inner: PropType,
}

#[derive(Clone, Debug)]
pub enum PropType {
    Str,
    Int,
    Num,
    Bool,
    Ref(String),
    Obj(JsonObject),
    Arr(Box<PropType>),
    Map(Box<PropType>),
    Optional(Box<PropType>),
    Enum(JsonEnum),
    Null,
}

impl PropType {
    pub fn from_schema(schema: &JsonSchema, name: &str) -> Self {
        if let Some(ref def) = schema.definition_ref {
            // TODO: This ignores `#/` and assumes filenames refer to an existing struct with that
            //       name.
            return PropType::Ref(Path::new(def)
                .file_stem()
                .unwrap()
                .to_str()
                .unwrap()
                .to_owned()
                .to_pascal_case());
        }

        if let Some(ref one_of) = schema.one_of {
            return PropType::Enum(JsonEnum {
                name: name.to_owned(),
                variants: one_of.iter()
                    .map(|o| {
                        // TODO: Have this just check title. id is not reliable
                        let variant_name =
                            o.title.as_ref().or_else(|| o.id.as_ref()).unwrap().to_pascal_case();
                        let obj_name = name.to_owned() + &variant_name;
                        JsonEnumVariant {
                            name: variant_name.clone(),
                            qualified_name: format!("{}::{}", name.to_owned(), variant_name),
                            inner: Self::from_schema(o, &obj_name),
                        }
                    })
                    .collect(),
            });
        }

        match schema.ty.as_ref().map(String::as_ref) {
            Some("boolean") => PropType::Bool,
            Some("string") => PropType::Str,
            Some("integer") => PropType::Int,
            Some("number") => PropType::Num,
            Some("null") => PropType::Null,
            Some("array") => {
                // HACK: to_singular is broken in current Inflector release
                let item_name = if name.ends_with("ies") {
                    name[..name.len() - 3].to_owned() + "y"
                } else {
                    name.to_singular()
                };
                let item_schema = schema.items
                    .as_ref()
                    .expect(&format!("{} is an array but no schema is set for items", item_name));
                let subobj = Self::from_schema(&item_schema.clone(), &item_name);
                PropType::Arr(Box::new(subobj))
            }
            Some("object") => {
                if let Some(ref pp) = schema.pattern_properties {
                    let subobj_schema = pp.iter().next().unwrap().1;
                    let subobj = Self::from_schema(subobj_schema, name);
                    PropType::Map(Box::new(subobj))
                } else {
                    PropType::Obj(schema.properties
                        .clone()
                        .map(|p| {
                            if p.is_empty() {
                                println!("{} is an object but has no properties. Likely an error.",
                                         &name);
                            }
                            let fields = p.iter()
                                .map(|(orig_name, p)| {
                                    let (field_name, rename) = match &orig_name[..] {
                                        "type" => ("ty", Some("type".into())),
                                        "self" => ("slf", Some("self".into())),
                                        name => (name, None),
                                    };
                                    let field_ty_name = name.to_owned() +
                                                        &orig_name.to_pascal_case();
                                    let mut ty = Self::from_schema(p, &field_ty_name);
                                    if let Some(ref req) = schema.required {
                                        if !req.contains(orig_name) {
                                            ty = PropType::Optional(Box::new(ty));
                                        }
                                    } else {
                                        ty = PropType::Optional(Box::new(ty));
                                    }
                                    // Hack for slack bug which writes empty map as empty array
                                    let default;
                                    let deserialize_with;
                                    if name == "UserProfile" && field_name == "fields" {
                                        deserialize_with = Some("::optional_struct_or_empty_array");
                                        default = true;
                                    } else {
                                        deserialize_with = None;
                                        default = false;
                                    }
                                    JsonObjectFieldInfo {
                                        name: field_name.into(),
                                        ty: ty,
                                        rename: rename,
                                        deserialize_with: deserialize_with,
                                        default: default,
                                    }
                                })
                                .collect();

                            JsonObject {
                                name: name.to_owned(),
                                fields: fields,
                            }
                        })
                        .expect("Failed to get sub object for object"))
                }
            }
            ty => panic!("Unknown JSON type: {:?} for {}", ty, name),
        }
    }

    pub fn to_rs_type(&self) -> String {
        match *self {
            PropType::Str => "String".into(),
            PropType::Int => "i32".into(),
            PropType::Num => "f32".into(),
            PropType::Bool => "bool".into(),
            PropType::Null => "()".into(),
            PropType::Obj(ref obj) => obj.name.clone(),
            PropType::Ref(ref name) => format!("::{}", name),
            PropType::Arr(ref prop) => format!("Vec<{}>", prop.to_rs_type()),
            PropType::Map(ref prop) => format!("HashMap<String, {}>", prop.to_rs_type()),
            PropType::Optional(ref prop) => format!("Option<{}>", prop.to_rs_type()),
            PropType::Enum(ref e) => e.name.clone(),
        }
    }
}<commit_msg>deserialize with optional_struct_or_empty_array for MessageBotMessage<commit_after>use std::collections::BTreeMap;
use std::path::Path;

use inflector::Inflector;

#[derive(Deserialize, Clone, Debug)]
pub struct JsonSchema {
    pub id: Option<String>,
    pub title: Option<String>,
    #[serde(rename = "$schema")]
    pub schema_ref: Option<String>,
    pub description: Option<String>,
    #[serde(rename = "type")]
    pub ty: Option<String>,
    pub properties: Option<BTreeMap<String, JsonSchema>>,
    pub required: Option<Vec<String>>,
    pub definitions: Option<BTreeMap<String, JsonSchema>>,
    pub items: Option<Box<JsonSchema>>,
    #[serde(rename = "patternProperties")]
    pub pattern_properties: Option<BTreeMap<String, JsonSchema>>,
    #[serde(default, rename = "additionalProperties")]
    pub additional_properties: bool,
    #[serde(rename = "$ref")]
    pub definition_ref: Option<String>,
    #[serde(rename = "oneOf")]
    pub one_of: Option<Vec<JsonSchema>>,
}

#[derive(Clone, Debug)]
pub struct JsonObject {
    pub name: String,
    pub fields: Vec<JsonObjectFieldInfo>,
}

#[derive(Clone, Debug)]
pub struct JsonObjectFieldInfo {
    pub name: String,
    pub ty: PropType,
    pub rename: Option<String>,
    pub deserialize_with: Option<&'static str>,
    pub default: bool,
}

#[derive(Clone, Debug)]
pub struct JsonEnum {
    pub name: String,
    pub variants: Vec<JsonEnumVariant>,
}

#[derive(Clone, Debug)]
pub struct JsonEnumVariant {
    pub name: String,
    pub qualified_name: String,
    // TODO: this should be able to support non-containing variants
    pub inner: PropType,
}

#[derive(Clone, Debug)]
pub enum PropType {
    Str,
    Int,
    Num,
    Bool,
    Ref(String),
    Obj(JsonObject),
    Arr(Box<PropType>),
    Map(Box<PropType>),
    Optional(Box<PropType>),
    Enum(JsonEnum),
    Null,
}

impl PropType {
    pub fn from_schema(schema: &JsonSchema, name: &str) -> Self {
        if let Some(ref def) = schema.definition_ref {
            // TODO: This ignores `#/` and assumes filenames refer to an existing struct with that
            //       name.
            return PropType::Ref(Path::new(def)
                .file_stem()
                .unwrap()
                .to_str()
                .unwrap()
                .to_owned()
                .to_pascal_case());
        }

        if let Some(ref one_of) = schema.one_of {
            return PropType::Enum(JsonEnum {
                name: name.to_owned(),
                variants: one_of.iter()
                    .map(|o| {
                        // TODO: Have this just check title. id is not reliable
                        let variant_name =
                            o.title.as_ref().or_else(|| o.id.as_ref()).unwrap().to_pascal_case();
                        let obj_name = name.to_owned() + &variant_name;
                        JsonEnumVariant {
                            name: variant_name.clone(),
                            qualified_name: format!("{}::{}", name.to_owned(), variant_name),
                            inner: Self::from_schema(o, &obj_name),
                        }
                    })
                    .collect(),
            });
        }

        match schema.ty.as_ref().map(String::as_ref) {
            Some("boolean") => PropType::Bool,
            Some("string") => PropType::Str,
            Some("integer") => PropType::Int,
            Some("number") => PropType::Num,
            Some("null") => PropType::Null,
            Some("array") => {
                // HACK: to_singular is broken in current Inflector release
                let item_name = if name.ends_with("ies") {
                    name[..name.len() - 3].to_owned() + "y"
                } else {
                    name.to_singular()
                };
                let item_schema = schema.items
                    .as_ref()
                    .expect(&format!("{} is an array but no schema is set for items", item_name));
                let subobj = Self::from_schema(&item_schema.clone(), &item_name);
                PropType::Arr(Box::new(subobj))
            }
            Some("object") => {
                if let Some(ref pp) = schema.pattern_properties {
                    let subobj_schema = pp.iter().next().unwrap().1;
                    let subobj = Self::from_schema(subobj_schema, name);
                    PropType::Map(Box::new(subobj))
                } else {
                    PropType::Obj(schema.properties
                        .clone()
                        .map(|p| {
                            if p.is_empty() {
                                println!("{} is an object but has no properties. Likely an error.",
                                         &name);
                            }
                            let fields = p.iter()
                                .map(|(orig_name, p)| {
                                    let (field_name, rename) = match &orig_name[..] {
                                        "type" => ("ty", Some("type".into())),
                                        "self" => ("slf", Some("self".into())),
                                        name => (name, None),
                                    };
                                    let field_ty_name = name.to_owned() +
                                                        &orig_name.to_pascal_case();
                                    let mut ty = Self::from_schema(p, &field_ty_name);
                                    if let Some(ref req) = schema.required {
                                        if !req.contains(orig_name) {
                                            ty = PropType::Optional(Box::new(ty));
                                        }
                                    } else {
                                        ty = PropType::Optional(Box::new(ty));
                                    }
                                    // Hack for slack bug which writes empty map as empty array
                                    let default;
                                    let deserialize_with;
                                    if name == "UserProfile" && field_name == "fields" {
                                        deserialize_with = Some("::optional_struct_or_empty_array");
                                        default = true;
                                    } else if name == "MessageBotMessage" && field_name == "icons" {
                                        deserialize_with = Some("::optional_struct_or_empty_array");
                                        default = true;
                                    } else {
                                        deserialize_with = None;
                                        default = false;
                                    }
                                    JsonObjectFieldInfo {
                                        name: field_name.into(),
                                        ty: ty,
                                        rename: rename,
                                        deserialize_with: deserialize_with,
                                        default: default,
                                    }
                                })
                                .collect();

                            JsonObject {
                                name: name.to_owned(),
                                fields: fields,
                            }
                        })
                        .expect("Failed to get sub object for object"))
                }
            }
            ty => panic!("Unknown JSON type: {:?} for {}", ty, name),
        }
    }

    pub fn to_rs_type(&self) -> String {
        match *self {
            PropType::Str => "String".into(),
            PropType::Int => "i32".into(),
            PropType::Num => "f32".into(),
            PropType::Bool => "bool".into(),
            PropType::Null => "()".into(),
            PropType::Obj(ref obj) => obj.name.clone(),
            PropType::Ref(ref name) => format!("::{}", name),
            PropType::Arr(ref prop) => format!("Vec<{}>", prop.to_rs_type()),
            PropType::Map(ref prop) => format!("HashMap<String, {}>", prop.to_rs_type()),
            PropType::Optional(ref prop) => format!("Option<{}>", prop.to_rs_type()),
            PropType::Enum(ref e) => e.name.clone(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 The 6502-rs Developers
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. Neither the names of the copyright holders nor the names of any
//    contributors may be used to endorse or promote products derived from this
//    software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#[deriving(PartialEq, Eq, PartialOrd, Ord)]
pub struct Address(pub u16);

#[deriving(PartialEq, Eq, PartialOrd, Ord)]
pub struct AddressDiff(pub u16);

// The idea here is that it doesn't make sense to add two addresses, but it
// does make sense to add an address and an "address-difference". (If this
// is too annoying to work with we should let it go.)

impl Add<AddressDiff, Address> for Address {
    fn add(&self, &AddressDiff(rhs): &AddressDiff) -> Address {
        let &Address(lhs) = self;

        // We probably don't want to overflow when doing arithmetic in our own
        // code.
        debug_assert!({
            match lhs.checked_add(&rhs) {
                None => false,
                _ => true
            }
        });

        return Address(lhs + rhs);
    }
}

impl Address {
	pub fn to_u16(&self) -> u16 {
		match *self {
			Address(address_) => address_
		}
	}

	pub fn to_uint(&self) -> uint {
		self.to_u16() as uint
	}

	pub fn get_page_number(&self) -> u8 {
		(self.to_u16() & 0xff00 >> 8) as u8
	}

	pub fn get_offset(&self) -> u8 {
		(self.to_u16() & 0x00ff) as u8
	}
}
<commit_msg>Integrate AddressingMode.<commit_after>// Copyright (C) 2014 The 6502-rs Developers
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. Neither the names of the copyright holders nor the names of any
//    contributors may be used to endorse or promote products derived from this
//    software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#[deriving(PartialEq, Eq, PartialOrd, Ord)]
pub struct Address(pub u16);

#[deriving(PartialEq, Eq, PartialOrd, Ord)]
pub struct AddressDiff(pub u16);

pub enum AddressingMode {
	Immediate,
	Absolute,
	ZeroPage,
	Implied,
	IndirectAbsolute,
	AbsoluteIndexedX,
	AbsoluteIndexedY,
	ZeroPageIndexedX,
	ZeroageIndexedY,
	IndexedIndirect,
	IndirectIndexed,
	Relative,
	Accumulator
}

// The idea here is that it doesn't make sense to add two addresses, but it
// does make sense to add an address and an "address-difference". (If this
// is too annoying to work with we should let it go.)

impl Add<AddressDiff, Address> for Address {
    fn add(&self, &AddressDiff(rhs): &AddressDiff) -> Address {
        let &Address(lhs) = self;

        // We probably don't want to overflow when doing arithmetic in our own
        // code.
        debug_assert!({
            match lhs.checked_add(&rhs) {
                None => false,
                _ => true
            }
        });

        return Address(lhs + rhs);
    }
}

impl Address {
	pub fn to_u16(&self) -> u16 {
		match *self {
			Address(address_) => address_
		}
	}

	pub fn to_uint(&self) -> uint {
		self.to_u16() as uint
	}

	pub fn get_page_number(&self) -> u8 {
		(self.to_u16() & 0xff00 >> 8) as u8
	}

	pub fn get_offset(&self) -> u8 {
		(self.to_u16() & 0x00ff) as u8
	}
}
<|endoftext|>


<commit_before>use ::crypto::{Hash, HASH_SIZE, hash};

pub use self::error::Error;
pub use self::db::{Database, Snapshot, Fork, Patch, Change, Iter};

pub use self::leveldb::LevelDB;
pub use self::memorydb::MemoryDB;

pub use self::keys::StorageKey;
pub use self::values::StorageValue;

pub use self::base_index::{BaseIndex, BaseIndexIter};
pub use self::entry::Entry;
pub use self::map_index::MapIndex;
pub use self::list_index::ListIndex;
pub use self::key_set_index::KeySetIndex;
pub use self::value_set_index::ValueSetIndex;
pub use self::proof_list_index::ProofListIndex;
pub use self::proof_map_index::ProofMapIndex;

pub type Result<T> = ::std::result::Result<T, Error>;

mod error;

mod db;
mod leveldb;
mod memorydb;

mod keys;
mod values;

mod base_index;
mod entry;
mod map_index;
mod list_index;
mod key_set_index;
mod value_set_index;
mod proof_list_index;
mod proof_map_index;

pub fn pair_hash(h1: &Hash, h2: &Hash) -> Hash {
    let mut v = [0; HASH_SIZE * 2];
    v[..HASH_SIZE].copy_from_slice(h1.as_ref());
    v[HASH_SIZE..].copy_from_slice(h2.as_ref());
    hash(&v)
}

// pub fn merkle_hash(hashes: &[Hash]) -> Hash {
//     match hashes.len() {
//         0 => Hash::default(),
//         1 => hashes[0],
//         n => {
//             let (l, r) = hashes.split_at(n.next_power_of_two() / 2);
//             pair_hash(&merkle_hash(l), &merkle_hash(r))
//         }
//     }
// }
<commit_msg>Reexports and public submodules<commit_after>use ::crypto::{Hash, HASH_SIZE, hash};

pub use self::error::Error;
pub use self::db::{Database, Snapshot, Fork, Patch, Change, Iter};

pub use self::leveldb::LevelDB;
pub use self::memorydb::MemoryDB;

pub use self::keys::StorageKey;
pub use self::values::StorageValue;

pub use self::entry::Entry;

pub use self::base_index::{BaseIndex, BaseIndexIter};
pub use self::map_index::MapIndex;
pub use self::list_index::ListIndex;
pub use self::key_set_index::KeySetIndex;
pub use self::value_set_index::ValueSetIndex;
pub use self::proof_list_index::ProofListIndex;
pub use self::proof_map_index::ProofMapIndex;

pub type Result<T> = ::std::result::Result<T, Error>;

mod error;

mod db;
mod leveldb;
mod memorydb;

mod keys;
mod values;

mod entry;

pub mod base_index;

pub mod map_index;
pub mod list_index;
pub mod key_set_index;
pub mod value_set_index;
pub mod proof_list_index;
pub mod proof_map_index;
<|endoftext|>


<commit_before>use crate::Multiaddr;
use libp2p::gossipsub::{GossipsubConfig, GossipsubConfigBuilder};

#[derive(Clone, Debug)]
/// Network configuration for lighthouse.
pub struct Config {
    //TODO: stubbing networking initial params, change in the future
    /// IP address to listen on.
    pub listen_addresses: Vec<Multiaddr>,
    /// Listen port UDP/TCP.
    pub listen_port: u16,
    /// Gossipsub configuration parameters.
    pub gs_config: GossipsubConfig,
    /// Configuration parameters for node identification protocol.
    pub identify_config: IdentifyConfig,
    /// List of nodes to initially connect to.
    pub boot_nodes: Vec<Multiaddr>,
    /// Client version
    pub client_version: String,
    /// List of topics to subscribe to as strings
    pub topics: Vec<String>,
}

impl Default for Config {
    /// Generate a default network configuration.
    fn default() -> Self {
        Config {
            listen_addresses: vec!["/ip4/127.0.0.1/tcp/9000"
                .parse()
                .expect("is a correct multi-address")],
            listen_port: 9000,
            gs_config: GossipsubConfigBuilder::new().build(),
            identify_config: IdentifyConfig::new(&version::version()),
            boot_nodes: Vec::new(),
            client_version: version::version(),
            topics: vec![String::from("beacon_chain")],
        }
    }
}

impl Config {
    pub fn new(boot_nodes: Vec<Multiaddr>) -> Self {
        let mut conf = Config::default();
        conf.boot_nodes = boot_nodes;

        conf
    }
}

/// The configuration parameters for the Identify protocol
#[derive(Debug, Clone)]
pub struct IdentifyConfig {
    /// The protocol version to listen on.
    pub version: String,
    /// The client's name and version for identification.
    pub user_agent: String,
}

impl Default for IdentifyConfig {
    fn default() -> Self {
        Self {
            version: "/eth/serenity/1.0".to_string(),
            user_agent: "Lighthouse".to_string(),
        }
    }
}

impl IdentifyConfig {
    /// Adds the version to the user agent.
    pub fn new(version: &String) -> Self {
        let mut config = IdentifyConfig::default();
        config.user_agent += version;
        config
    }
}
<commit_msg>Correct user agent string<commit_after>use crate::Multiaddr;
use libp2p::gossipsub::{GossipsubConfig, GossipsubConfigBuilder};

#[derive(Clone, Debug)]
/// Network configuration for lighthouse.
pub struct Config {
    //TODO: stubbing networking initial params, change in the future
    /// IP address to listen on.
    pub listen_addresses: Vec<Multiaddr>,
    /// Listen port UDP/TCP.
    pub listen_port: u16,
    /// Gossipsub configuration parameters.
    pub gs_config: GossipsubConfig,
    /// Configuration parameters for node identification protocol.
    pub identify_config: IdentifyConfig,
    /// List of nodes to initially connect to.
    pub boot_nodes: Vec<Multiaddr>,
    /// Client version
    pub client_version: String,
    /// List of topics to subscribe to as strings
    pub topics: Vec<String>,
}

impl Default for Config {
    /// Generate a default network configuration.
    fn default() -> Self {
        Config {
            listen_addresses: vec!["/ip4/127.0.0.1/tcp/9000"
                .parse()
                .expect("is a correct multi-address")],
            listen_port: 9000,
            gs_config: GossipsubConfigBuilder::new().build(),
            identify_config: IdentifyConfig::default(),
            boot_nodes: Vec::new(),
            client_version: version::version(),
            topics: vec![String::from("beacon_chain")],
        }
    }
}

impl Config {
    pub fn new(boot_nodes: Vec<Multiaddr>) -> Self {
        let mut conf = Config::default();
        conf.boot_nodes = boot_nodes;

        conf
    }
}

/// The configuration parameters for the Identify protocol
#[derive(Debug, Clone)]
pub struct IdentifyConfig {
    /// The protocol version to listen on.
    pub version: String,
    /// The client's name and version for identification.
    pub user_agent: String,
}

impl Default for IdentifyConfig {
    fn default() -> Self {
        Self {
            version: "/eth/serenity/1.0".to_string(),
            user_agent: version::version(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2016 William (B.J.) Snow Orvis
//
// 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.

pub mod fractaldata;
pub mod pistonrendering;
pub mod work_multiplexer;

fn main() {
    // Command line arguments specification
    let mut app = clap::App::new("fractal")
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about("Renders fractals in another window.");
    app = fractaldata::add_subcommands(app);

    let matches = app.get_matches();
    let result = fractaldata::run_subcommand(&matches);

    match result {
        Ok(_) => {}
        Err(e) => {
            use std;
            use std::io::{stderr, Write};
            writeln!(&mut stderr(), "{}", e).unwrap();
            std::process::exit(1);
        }
    }
}
<commit_msg>Remove a now-extraneous `use std`<commit_after>// Copyright (c) 2015-2016 William (B.J.) Snow Orvis
//
// 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.

pub mod fractaldata;
pub mod pistonrendering;
pub mod work_multiplexer;

fn main() {
    // Command line arguments specification
    let mut app = clap::App::new("fractal")
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about("Renders fractals in another window.");
    app = fractaldata::add_subcommands(app);

    let matches = app.get_matches();
    let result = fractaldata::run_subcommand(&matches);

    match result {
        Ok(_) => {}
        Err(e) => {
            use std::io::{stderr, Write};
            writeln!(&mut stderr(), "{}", e).unwrap();
            std::process::exit(1);
        }
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;

#[derive(Debug)]
pub enum Data
{
	Root,
	Module {},
	Import {name: String},
	Namespace {name: String},
	Interface {name: String},
	CID {name: String, cid: u64},
	IID {name: String, iid: u64}
}

pub type NodePtr = Box<Node>;

#[derive(Debug)]
pub struct Node
{
	parent: Option<Rc<NodePtr>>,
	first_child: Option<Rc<NodePtr>>,
	last_child: Option<Rc<NodePtr>>,
	prev: Option<Rc<NodePtr>>,
	next: Option<Rc<NodePtr>>,
	data: Data
}
impl Node
{
	pub fn new(data: Data) -> Box<Node>
	{
		Box::new(Node
		{
			parent: None,
			first_child: None,
			last_child: None,
			prev: None,
			next: None,
			data: data
		})
	}
}

#[derive(Debug)]
pub struct Tree
{
	root: Node
}
impl Tree
{
	pub fn new() -> Tree
	{
		Tree
		{
			root: Node
			{
				parent: None,
				first_child: None,
				last_child: None,
				prev: None,
				next: None,
				data: Data::Root
			}
		}
	}
}
impl<'a> IntoIterator for &'a Tree
{
	type Item = &'a Node;
	type IntoIter = TreeIterator<'a>;

	fn into_iter(self) -> Self::IntoIter
	{
		/*
		match self.root.first_child
		{
			None => TreeIterator {stack: Vec::new(), tree: self},
			Some(first) => TreeIterator {stack: vec![first], tree: self}
		}
		*/
		TreeIterator {stack: Vec::new(), tree: self}
	}
}

pub struct TreeIterator<'a>
{
	stack: Vec<Rc<NodePtr>>,
	tree: &'a Tree
}
impl<'a> Iterator for TreeIterator<'a>
{
	type Item = &'a Node;
	fn next(&mut self) -> Option<&'a Node>
	{
		return None;
	}
}

/*
#[derive(Debug)]
pub struct Tree
{
	root: Option<Index>,
	nodes: Vec<Node>
}
impl<'a> IntoIterator for &'a Tree
{
	type Item = &'a Node;
	type IntoIter = TreeIterator<'a>;
	fn into_iter(self) -> Self::IntoIter
	{
		match self.root
		{
			None => TreeIterator {stack: Vec::new(), tree: self},
			Some(root) => TreeIterator {stack: vec![root], tree: self}
		}
	}
}

pub struct TreeIterator<'a>
{
	stack: Vec<Index>,
	tree: &'a Tree // I assume this is going to copy the tree, we want a reference instead.
}
impl<'a> Iterator for TreeIterator<'a>
{
	type Item = &'a Node;
	fn next(&mut self) -> Option<&'a Node>
	{
		if self.stack.len() == 0
		{
			return None;
		}
		let current = self.stack.pop().unwrap();

		// If current has a sibling, we push that on the stack.
		match self.tree.nodes[current].next
		{
			Some(next) => self.stack.push(next),
			None => {}
		}
		// If current has a child, we push that on the stack so it will be processed next.
		match self.tree.nodes[current].first_child
		{
			Some(child) => self.stack.push(child),
			None => {}
		}

		return Some(&self.tree.nodes[current]);
	}
}

impl Tree
{
	pub fn new() -> Tree
	{
		Tree
		{
			root: None,
			nodes: Vec::new()
		}
	}
	pub fn get_root(&self) -> Option<Index>
	{
		return self.root;
	}
	pub fn set_root(&mut self, root: Index)
	{
		self.root = Some(root);
	}
	pub fn get_node(&self, node: Index) -> &Node
	{
		return &self.nodes[node];
	}
	pub fn create_node(&mut self, data: Data) -> Index
	{
		let index : Index = self.nodes.len();
		self.nodes.push(Node::new(data));
		index
	}
	pub fn add_child(&mut self, parent: Index, child: Index)
	{
		self.nodes[child].parent = Some(parent);
		self.nodes[child].prev = self.nodes[parent].last_child;
		self.nodes[parent].last_child = Some(child);
		match self.nodes[parent].first_child
		{
			None => {self.nodes[parent].first_child = Some(child);}
			Some(_) => {}
		}
	}
}
*/
<commit_msg>Further tweaks and changes.<commit_after>use std::rc::Rc;

#[derive(Debug)]
pub enum Data
{
	Root,
	Module {},
	Import {name: String},
	Namespace {name: String},
	Interface {name: String},
	CID {name: String, cid: u64},
	IID {name: String, iid: u64}
}

pub type NodePtr = Rc<Node>;

#[derive(Debug)]
pub struct Node
{
	parent: Option<NodePtr>,
	first_child: Option<NodePtr>,
	last_child: Option<NodePtr>,
	prev: Option<NodePtr>,
	next: Option<NodePtr>,
	data: Data
}
impl Node
{
	pub fn new(data: Data) -> NodePtr
	{
		Rc::new(Node
		{
			parent: None,
			first_child: None,
			last_child: None,
			prev: None,
			next: None,
			data: data
		})
	}
}

#[derive(Debug)]
pub struct Tree
{
	root: Node
}
impl Tree
{
	pub fn new() -> Tree
	{
		Tree
		{
			root: Node
			{
				parent: None,
				first_child: None,
				last_child: None,
				prev: None,
				next: None,
				data: Data::Root
			}
		}
	}
}
impl<'a> IntoIterator for &'a Tree
{
	type Item = &'a Node;
	type IntoIter = TreeIterator<'a>;

	fn into_iter(self) -> Self::IntoIter
	{
		match self.root.first_child
		{
			None => TreeIterator {stack: Vec::new(), tree: self},
			Some(ref first) =>
			{
				TreeIterator {stack: vec![first.clone()], tree: self}
			}
		}
	}
}

pub struct TreeIterator<'a>
{
	stack: Vec<NodePtr>,
	tree: &'a Tree
}
impl<'a> Iterator for TreeIterator<'a>
{
	type Item = &'a Node;
	fn next(&mut self) -> Option<&'a Node>
	{
		if self.stack.len() == 0
		{
			return None;
		}
		let current = self.stack.pop().unwrap();

		// If there is a sibling, push it on the stack to be processed later.
		match current.next
		{
			None => {},
			Some(ref next) => {}
		}

		return None;
	}
}

/*
impl<'a> Iterator for TreeIterator<'a>
{
	type Item = &'a Node;
	fn next(&mut self) -> Option<&'a Node>
	{
		if self.stack.len() == 0
		{
			return None;
		}
		let current = self.stack.pop().unwrap();

		// If current has a sibling, we push that on the stack.
		match self.tree.nodes[current].next
		{
			Some(next) => self.stack.push(next),
			None => {}
		}
		// If current has a child, we push that on the stack so it will be processed next.
		match self.tree.nodes[current].first_child
		{
			Some(child) => self.stack.push(child),
			None => {}
		}

		return Some(&self.tree.nodes[current]);
	}
}

impl Tree
{
	pub fn new() -> Tree
	{
		Tree
		{
			root: None,
			nodes: Vec::new()
		}
	}
	pub fn get_root(&self) -> Option<Index>
	{
		return self.root;
	}
	pub fn set_root(&mut self, root: Index)
	{
		self.root = Some(root);
	}
	pub fn get_node(&self, node: Index) -> &Node
	{
		return &self.nodes[node];
	}
	pub fn create_node(&mut self, data: Data) -> Index
	{
		let index : Index = self.nodes.len();
		self.nodes.push(Node::new(data));
		index
	}
	pub fn add_child(&mut self, parent: Index, child: Index)
	{
		self.nodes[child].parent = Some(parent);
		self.nodes[child].prev = self.nodes[parent].last_child;
		self.nodes[parent].last_child = Some(child);
		match self.nodes[parent].first_child
		{
			None => {self.nodes[parent].first_child = Some(child);}
			Some(_) => {}
		}
	}
}
*/
<|endoftext|>


<commit_before>//! Utility types to support cancellation.
//!
//! In a typical IDE use-case, requests and modification happen concurrently, as
//! in the following scenario:
//!
//!   * user types a character,
//!   * a syntax highlighting process is started
//!   * user types next character, while syntax highlighting *is still in
//!     progress*.
//!
//! In this situation, we want to react to modification as quickly as possible.
//! At the same time, in-progress results are not very interesting, because they
//! are invalidated by the edit anyway. So, we first cancel all in-flight
//! requests, and then apply modification knowing that it won't interfere with
//! any background processing (this bit is handled by salsa, see the
//! `BaseDatabase::check_canceled` method).

/// An "error" signifing that the operation was canceled.
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Canceled {
    _private: (),
}

pub type Cancelable<T> = Result<T, Canceled>;

impl Canceled {
    pub(crate) fn new() -> Canceled {
        Canceled { _private: () }
    }

    pub fn throw() -> ! {
        std::panic::resume_unwind(Box::new(Canceled::new()))
    }
}

impl std::fmt::Display for Canceled {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        fmt.write_str("canceled")
    }
}

impl std::fmt::Debug for Canceled {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(fmt, "Canceled")
    }
}

impl std::error::Error for Canceled {}
<commit_msg>explain why we use resume_unwind<commit_after>//! Utility types to support cancellation.
//!
//! In a typical IDE use-case, requests and modification happen concurrently, as
//! in the following scenario:
//!
//!   * user types a character,
//!   * a syntax highlighting process is started
//!   * user types next character, while syntax highlighting *is still in
//!     progress*.
//!
//! In this situation, we want to react to modification as quickly as possible.
//! At the same time, in-progress results are not very interesting, because they
//! are invalidated by the edit anyway. So, we first cancel all in-flight
//! requests, and then apply modification knowing that it won't interfere with
//! any background processing (this bit is handled by salsa, see the
//! `BaseDatabase::check_canceled` method).

/// An "error" signifing that the operation was canceled.
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Canceled {
    _private: (),
}

pub type Cancelable<T> = Result<T, Canceled>;

impl Canceled {
    pub(crate) fn new() -> Canceled {
        Canceled { _private: () }
    }

    pub fn throw() -> ! {
        // We use resume and not panic here to avoid running the panic
        // hook (that is, to avoid collecting and printing backtrace).
        std::panic::resume_unwind(Box::new(Canceled::new()))
    }
}

impl std::fmt::Display for Canceled {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        fmt.write_str("canceled")
    }
}

impl std::fmt::Debug for Canceled {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(fmt, "Canceled")
    }
}

impl std::error::Error for Canceled {}
<|endoftext|>


<commit_before><commit_msg>Add additional checks for union inference tests<commit_after><|endoftext|>


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

//! Screen capture infrastructure for the Gecko Profiler and Composition Recorder.

use std::collections::HashMap;

use api::{ImageFormat, TextureTarget};
use api::units::*;

use crate::device::{Device, PBO, DrawTarget, ReadTarget, Texture, TextureFilter};
use crate::internal_types::RenderTargetInfo;
use crate::renderer::Renderer;
use crate::util::round_up_to_multiple;

/// A handle to a screenshot that is being asynchronously captured and scaled.
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct AsyncScreenshotHandle(usize);

/// A handle to a recorded frame that was captured.
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RecordedFrameHandle(usize);

/// An asynchronously captured screenshot bound to a PBO which has not yet been mapped for copying.
struct AsyncScreenshot {
    /// The PBO that will contain the screenshot data.
    pbo: PBO,
    /// The size of the screenshot.
    screenshot_size: DeviceIntSize,
    /// The stride of the data in the PBO.
    buffer_stride: usize,
    /// Thge image format of the screenshot.
    image_format: ImageFormat,
}

/// How the `AsyncScreenshotGrabber` captures frames.
#[derive(Debug, Eq, PartialEq)]
enum AsyncScreenshotGrabberMode {
    /// Capture screenshots for the Gecko profiler.
    ///
    /// This mode will asynchronously scale the screenshots captured.
    ProfilerScreenshots,

    /// Capture screenshots for the CompositionRecorder.
    ///
    /// This mode does not scale the captured screenshots.
    CompositionRecorder,
}

/// Renderer infrastructure for capturing screenshots and scaling them asynchronously.
pub(in crate) struct AsyncScreenshotGrabber {
    /// The textures used to scale screenshots.
    scaling_textures: Vec<Texture>,
    /// PBOs available to be used for screenshot readback.
    available_pbos: Vec<PBO>,
    /// PBOs containing screenshots that are awaiting readback.
    awaiting_readback: HashMap<AsyncScreenshotHandle, AsyncScreenshot>,
    /// The handle for the net PBO that will be inserted into `in_use_pbos`.
    next_pbo_handle: usize,
    /// The mode the grabber operates in.
    mode: AsyncScreenshotGrabberMode,
}

impl Default for AsyncScreenshotGrabber {
    fn default() -> Self {
        AsyncScreenshotGrabber {
            scaling_textures: Vec::new(),
            available_pbos: Vec::new(),
            awaiting_readback: HashMap::new(),
            next_pbo_handle: 1,
            mode: AsyncScreenshotGrabberMode::ProfilerScreenshots,
        }
    }
}

impl AsyncScreenshotGrabber {
    /// Create a new AsyncScreenshotGrabber for the composition recorder.
    pub fn new_composition_recorder() -> Self {
        let mut recorder = Self::default();
        recorder.mode = AsyncScreenshotGrabberMode::CompositionRecorder;

        recorder
    }

    /// Deinitialize the allocated textures and PBOs.
    pub fn deinit(self, device: &mut Device) {
        for texture in self.scaling_textures {
            device.delete_texture(texture);
        }

        for pbo in self.available_pbos {
            device.delete_pbo(pbo);
        }

        for (_, async_screenshot) in self.awaiting_readback {
            device.delete_pbo(async_screenshot.pbo);
        }
    }

    /// Take a screenshot and scale it asynchronously.
    ///
    /// The returned handle can be used to access the mapped screenshot data via
    /// `map_and_recycle_screenshot`.
    /// The returned size is the size of the screenshot.
    pub fn get_screenshot(
        &mut self,
        device: &mut Device,
        window_rect: DeviceIntRect,
        buffer_size: DeviceIntSize,
        image_format: ImageFormat,
    ) -> (AsyncScreenshotHandle, DeviceIntSize) {
        let screenshot_size = match self.mode {
            AsyncScreenshotGrabberMode::ProfilerScreenshots => {
                let scale = (buffer_size.width as f32 / window_rect.size.width as f32)
                    .min(buffer_size.height as f32 / window_rect.size.height as f32);

                (window_rect.size.to_f32() * scale).round().to_i32()
            }

            AsyncScreenshotGrabberMode::CompositionRecorder => {
                assert_eq!(buffer_size, window_rect.size);
                buffer_size
            }
        };

        assert!(screenshot_size.width <= buffer_size.width);
        assert!(screenshot_size.height <= buffer_size.height);

        // To ensure that we hit the fast path when reading from a
        // framebuffer we must ensure that the width of the area we read
        // is a multiple of the device's optimal pixel-transfer stride.
        // The read_size should therefore be the screenshot_size with the width
        // increased to a suitable value. We will also pass this value to
        // scale_screenshot() as the min_texture_size, to ensure the texture is
        // large enough to read from. In CompositionRecorder mode we read
        // directly from the default framebuffer so are unable choose this size.
        let read_size = match self.mode {
            AsyncScreenshotGrabberMode::ProfilerScreenshots => {
                let stride = (screenshot_size.width * image_format.bytes_per_pixel()) as usize;
                let rounded = round_up_to_multiple(stride, device.get_optimal_pbo_stride());
                let optimal_width = rounded as i32 / image_format.bytes_per_pixel();

                DeviceIntSize::new(
                    optimal_width,
                    screenshot_size.height,
                )
            }
            AsyncScreenshotGrabberMode::CompositionRecorder => buffer_size,
        };
        let required_size = read_size.area() as usize * image_format.bytes_per_pixel() as usize;

        // Find an available PBO with the required size, creating a new one if necessary.
        let pbo = {
            let mut reusable_pbo = None;
            while let Some(pbo) = self.available_pbos.pop() {
                if pbo.get_reserved_size() != required_size {
                    device.delete_pbo(pbo);
                } else {
                    reusable_pbo = Some(pbo);
                    break;
                }
            };

            reusable_pbo.unwrap_or_else(|| device.create_pbo_with_size(required_size))
        };
        assert_eq!(pbo.get_reserved_size(), required_size);

        let read_target = match self.mode {
            AsyncScreenshotGrabberMode::ProfilerScreenshots => {
                self.scale_screenshot(
                    device,
                    ReadTarget::Default,
                    window_rect,
                    buffer_size,
                    read_size,
                    screenshot_size,
                    image_format,
                    0,
                );

                ReadTarget::from_texture(&self.scaling_textures[0], 0)
            }

            AsyncScreenshotGrabberMode::CompositionRecorder => ReadTarget::Default,
        };

        device.read_pixels_into_pbo(
            read_target,
            DeviceIntRect::new(DeviceIntPoint::new(0, 0), read_size),
            image_format,
            &pbo,
        );

        let handle = AsyncScreenshotHandle(self.next_pbo_handle);
        self.next_pbo_handle += 1;

        self.awaiting_readback.insert(
            handle,
            AsyncScreenshot {
                pbo,
                screenshot_size,
                buffer_stride: (read_size.width * image_format.bytes_per_pixel()) as usize,
                image_format,
            },
        );

        (handle, screenshot_size)
    }

    /// Take the screenshot in the given `ReadTarget` and scale it to `dest_size` recursively.
    ///
    /// Each scaling operation scales only by a factor of two to preserve quality.
    ///
    /// Textures are scaled such that `scaling_textures[n]` is half the size of
    /// `scaling_textures[n+1]`.
    ///
    /// After the scaling completes, the final screenshot will be in
    /// `scaling_textures[0]`.
    ///
    /// The size of `scaling_textures[0]` will be increased to `min_texture_size`
    /// so that an optimally-sized area can be read from it.
    fn scale_screenshot(
        &mut self,
        device: &mut Device,
        read_target: ReadTarget,
        read_target_rect: DeviceIntRect,
        buffer_size: DeviceIntSize,
        min_texture_size: DeviceIntSize,
        dest_size: DeviceIntSize,
        image_format: ImageFormat,
        level: usize,
    ) {
        assert_eq!(self.mode, AsyncScreenshotGrabberMode::ProfilerScreenshots);

        let texture_size = {
            let size = buffer_size * (1 << level);
            DeviceIntSize::new(
                size.width.max(min_texture_size.width),
                size.height.max(min_texture_size.height),
            )
        };

        // If we haven't created a texture for this level, or the existing
        // texture is the wrong size, then create a new one.
        if level == self.scaling_textures.len() || self.scaling_textures[level].get_dimensions() != texture_size {
            let texture = device.create_texture(
                TextureTarget::Default,
                image_format,
                texture_size.width,
                texture_size.height,
                TextureFilter::Linear,
                Some(RenderTargetInfo { has_depth: false }),
                1,
            );
            if level == self.scaling_textures.len() {
                self.scaling_textures.push(texture);
            } else {
                let old_texture = std::mem::replace(&mut self.scaling_textures[level], texture);
                device.delete_texture(old_texture);
            }
        }
        assert_eq!(self.scaling_textures[level].get_dimensions(), texture_size);

        let (read_target, read_target_rect) = if read_target_rect.size.width > 2 * dest_size.width {
            self.scale_screenshot(
                device,
                read_target,
                read_target_rect,
                buffer_size,
                min_texture_size,
                dest_size * 2,
                image_format,
                level + 1,
            );

            (
                ReadTarget::from_texture(&self.scaling_textures[level + 1], 0),
                DeviceIntRect::new(DeviceIntPoint::new(0, 0), dest_size * 2),
            )
        } else {
            (read_target, read_target_rect)
        };

        let draw_target = DrawTarget::from_texture(&self.scaling_textures[level], 0 as _, false);

        let draw_target_rect = draw_target
            .to_framebuffer_rect(DeviceIntRect::new(DeviceIntPoint::new(0, 0), dest_size));

        let read_target_rect = FramebufferIntRect::from_untyped(&read_target_rect.to_untyped());

        if level == 0 {
            device.blit_render_target_invert_y(
                read_target,
                read_target_rect,
                draw_target,
                draw_target_rect,
            );
        } else {
            device.blit_render_target(
                read_target,
                read_target_rect,
                draw_target,
                draw_target_rect,
                TextureFilter::Linear,
            );
        }
    }

    /// Map the contents of the screenshot given by the handle and copy it into
    /// the given buffer.
    pub fn map_and_recycle_screenshot(
        &mut self,
        device: &mut Device,
        handle: AsyncScreenshotHandle,
        dst_buffer: &mut [u8],
        dst_stride: usize,
    ) -> bool {
        let AsyncScreenshot {
            pbo,
            screenshot_size,
            buffer_stride,
            image_format,
        } = match self.awaiting_readback.remove(&handle) {
            Some(screenshot) => screenshot,
            None => return false,
        };

        let success = if let Some(bound_pbo) = device.map_pbo_for_readback(&pbo) {
            let src_buffer = &bound_pbo.data;
            let src_stride = buffer_stride;
            let src_width =
                screenshot_size.width as usize * image_format.bytes_per_pixel() as usize;

            for (src_slice, dst_slice) in src_buffer
                .chunks(src_stride)
                .zip(dst_buffer.chunks_mut(dst_stride))
                .take(screenshot_size.height as usize)
            {
                dst_slice[.. src_width].copy_from_slice(&src_slice[.. src_width]);
            }

            true
        } else {
            false
        };

        match self.mode {
            AsyncScreenshotGrabberMode::ProfilerScreenshots => self.available_pbos.push(pbo),
            AsyncScreenshotGrabberMode::CompositionRecorder => device.delete_pbo(pbo),
        }

        success
    }
}

// Screen-capture specific Renderer impls.
impl Renderer {
    /// Record a frame for the Composition Recorder.
    ///
    /// The returned handle can be passed to `map_recorded_frame` to copy it into
    /// a buffer.
    /// The returned size is the size of the frame.
    pub fn record_frame(
        &mut self,
        image_format: ImageFormat,
    ) -> Option<(RecordedFrameHandle, DeviceIntSize)> {
        let device_size = self.device_size()?;
        self.device.begin_frame();

        let (handle, _) = self
            .async_frame_recorder
            .get_or_insert_with(AsyncScreenshotGrabber::new_composition_recorder)
            .get_screenshot(
                &mut self.device,
                DeviceIntRect::new(DeviceIntPoint::new(0, 0), device_size),
                device_size,
                image_format,
            );

        self.device.end_frame();

        Some((RecordedFrameHandle(handle.0), device_size))
    }

    /// Map a frame captured for the composition recorder into the given buffer.
    pub fn map_recorded_frame(
        &mut self,
        handle: RecordedFrameHandle,
        dst_buffer: &mut [u8],
        dst_stride: usize,
    ) -> bool {
        if let Some(async_frame_recorder) = self.async_frame_recorder.as_mut() {
            async_frame_recorder.map_and_recycle_screenshot(
                &mut self.device,
                AsyncScreenshotHandle(handle.0),
                dst_buffer,
                dst_stride,
            )
        } else {
            false
        }
    }

    /// Free the data structures used by the composition recorder.
    pub fn release_composition_recorder_structures(&mut self) {
        if let Some(async_frame_recorder) = self.async_frame_recorder.take() {
            self.device.begin_frame();
            async_frame_recorder.deinit(&mut self.device);
            self.device.end_frame();
        }
    }

    /// Take a screenshot and scale it asynchronously.
    ///
    /// The returned handle can be used to access the mapped screenshot data via
    /// `map_and_recycle_screenshot`.
    ///
    /// The returned size is the size of the screenshot.
    pub fn get_screenshot_async(
        &mut self,
        window_rect: DeviceIntRect,
        buffer_size: DeviceIntSize,
        image_format: ImageFormat,
    ) -> (AsyncScreenshotHandle, DeviceIntSize) {
        self.device.begin_frame();

        let handle = self
            .async_screenshots
            .get_or_insert_with(AsyncScreenshotGrabber::default)
            .get_screenshot(&mut self.device, window_rect, buffer_size, image_format);

        self.device.end_frame();

        handle
    }

    /// Map the contents of the screenshot given by the handle and copy it into
    /// the given buffer.
    pub fn map_and_recycle_screenshot(
        &mut self,
        handle: AsyncScreenshotHandle,
        dst_buffer: &mut [u8],
        dst_stride: usize,
    ) -> bool {
        if let Some(async_screenshots) = self.async_screenshots.as_mut() {
            async_screenshots.map_and_recycle_screenshot(
                &mut self.device,
                handle,
                dst_buffer,
                dst_stride,
            )
        } else {
            false
        }
    }

    /// Release the screenshot grabbing structures that the profiler was using.
    pub fn release_profiler_structures(&mut self) {
        if let Some(async_screenshots) = self.async_screenshots.take() {
            self.device.begin_frame();
            async_screenshots.deinit(&mut self.device);
            self.device.end_frame();
        }
    }
}
<commit_msg>Bug 1570442 - Flip upside down recorded frames right side up on non-ANGLE configurations r=kvark<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Screen capture infrastructure for the Gecko Profiler and Composition Recorder.

use std::collections::HashMap;

use api::{ImageFormat, TextureTarget};
use api::units::*;
use gleam::gl::GlType;

use crate::device::{Device, PBO, DrawTarget, ReadTarget, Texture, TextureFilter};
use crate::internal_types::RenderTargetInfo;
use crate::renderer::Renderer;
use crate::util::round_up_to_multiple;

/// A handle to a screenshot that is being asynchronously captured and scaled.
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct AsyncScreenshotHandle(usize);

/// A handle to a recorded frame that was captured.
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RecordedFrameHandle(usize);

/// An asynchronously captured screenshot bound to a PBO which has not yet been mapped for copying.
struct AsyncScreenshot {
    /// The PBO that will contain the screenshot data.
    pbo: PBO,
    /// The size of the screenshot.
    screenshot_size: DeviceIntSize,
    /// The stride of the data in the PBO.
    buffer_stride: usize,
    /// Thge image format of the screenshot.
    image_format: ImageFormat,
}

/// How the `AsyncScreenshotGrabber` captures frames.
#[derive(Debug, Eq, PartialEq)]
enum AsyncScreenshotGrabberMode {
    /// Capture screenshots for the Gecko profiler.
    ///
    /// This mode will asynchronously scale the screenshots captured.
    ProfilerScreenshots,

    /// Capture screenshots for the CompositionRecorder.
    ///
    /// This mode does not scale the captured screenshots.
    CompositionRecorder,
}

/// Renderer infrastructure for capturing screenshots and scaling them asynchronously.
pub(in crate) struct AsyncScreenshotGrabber {
    /// The textures used to scale screenshots.
    scaling_textures: Vec<Texture>,
    /// PBOs available to be used for screenshot readback.
    available_pbos: Vec<PBO>,
    /// PBOs containing screenshots that are awaiting readback.
    awaiting_readback: HashMap<AsyncScreenshotHandle, AsyncScreenshot>,
    /// The handle for the net PBO that will be inserted into `in_use_pbos`.
    next_pbo_handle: usize,
    /// The mode the grabber operates in.
    mode: AsyncScreenshotGrabberMode,
}

impl Default for AsyncScreenshotGrabber {
    fn default() -> Self {
        AsyncScreenshotGrabber {
            scaling_textures: Vec::new(),
            available_pbos: Vec::new(),
            awaiting_readback: HashMap::new(),
            next_pbo_handle: 1,
            mode: AsyncScreenshotGrabberMode::ProfilerScreenshots,
        }
    }
}

impl AsyncScreenshotGrabber {
    /// Create a new AsyncScreenshotGrabber for the composition recorder.
    pub fn new_composition_recorder() -> Self {
        let mut recorder = Self::default();
        recorder.mode = AsyncScreenshotGrabberMode::CompositionRecorder;

        recorder
    }

    /// Deinitialize the allocated textures and PBOs.
    pub fn deinit(self, device: &mut Device) {
        for texture in self.scaling_textures {
            device.delete_texture(texture);
        }

        for pbo in self.available_pbos {
            device.delete_pbo(pbo);
        }

        for (_, async_screenshot) in self.awaiting_readback {
            device.delete_pbo(async_screenshot.pbo);
        }
    }

    /// Take a screenshot and scale it asynchronously.
    ///
    /// The returned handle can be used to access the mapped screenshot data via
    /// `map_and_recycle_screenshot`.
    /// The returned size is the size of the screenshot.
    pub fn get_screenshot(
        &mut self,
        device: &mut Device,
        window_rect: DeviceIntRect,
        buffer_size: DeviceIntSize,
        image_format: ImageFormat,
    ) -> (AsyncScreenshotHandle, DeviceIntSize) {
        let screenshot_size = match self.mode {
            AsyncScreenshotGrabberMode::ProfilerScreenshots => {
                let scale = (buffer_size.width as f32 / window_rect.size.width as f32)
                    .min(buffer_size.height as f32 / window_rect.size.height as f32);

                (window_rect.size.to_f32() * scale).round().to_i32()
            }

            AsyncScreenshotGrabberMode::CompositionRecorder => {
                assert_eq!(buffer_size, window_rect.size);
                buffer_size
            }
        };

        assert!(screenshot_size.width <= buffer_size.width);
        assert!(screenshot_size.height <= buffer_size.height);

        // To ensure that we hit the fast path when reading from a
        // framebuffer we must ensure that the width of the area we read
        // is a multiple of the device's optimal pixel-transfer stride.
        // The read_size should therefore be the screenshot_size with the width
        // increased to a suitable value. We will also pass this value to
        // scale_screenshot() as the min_texture_size, to ensure the texture is
        // large enough to read from. In CompositionRecorder mode we read
        // directly from the default framebuffer so are unable choose this size.
        let read_size = match self.mode {
            AsyncScreenshotGrabberMode::ProfilerScreenshots => {
                let stride = (screenshot_size.width * image_format.bytes_per_pixel()) as usize;
                let rounded = round_up_to_multiple(stride, device.get_optimal_pbo_stride());
                let optimal_width = rounded as i32 / image_format.bytes_per_pixel();

                DeviceIntSize::new(
                    optimal_width,
                    screenshot_size.height,
                )
            }
            AsyncScreenshotGrabberMode::CompositionRecorder => buffer_size,
        };
        let required_size = read_size.area() as usize * image_format.bytes_per_pixel() as usize;

        // Find an available PBO with the required size, creating a new one if necessary.
        let pbo = {
            let mut reusable_pbo = None;
            while let Some(pbo) = self.available_pbos.pop() {
                if pbo.get_reserved_size() != required_size {
                    device.delete_pbo(pbo);
                } else {
                    reusable_pbo = Some(pbo);
                    break;
                }
            };

            reusable_pbo.unwrap_or_else(|| device.create_pbo_with_size(required_size))
        };
        assert_eq!(pbo.get_reserved_size(), required_size);

        let read_target = match self.mode {
            AsyncScreenshotGrabberMode::ProfilerScreenshots => {
                self.scale_screenshot(
                    device,
                    ReadTarget::Default,
                    window_rect,
                    buffer_size,
                    read_size,
                    screenshot_size,
                    image_format,
                    0,
                );

                ReadTarget::from_texture(&self.scaling_textures[0], 0)
            }

            AsyncScreenshotGrabberMode::CompositionRecorder => ReadTarget::Default,
        };

        device.read_pixels_into_pbo(
            read_target,
            DeviceIntRect::new(DeviceIntPoint::new(0, 0), read_size),
            image_format,
            &pbo,
        );

        let handle = AsyncScreenshotHandle(self.next_pbo_handle);
        self.next_pbo_handle += 1;

        self.awaiting_readback.insert(
            handle,
            AsyncScreenshot {
                pbo,
                screenshot_size,
                buffer_stride: (read_size.width * image_format.bytes_per_pixel()) as usize,
                image_format,
            },
        );

        (handle, screenshot_size)
    }

    /// Take the screenshot in the given `ReadTarget` and scale it to `dest_size` recursively.
    ///
    /// Each scaling operation scales only by a factor of two to preserve quality.
    ///
    /// Textures are scaled such that `scaling_textures[n]` is half the size of
    /// `scaling_textures[n+1]`.
    ///
    /// After the scaling completes, the final screenshot will be in
    /// `scaling_textures[0]`.
    ///
    /// The size of `scaling_textures[0]` will be increased to `min_texture_size`
    /// so that an optimally-sized area can be read from it.
    fn scale_screenshot(
        &mut self,
        device: &mut Device,
        read_target: ReadTarget,
        read_target_rect: DeviceIntRect,
        buffer_size: DeviceIntSize,
        min_texture_size: DeviceIntSize,
        dest_size: DeviceIntSize,
        image_format: ImageFormat,
        level: usize,
    ) {
        assert_eq!(self.mode, AsyncScreenshotGrabberMode::ProfilerScreenshots);

        let texture_size = {
            let size = buffer_size * (1 << level);
            DeviceIntSize::new(
                size.width.max(min_texture_size.width),
                size.height.max(min_texture_size.height),
            )
        };

        // If we haven't created a texture for this level, or the existing
        // texture is the wrong size, then create a new one.
        if level == self.scaling_textures.len() || self.scaling_textures[level].get_dimensions() != texture_size {
            let texture = device.create_texture(
                TextureTarget::Default,
                image_format,
                texture_size.width,
                texture_size.height,
                TextureFilter::Linear,
                Some(RenderTargetInfo { has_depth: false }),
                1,
            );
            if level == self.scaling_textures.len() {
                self.scaling_textures.push(texture);
            } else {
                let old_texture = std::mem::replace(&mut self.scaling_textures[level], texture);
                device.delete_texture(old_texture);
            }
        }
        assert_eq!(self.scaling_textures[level].get_dimensions(), texture_size);

        let (read_target, read_target_rect) = if read_target_rect.size.width > 2 * dest_size.width {
            self.scale_screenshot(
                device,
                read_target,
                read_target_rect,
                buffer_size,
                min_texture_size,
                dest_size * 2,
                image_format,
                level + 1,
            );

            (
                ReadTarget::from_texture(&self.scaling_textures[level + 1], 0),
                DeviceIntRect::new(DeviceIntPoint::new(0, 0), dest_size * 2),
            )
        } else {
            (read_target, read_target_rect)
        };

        let draw_target = DrawTarget::from_texture(&self.scaling_textures[level], 0 as _, false);

        let draw_target_rect = draw_target
            .to_framebuffer_rect(DeviceIntRect::new(DeviceIntPoint::new(0, 0), dest_size));

        let read_target_rect = FramebufferIntRect::from_untyped(&read_target_rect.to_untyped());

        if level == 0 {
            device.blit_render_target_invert_y(
                read_target,
                read_target_rect,
                draw_target,
                draw_target_rect,
            );
        } else {
            device.blit_render_target(
                read_target,
                read_target_rect,
                draw_target,
                draw_target_rect,
                TextureFilter::Linear,
            );
        }
    }

    /// Map the contents of the screenshot given by the handle and copy it into
    /// the given buffer.
    pub fn map_and_recycle_screenshot(
        &mut self,
        device: &mut Device,
        handle: AsyncScreenshotHandle,
        dst_buffer: &mut [u8],
        dst_stride: usize,
    ) -> bool {
        let AsyncScreenshot {
            pbo,
            screenshot_size,
            buffer_stride,
            image_format,
        } = match self.awaiting_readback.remove(&handle) {
            Some(screenshot) => screenshot,
            None => return false,
        };

        let gl_type = device.gl().get_type();

        let success = if let Some(bound_pbo) = device.map_pbo_for_readback(&pbo) {
            let src_buffer = &bound_pbo.data;
            let src_stride = buffer_stride;
            let src_width =
                screenshot_size.width as usize * image_format.bytes_per_pixel() as usize;

            for (src_slice, dst_slice) in self
                .iter_src_buffer_chunked(gl_type, src_buffer, src_stride)
                .zip(dst_buffer.chunks_mut(dst_stride))
                .take(screenshot_size.height as usize)
            {
                dst_slice[.. src_width].copy_from_slice(&src_slice[.. src_width]);
            }

            true
        } else {
            false
        };

        match self.mode {
            AsyncScreenshotGrabberMode::ProfilerScreenshots => self.available_pbos.push(pbo),
            AsyncScreenshotGrabberMode::CompositionRecorder => device.delete_pbo(pbo),
        }

        success
    }

    fn iter_src_buffer_chunked<'a>(
        &self,
        gl_type: GlType,
        src_buffer: &'a [u8],
        src_stride: usize,
    ) -> Box<dyn Iterator<Item = &'a [u8]> + 'a> {
        use AsyncScreenshotGrabberMode::*;

        let is_angle = cfg!(windows) && gl_type == GlType::Gles;

        if self.mode == CompositionRecorder && !is_angle {
            // This is a non-ANGLE configuration. in this case, the recorded frames were captured
            // upside down, so we have to flip them right side up.
            Box::new(src_buffer.chunks(src_stride).rev())
        } else {
            // This is either an ANGLE configuration in the `CompositionRecorder` mode or a
            // non-ANGLE configuration in the `ProfilerScreenshots` mode. In either case, the
            // captured frames are right-side up.
            Box::new(src_buffer.chunks(src_stride))
        }
    }
}

// Screen-capture specific Renderer impls.
impl Renderer {
    /// Record a frame for the Composition Recorder.
    ///
    /// The returned handle can be passed to `map_recorded_frame` to copy it into
    /// a buffer.
    /// The returned size is the size of the frame.
    pub fn record_frame(
        &mut self,
        image_format: ImageFormat,
    ) -> Option<(RecordedFrameHandle, DeviceIntSize)> {
        let device_size = self.device_size()?;
        self.device.begin_frame();

        let (handle, _) = self
            .async_frame_recorder
            .get_or_insert_with(AsyncScreenshotGrabber::new_composition_recorder)
            .get_screenshot(
                &mut self.device,
                DeviceIntRect::new(DeviceIntPoint::new(0, 0), device_size),
                device_size,
                image_format,
            );

        self.device.end_frame();

        Some((RecordedFrameHandle(handle.0), device_size))
    }

    /// Map a frame captured for the composition recorder into the given buffer.
    pub fn map_recorded_frame(
        &mut self,
        handle: RecordedFrameHandle,
        dst_buffer: &mut [u8],
        dst_stride: usize,
    ) -> bool {
        if let Some(async_frame_recorder) = self.async_frame_recorder.as_mut() {
            async_frame_recorder.map_and_recycle_screenshot(
                &mut self.device,
                AsyncScreenshotHandle(handle.0),
                dst_buffer,
                dst_stride,
            )
        } else {
            false
        }
    }

    /// Free the data structures used by the composition recorder.
    pub fn release_composition_recorder_structures(&mut self) {
        if let Some(async_frame_recorder) = self.async_frame_recorder.take() {
            self.device.begin_frame();
            async_frame_recorder.deinit(&mut self.device);
            self.device.end_frame();
        }
    }

    /// Take a screenshot and scale it asynchronously.
    ///
    /// The returned handle can be used to access the mapped screenshot data via
    /// `map_and_recycle_screenshot`.
    ///
    /// The returned size is the size of the screenshot.
    pub fn get_screenshot_async(
        &mut self,
        window_rect: DeviceIntRect,
        buffer_size: DeviceIntSize,
        image_format: ImageFormat,
    ) -> (AsyncScreenshotHandle, DeviceIntSize) {
        self.device.begin_frame();

        let handle = self
            .async_screenshots
            .get_or_insert_with(AsyncScreenshotGrabber::default)
            .get_screenshot(&mut self.device, window_rect, buffer_size, image_format);

        self.device.end_frame();

        handle
    }

    /// Map the contents of the screenshot given by the handle and copy it into
    /// the given buffer.
    pub fn map_and_recycle_screenshot(
        &mut self,
        handle: AsyncScreenshotHandle,
        dst_buffer: &mut [u8],
        dst_stride: usize,
    ) -> bool {
        if let Some(async_screenshots) = self.async_screenshots.as_mut() {
            async_screenshots.map_and_recycle_screenshot(
                &mut self.device,
                handle,
                dst_buffer,
                dst_stride,
            )
        } else {
            false
        }
    }

    /// Release the screenshot grabbing structures that the profiler was using.
    pub fn release_profiler_structures(&mut self) {
        if let Some(async_screenshots) = self.async_screenshots.take() {
            self.device.begin_frame();
            async_screenshots.deinit(&mut self.device);
            self.device.end_frame();
        }
    }
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

//! Defines a bitmap, which is used to track which values in an Arrow array are null.
//! This is called a "validity bitmap" in the Arrow documentation.

use super::buffer::Buffer;
use crate::util::bit_util;

#[derive(PartialEq, Debug)]
pub struct Bitmap {
    pub(crate) bits: Buffer,
}

impl Bitmap {
    pub fn new(num_bits: usize) -> Self {
        let num_bytes = num_bits / 8 + if num_bits % 8 > 0 { 1 } else { 0 };
        let r = num_bytes % 64;
        let len = if r == 0 {
            num_bytes
        } else {
            num_bytes + 64 - r
        };
        let mut v = Vec::with_capacity(len);
        for _ in 0..len {
            v.push(255); // 1 is not null
        }
        Bitmap {
            bits: Buffer::from(&v[..]),
        }
    }

    pub fn len(&self) -> usize {
        self.bits.len()
    }

    pub fn is_set(&self, i: usize) -> bool {
        assert!(i < (self.bits.len() << 3));
        unsafe { bit_util::get_bit_raw(self.bits.raw_data(), i) }
    }
}

impl From<Buffer> for Bitmap {
    fn from(buf: Buffer) -> Self {
        Self { bits: buf }
    }
}

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

    #[test]
    fn test_bitmap_length() {
        assert_eq!(64, Bitmap::new(63 * 8).len());
        assert_eq!(64, Bitmap::new(64 * 8).len());
        assert_eq!(128, Bitmap::new(65 * 8).len());
    }

    #[test]
    fn test_bitmap_is_set() {
        let bitmap = Bitmap::from(Buffer::from([0b01001010]));
        assert_eq!(false, bitmap.is_set(0));
        assert_eq!(true, bitmap.is_set(1));
        assert_eq!(false, bitmap.is_set(2));
        assert_eq!(true, bitmap.is_set(3));
        assert_eq!(false, bitmap.is_set(4));
        assert_eq!(false, bitmap.is_set(5));
        assert_eq!(true, bitmap.is_set(6));
        assert_eq!(false, bitmap.is_set(7));
    }

}
<commit_msg>ARROW-4513: [Rust] Implement BitAnd/BitOr for &Bitmap<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

//! Defines a bitmap, which is used to track which values in an Arrow array are null.
//! This is called a "validity bitmap" in the Arrow documentation.

use super::buffer::Buffer;
use crate::util::bit_util;
use std::ops::{BitAnd, BitOr};

#[derive(PartialEq, Debug)]
pub struct Bitmap {
    pub(crate) bits: Buffer,
}

impl Bitmap {
    pub fn new(num_bits: usize) -> Self {
        let num_bytes = num_bits / 8 + if num_bits % 8 > 0 { 1 } else { 0 };
        let r = num_bytes % 64;
        let len = if r == 0 {
            num_bytes
        } else {
            num_bytes + 64 - r
        };
        let mut v = Vec::with_capacity(len);
        for _ in 0..len {
            v.push(255); // 1 is not null
        }
        Bitmap {
            bits: Buffer::from(&v[..]),
        }
    }

    pub fn len(&self) -> usize {
        self.bits.len()
    }

    pub fn is_set(&self, i: usize) -> bool {
        assert!(i < (self.bits.len() << 3));
        unsafe { bit_util::get_bit_raw(self.bits.raw_data(), i) }
    }
}

impl<'a, 'b> BitAnd<&'b Bitmap> for &'a Bitmap {
    type Output = Bitmap;

    fn bitand(self, rhs: &'b Bitmap) -> Bitmap {
        Bitmap::from(&self.bits & &rhs.bits)
    }
}

impl<'a, 'b> BitOr<&'b Bitmap> for &'a Bitmap {
    type Output = Bitmap;

    fn bitor(self, rhs: &'b Bitmap) -> Bitmap {
        Bitmap::from(&self.bits | &rhs.bits)
    }
}

impl From<Buffer> for Bitmap {
    fn from(buf: Buffer) -> Self {
        Self { bits: buf }
    }
}

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

    #[test]
    fn test_bitmap_length() {
        assert_eq!(64, Bitmap::new(63 * 8).len());
        assert_eq!(64, Bitmap::new(64 * 8).len());
        assert_eq!(128, Bitmap::new(65 * 8).len());
    }

    #[test]
    fn test_bitwise_and() {
        let bitmap1 = Bitmap::from(Buffer::from([0b01101010]));
        let bitmap2 = Bitmap::from(Buffer::from([0b01001110]));
        assert_eq!(
            Bitmap::from(Buffer::from([0b01001010])),
            &bitmap1 & &bitmap2
        );
    }

    #[test]
    fn test_bitwise_or() {
        let bitmap1 = Bitmap::from(Buffer::from([0b01101010]));
        let bitmap2 = Bitmap::from(Buffer::from([0b01001110]));
        assert_eq!(
            Bitmap::from(Buffer::from([0b01101110])),
            &bitmap1 | &bitmap2
        );
    }

    #[test]
    fn test_bitmap_is_set() {
        let bitmap = Bitmap::from(Buffer::from([0b01001010]));
        assert_eq!(false, bitmap.is_set(0));
        assert_eq!(true, bitmap.is_set(1));
        assert_eq!(false, bitmap.is_set(2));
        assert_eq!(true, bitmap.is_set(3));
        assert_eq!(false, bitmap.is_set(4));
        assert_eq!(false, bitmap.is_set(5));
        assert_eq!(true, bitmap.is_set(6));
        assert_eq!(false, bitmap.is_set(7));
    }

}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};

use std::env;
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <input>
       metadata comments <input>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_input: String,
  cmd_streaminfo: bool,
  cmd_comments: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
}

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    println!("Minimum block size: {} samples", info.min_block_size);
    println!("Maximum block size: {} samples", info.max_block_size);
  }

  if no_flags || args.flag_frame_size {
    println!("Minimum frame size: {} bytes", info.min_frame_size);
    println!("Maximum frame size: {} bytes", info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    println!("Sample rate: {} Hz", info.sample_rate);
  }

  if no_flags || args.flag_channels {
    println!("Number of channels: {}", info.channels);
  }

  if no_flags || args.flag_bits_per_sample {
    println!("Bits per sample: {}", info.bits_per_sample);
  }

  if no_flags || args.flag_total_samples {
    println!("Total samples: {}", info.total_samples);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    println!("MD5 sum: {}", md5);
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_input)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }
}
<commit_msg>Add implementation for VorbisComment printing<commit_after>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};
use flac::metadata::VorbisComment;

use std::env;
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <input>
       metadata comments <input>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_input: String,
  cmd_streaminfo: bool,
  cmd_comments: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
}

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    println!("Minimum block size: {} samples", info.min_block_size);
    println!("Maximum block size: {} samples", info.max_block_size);
  }

  if no_flags || args.flag_frame_size {
    println!("Minimum frame size: {} bytes", info.min_frame_size);
    println!("Maximum frame size: {} bytes", info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    println!("Sample rate: {} Hz", info.sample_rate);
  }

  if no_flags || args.flag_channels {
    println!("Number of channels: {}", info.channels);
  }

  if no_flags || args.flag_bits_per_sample {
    println!("Bits per sample: {}", info.bits_per_sample);
  }

  if no_flags || args.flag_total_samples {
    println!("Total samples: {}", info.total_samples);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    println!("MD5 sum: {}", md5);
  }
}

fn print_vorbis_comments(vorbis_comment: &VorbisComment) {
  let mut index = 1;

  println!("Vendor String: {}", vorbis_comment.vendor_string);
  println!("Number of Comments: {}", vorbis_comment.comments.len());

  for comment in &vorbis_comment.comments {
    println!("  {}: \"{}\" = {}", index, comment.0, comment.1);

    index += 1;
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_input)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }
}
<|endoftext|>