<commit_before>// Take a look at the license at the top of the repository in the LICENSE file.

use crate::ComponentExt;

use std::collections::HashMap;
use std::fs::{metadata, read_dir, File};
use std::io::Read;
use std::path::{Path, PathBuf};

#[doc = include_str!("../../md_doc/component.md")]
pub struct Component {
    temperature: f32,
    max: f32,
    critical: Option<f32>,
    label: String,
    input_file: PathBuf,
}

fn get_file_line(file: &Path, capacity: usize) -> Option<String> {
    let mut reader = String::with_capacity(capacity);
    if let Ok(mut f) = File::open(file) {
        if f.read_to_string(&mut reader).is_ok() {
            Some(reader)
        } else {
            None
        }
    } else {
        None
    }
}

fn is_file<T: AsRef<Path>>(path: T) -> bool {
    metadata(path).ok().map(|m| m.is_file()).unwrap_or(false)
}

fn append_files(components: &mut Vec<Component>, folder: &Path) {
    let mut matchings: HashMap<u32, Vec<String>> = HashMap::with_capacity(10);

    if let Ok(dir) = read_dir(folder) {
        for entry in dir.flatten() {
            let entry = entry.path();
            if entry.is_dir()
                || !entry
                    .file_name()
                    .and_then(|x| x.to_str())
                    .unwrap_or("")
                    .starts_with("temp")
            {
                continue;
            }
            if let Some(entry) = entry.file_name() {
                if let Some(entry) = entry.to_str() {
                    let mut parts = entry.split('_');
                    if let Some(Some(id)) = parts.next().map(|s| s[4..].parse::<u32>().ok()) {
                        matchings
                            .entry(id)
                            .or_insert_with(|| Vec::with_capacity(5))
                            .push(
                                parts
                                    .next()
                                    .map(|s| format!("_{}", s))
                                    .unwrap_or_else(String::new),
                            );
                    }
                }
            }
        }
        for (key, val) in &matchings {
            let mut found_input = None;
            let mut found_label = None;
            for (pos, v) in val.iter().enumerate() {
                match v.as_str() {
                    // raspberry has empty string for temperature input
                    "_input" | "" => {
                        found_input = Some(pos);
                    }
                    "_label" => {
                        found_label = Some(pos);
                    }
                    _ => {}
                }
            }
            if let (Some(_), Some(found_input)) = (found_label, found_input) {
                let mut p_label = folder.to_path_buf();
                let mut p_input = folder.to_path_buf();
                let mut p_crit = folder.to_path_buf();
                let mut p_max = folder.to_path_buf();

                p_label.push(&format!("temp{}_label", key));
                p_input.push(&format!("temp{}{}", key, val[found_input]));
                p_max.push(&format!("temp{}_max", key));
                p_crit.push(&format!("temp{}_crit", key));
                if is_file(&p_input) {
                    let label = get_file_line(p_label.as_path(), 10)
                        .unwrap_or_else(|| format!("Component {}", key)) // needed for raspberry pi
                        .replace('\n', "");
                    let max = get_file_line(p_max.as_path(), 10).map(|max| {
                        max.replace('\n', "").parse::<f32>().unwrap_or(100_000f32) / 1000f32
                    });
                    let crit = get_file_line(p_crit.as_path(), 10).map(|crit| {
                        crit.replace('\n', "").parse::<f32>().unwrap_or(100_000f32) / 1000f32
                    });
                    components.push(Component::new(label, p_input.as_path(), max, crit));
                }
            }
        }
    }
}

impl Component {
    /// Creates a new component with the given information.
    pub(crate) fn new(
        label: String,
        input_path: &Path,
        max: Option<f32>,
        critical: Option<f32>,
    ) -> Component {
        let mut c = Component {
            temperature: 0f32,
            label,
            input_file: input_path.to_path_buf(),
            max: max.unwrap_or(0.0),
            critical,
        };
        c.refresh();
        c
    }
}

impl ComponentExt for Component {
    fn temperature(&self) -> f32 {
        self.temperature
    }

    fn max(&self) -> f32 {
        self.max
    }

    fn critical(&self) -> Option<f32> {
        self.critical
    }

    fn label(&self) -> &str {
        &self.label
    }

    fn refresh(&mut self) {
        if let Some(content) = get_file_line(self.input_file.as_path(), 10) {
            self.temperature = content
                .replace('\n', "")
                .parse::<f32>()
                .unwrap_or(100_000f32)
                / 1000f32;
            if self.temperature > self.max {
                self.max = self.temperature;
            }
        }
    }
}

pub(crate) fn get_components() -> Vec<Component> {
    let mut components = Vec::with_capacity(10);
    if let Ok(dir) = read_dir(&Path::new("/sys/class/hwmon/")) {
        for entry in dir.flatten() {
            let entry = entry.path();
            if !entry.is_dir()
                || !entry
                    .file_name()
                    .and_then(|x| x.to_str())
                    .unwrap_or("")
                    .starts_with("hwmon")
            {
                continue;
            }
            append_files(&mut components, &entry);
        }
        components.sort_by(|c1, c2| c1.label.to_lowercase().cmp(&c2.label.to_lowercase()));
    }
    if is_file("/sys/class/thermal/thermal_zone0/temp") {
        // Specfic to raspberry pi.
        components.push(Component::new(
            "CPU".to_owned(),
            Path::new("/sys/class/thermal/thermal_zone0/temp"),
            None,
            None,
        ));
    }
    components
}
<commit_msg>Update Component::new argument to take a PathBuf instead of a Path<commit_after>// Take a look at the license at the top of the repository in the LICENSE file.

use crate::ComponentExt;

use std::collections::HashMap;
use std::fs::{metadata, read_dir, File};
use std::io::Read;
use std::path::{Path, PathBuf};

#[doc = include_str!("../../md_doc/component.md")]
pub struct Component {
    temperature: f32,
    max: f32,
    critical: Option<f32>,
    label: String,
    input_file: PathBuf,
}

fn get_file_line(file: &Path, capacity: usize) -> Option<String> {
    let mut reader = String::with_capacity(capacity);
    if let Ok(mut f) = File::open(file) {
        if f.read_to_string(&mut reader).is_ok() {
            Some(reader)
        } else {
            None
        }
    } else {
        None
    }
}

fn is_file<T: AsRef<Path>>(path: T) -> bool {
    metadata(path).ok().map(|m| m.is_file()).unwrap_or(false)
}

fn append_files(components: &mut Vec<Component>, folder: &Path) {
    let mut matchings: HashMap<u32, Vec<String>> = HashMap::with_capacity(10);

    if let Ok(dir) = read_dir(folder) {
        for entry in dir.flatten() {
            let entry = entry.path();
            if entry.is_dir()
                || !entry
                    .file_name()
                    .and_then(|x| x.to_str())
                    .unwrap_or("")
                    .starts_with("temp")
            {
                continue;
            }
            if let Some(entry) = entry.file_name() {
                if let Some(entry) = entry.to_str() {
                    let mut parts = entry.split('_');
                    if let Some(Some(id)) = parts.next().map(|s| s[4..].parse::<u32>().ok()) {
                        matchings
                            .entry(id)
                            .or_insert_with(|| Vec::with_capacity(5))
                            .push(
                                parts
                                    .next()
                                    .map(|s| format!("_{}", s))
                                    .unwrap_or_else(String::new),
                            );
                    }
                }
            }
        }
        for (key, val) in &matchings {
            let mut found_input = None;
            let mut found_label = None;
            for (pos, v) in val.iter().enumerate() {
                match v.as_str() {
                    // raspberry has empty string for temperature input
                    "_input" | "" => {
                        found_input = Some(pos);
                    }
                    "_label" => {
                        found_label = Some(pos);
                    }
                    _ => {}
                }
            }
            if let (Some(_), Some(found_input)) = (found_label, found_input) {
                let mut p_label = folder.to_path_buf();
                let mut p_input = folder.to_path_buf();
                let mut p_crit = folder.to_path_buf();
                let mut p_max = folder.to_path_buf();

                p_label.push(&format!("temp{}_label", key));
                p_input.push(&format!("temp{}{}", key, val[found_input]));
                p_max.push(&format!("temp{}_max", key));
                p_crit.push(&format!("temp{}_crit", key));
                if is_file(&p_input) {
                    let label = get_file_line(p_label.as_path(), 10)
                        .unwrap_or_else(|| format!("Component {}", key)) // needed for raspberry pi
                        .replace('\n', "");
                    let max = get_file_line(p_max.as_path(), 10).map(|max| {
                        max.replace('\n', "").parse::<f32>().unwrap_or(100_000f32) / 1000f32
                    });
                    let crit = get_file_line(p_crit.as_path(), 10).map(|crit| {
                        crit.replace('\n', "").parse::<f32>().unwrap_or(100_000f32) / 1000f32
                    });
                    components.push(Component::new(label, p_input, max, crit));
                }
            }
        }
    }
}

impl Component {
    /// Creates a new component with the given information.
    pub(crate) fn new(
        label: String,
        input_file: PathBuf,
        max: Option<f32>,
        critical: Option<f32>,
    ) -> Component {
        let mut c = Component {
            temperature: 0f32,
            label,
            input_file,
            max: max.unwrap_or(0.0),
            critical,
        };
        c.refresh();
        c
    }
}

impl ComponentExt for Component {
    fn temperature(&self) -> f32 {
        self.temperature
    }

    fn max(&self) -> f32 {
        self.max
    }

    fn critical(&self) -> Option<f32> {
        self.critical
    }

    fn label(&self) -> &str {
        &self.label
    }

    fn refresh(&mut self) {
        if let Some(content) = get_file_line(self.input_file.as_path(), 10) {
            self.temperature = content
                .replace('\n', "")
                .parse::<f32>()
                .unwrap_or(100_000f32)
                / 1000f32;
            if self.temperature > self.max {
                self.max = self.temperature;
            }
        }
    }
}

pub(crate) fn get_components() -> Vec<Component> {
    let mut components = Vec::with_capacity(10);
    if let Ok(dir) = read_dir(Path::new("/sys/class/hwmon/")) {
        for entry in dir.flatten() {
            let entry = entry.path();
            if !entry.is_dir()
                || !entry
                    .file_name()
                    .and_then(|x| x.to_str())
                    .unwrap_or("")
                    .starts_with("hwmon")
            {
                continue;
            }
            append_files(&mut components, &entry);
        }
        components.sort_by(|c1, c2| c1.label.to_lowercase().cmp(&c2.label.to_lowercase()));
    }
    if is_file("/sys/class/thermal/thermal_zone0/temp") {
        // Specfic to raspberry pi.
        components.push(Component::new(
            "CPU".to_owned(),
            Path::new("/sys/class/thermal/thermal_zone0/temp").to_path_buf(),
            None,
            None,
        ));
    }
    components
}
<|endoftext|>


<commit_before>// Copyright 2020 The Propverify authors
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// #![feature(cstring_from_vec_with_nul)]
#![cfg_attr(not(feature = "std"), no_std)]

// Traits for creating symbolic/abstract values
pub mod traits;
pub mod verifier;

#[cfg(feature = "std")]
pub mod utils {
    pub trait UnwrapOrReject {
        type Wrapped;
        fn unwrap_or_reject(self) -> Self::Wrapped;
    }

    impl<T, E> UnwrapOrReject for Result<T, E> {
        type Wrapped = T;
        fn unwrap_or_reject(self) -> Self::Wrapped {
            match self {
                Ok(x) => x,
                Err(_) => crate::verifier::reject(),
            }
        }
    }

    impl<T> UnwrapOrReject for Option<T> {
        type Wrapped = T;
        fn unwrap_or_reject(self) -> Self::Wrapped {
            match self {
                Some(x) => x,
                None => crate::verifier::reject(),
            }
        }
    }
}

// `use verfication_annotations::prelude::*`
pub mod prelude {
    pub use crate::traits::*;
    #[cfg(feature = "std")]
    pub use crate::utils::*;
    pub use crate::verifier;

    // Macros
    pub use crate::verifier::assert as verifier_assert;
    pub use crate::verifier::assert_eq as verifier_assert_eq;
    pub use crate::verifier::assert_ne as verifier_assert_ne;
    pub use crate::verifier::assume as verifier_assume;
    pub use crate::verifier::unreachable as verifier_unreachable;
}

// At the moment, the cargo-verify script does not support
// use of a separate test directory so, for now, we put
// the tests here.
#[cfg(all(test, feature = "std"))]
mod tests;
<commit_msg>Revert cstring_from_vec_with_nul - may break no_std???<commit_after>// Copyright 2020 The Propverify authors
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(cstring_from_vec_with_nul)]
#![cfg_attr(not(feature = "std"), no_std)]

// Traits for creating symbolic/abstract values
pub mod traits;
pub mod verifier;

#[cfg(feature = "std")]
pub mod utils {
    pub trait UnwrapOrReject {
        type Wrapped;
        fn unwrap_or_reject(self) -> Self::Wrapped;
    }

    impl<T, E> UnwrapOrReject for Result<T, E> {
        type Wrapped = T;
        fn unwrap_or_reject(self) -> Self::Wrapped {
            match self {
                Ok(x) => x,
                Err(_) => crate::verifier::reject(),
            }
        }
    }

    impl<T> UnwrapOrReject for Option<T> {
        type Wrapped = T;
        fn unwrap_or_reject(self) -> Self::Wrapped {
            match self {
                Some(x) => x,
                None => crate::verifier::reject(),
            }
        }
    }
}

// `use verfication_annotations::prelude::*`
pub mod prelude {
    pub use crate::traits::*;
    #[cfg(feature = "std")]
    pub use crate::utils::*;
    pub use crate::verifier;

    // Macros
    pub use crate::verifier::assert as verifier_assert;
    pub use crate::verifier::assert_eq as verifier_assert_eq;
    pub use crate::verifier::assert_ne as verifier_assert_ne;
    pub use crate::verifier::assume as verifier_assume;
    pub use crate::verifier::unreachable as verifier_unreachable;
}

// At the moment, the cargo-verify script does not support
// use of a separate test directory so, for now, we put
// the tests here.
#[cfg(all(test, feature = "std"))]
mod tests;
<|endoftext|>


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

/// Central registry of all information known about types.
/// At present this is very minimal; in future we should roll
/// known_types.rs into this and possibly other things as well.
#[derive(Default, Hash, Debug)]
pub struct TypeConfig {
    pod_requests: Vec<String>,
    allowlist: Vec<String>, // not TypeName as it may be funcs not types.
    blocklist: Vec<String>, // not TypeName as it may be funcs not types.
}

impl TypeConfig {
    pub fn new() -> Self {
        Self::default()
    }

    pub(crate) fn note_pod_request(&mut self, tn: String) {
        self.pod_requests.push(tn);
    }

    pub(crate) fn add_to_allowlist(&mut self, item: String) {
        self.allowlist.push(item);
    }

    pub(crate) fn add_to_blocklist(&mut self, item: String) {
        self.blocklist.push(item);
    }

    pub fn get_pod_requests(&self) -> &[String] {
        &self.pod_requests
    }

    pub fn allowlist(&self) -> impl Iterator<Item = &String> {
        self.allowlist.iter()
    }

    pub fn allowlist_is_empty(&self) -> bool {
        self.allowlist.is_empty()
    }

    /// Whether this type is on the allowlist specified by the user.
    ///
    /// A note on the allowlist handling in general. It's used in two places:
    /// 1) As directives to bindgen
    /// 2) After bindgen has generated code, to filter the APIs which
    ///    we pass to cxx.
    /// This second pass may seem redundant. But sometimes bindgen generates
    /// unnecessary stuff.
    pub fn is_on_allowlist(&self, cpp_name: &str) -> bool {
        self.allowlist.contains(&cpp_name.to_string())
    }

    pub fn is_on_blocklist(&self, cpp_name: &str) -> bool {
        self.blocklist.contains(&cpp_name.to_string())
    }

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

/// Configuration about types.
/// At present this is very minimal; in future we should roll
/// known_types.rs into this and possibly other things as well.
#[derive(Default, Hash, Debug)]
pub struct TypeConfig {
    pod_requests: Vec<String>,
    allowlist: Vec<String>, // not TypeName as it may be funcs not types.
    blocklist: Vec<String>, // not TypeName as it may be funcs not types.
}

impl TypeConfig {
    pub fn new() -> Self {
        Self::default()
    }

    pub(crate) fn note_pod_request(&mut self, tn: String) {
        self.pod_requests.push(tn);
    }

    pub(crate) fn add_to_allowlist(&mut self, item: String) {
        self.allowlist.push(item);
    }

    pub(crate) fn add_to_blocklist(&mut self, item: String) {
        self.blocklist.push(item);
    }

    pub fn get_pod_requests(&self) -> &[String] {
        &self.pod_requests
    }

    pub fn allowlist(&self) -> impl Iterator<Item = &String> {
        self.allowlist.iter()
    }

    pub fn allowlist_is_empty(&self) -> bool {
        self.allowlist.is_empty()
    }

    /// Whether this type is on the allowlist specified by the user.
    ///
    /// A note on the allowlist handling in general. It's used in two places:
    /// 1) As directives to bindgen
    /// 2) After bindgen has generated code, to filter the APIs which
    ///    we pass to cxx.
    /// This second pass may seem redundant. But sometimes bindgen generates
    /// unnecessary stuff.
    pub fn is_on_allowlist(&self, cpp_name: &str) -> bool {
        self.allowlist.contains(&cpp_name.to_string())
    }

    pub fn is_on_blocklist(&self, cpp_name: &str) -> bool {
        self.blocklist.contains(&cpp_name.to_string())
    }

    pub fn get_blocklist(&self) -> impl Iterator<Item = &String> {
        self.blocklist.iter()
    }
}
<|endoftext|>


<commit_before>use serde::{Serialize, Serializer};

use exonum::crypto::{PublicKey, Hash, HexValue};
use exonum::storage::{Map, List, Database, Result as StorageResult};
use exonum::blockchain::Blockchain;
use blockchain_explorer::{TransactionInfo, HexField};

use super::{Role,DigitalRightsTx, DigitalRightsBlockchain, ContentShare, Uuid, Fingerprint, Content, Contract};

impl Serialize for DigitalRightsTx {
    fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        let mut state;
        match *self {
            DigitalRightsTx::CreateOwner(ref tx) => {
                state = ser.serialize_struct("transaction", 3)?;
                ser.serialize_struct_elt(&mut state, "type", "create_owner")?;
                ser.serialize_struct_elt(&mut state, "name", tx.name())?;
                ser.serialize_struct_elt(&mut state, "pub_key", tx.pub_key().to_hex())?;
            }
            DigitalRightsTx::CreateDistributor(ref tx) => {
                state = ser.serialize_struct("transaction", 3)?;
                ser.serialize_struct_elt(&mut state, "type", "create_distributor")?;
                ser.serialize_struct_elt(&mut state, "name", tx.name())?;
                ser.serialize_struct_elt(&mut state, "pub_key", tx.pub_key().to_hex())?;
            }
            DigitalRightsTx::AddContent(ref tx) => {
                state = ser.serialize_struct("transaction", 8)?;
                ser.serialize_struct_elt(&mut state, "type", "create_distributor")?;
                ser.serialize_struct_elt(&mut state, "pub_key", tx.pub_key().to_hex())?;
                ser.serialize_struct_elt(&mut state, "fingerprint", tx.fingerprint().to_hex())?;
                ser.serialize_struct_elt(&mut state, "title", tx.title())?;
                ser.serialize_struct_elt(&mut state, "price_per_listen", tx.price_per_listen())?;
                ser.serialize_struct_elt(&mut state, "min_plays", tx.min_plays())?;
                ser.serialize_struct_elt(&mut state, "additional_conditions", tx.title())?;
                ser.serialize_struct_elt(&mut state, "owners", tx.owner_shares())?;
            }
            DigitalRightsTx::AddContract(ref tx) => {
                state = ser.serialize_struct("transaction", 3)?;
                ser.serialize_struct_elt(&mut state, "type", "add_contract")?;
                ser.serialize_struct_elt(&mut state, "distributor_id", tx.distributor_id())?;
                ser.serialize_struct_elt(&mut state, "fingerprint", tx.fingerprint().to_hex())?;
            }
            DigitalRightsTx::Report(ref tx) => {
                state = ser.serialize_struct("transaction", 8)?;
                ser.serialize_struct_elt(&mut state, "type", "report")?;
                ser.serialize_struct_elt(&mut state, "pub_key", tx.pub_key().to_hex())?;
                ser.serialize_struct_elt(&mut state, "uuid", tx.uuid().to_hex())?;
                ser.serialize_struct_elt(&mut state, "distributor_id", tx.distributor_id())?;
                ser.serialize_struct_elt(&mut state, "fingerprint", tx.fingerprint())?;
                ser.serialize_struct_elt(&mut state, "time", tx.time().sec)?;
                ser.serialize_struct_elt(&mut state, "plays", tx.plays())?;
                ser.serialize_struct_elt(&mut state, "comment", tx.comment())?;
            }
        }
        ser.serialize_struct_end(state)
    }
}

impl TransactionInfo for DigitalRightsTx {}

#[derive(Debug, Serialize)]
pub struct OwnerInfo {
    pub id: u16,
    pub role: &'static str,
    pub name: String,
    pub pub_key: HexField<PublicKey>,
    pub ownership: HexField<Hash>,
}

#[derive(Debug, Serialize)]
pub struct DistributorInfo {
    pub id: u16,
    pub role: &'static str,
    pub name: String,
    pub pub_key: HexField<PublicKey>,
    pub available_content: Vec<ContentInfo>,
    pub contracts: Vec<ContractInfo>,
    pub contracts_hash: HexField<Hash>,
}

#[derive(Debug, Serialize)]
pub struct ContentInfo {
    pub title: String,
    pub fingerprint: HexField<Fingerprint>,
    pub additional_conditions: String,
    pub price_per_listen: u64,
    pub min_plays: u64,
    pub distributors: Vec<u16>,
}

#[derive(Debug, Serialize)]
pub struct ContractInfo {
    pub fingerprint: HexField<Fingerprint>,
    pub plays: u64,
    pub amount: u64,
    pub reports_hash: HexField<Hash>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct NewContent {
    pub title: String,
    pub fingerprint: HexField<Fingerprint>,
    pub additional_conditions: String,
    pub price_per_listen: u64,
    pub min_plays: u64,
    pub owners: Vec<ContentShare>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct NewReport {
    pub uuid: HexField<Uuid>,
    pub fingerprint: HexField<Fingerprint>,
    pub time: u64,
    pub plays: u64,
    pub comment: String,
}

impl ContractInfo {
    pub fn new(contract: Contract) -> ContractInfo {
        ContractInfo {
            fingerprint: HexField(*contract.fingerprint()),
            plays: contract.plays(),
            amount: contract.amount(),
            reports_hash: HexField(*contract.reports_hash())
        }
    }
}

impl ContentInfo {
    pub fn new(fingerprint: Fingerprint, content: Content) -> ContentInfo {
        ContentInfo {
            title: content.title().to_string(),
            fingerprint: HexField(fingerprint),
            additional_conditions: content.additional_conditions().to_string(),
            price_per_listen: content.price_per_listen(),
            min_plays: content.min_plays(),
            distributors: content.distributors().into()
        }
    }
}

pub struct DigitalRightsApi<D: Database> {
    blockchain: DigitalRightsBlockchain<D>,
}

impl<D: Database> DigitalRightsApi<D> {
    pub fn new(b: DigitalRightsBlockchain<D>) -> DigitalRightsApi<D> {
        DigitalRightsApi { blockchain: b }
    }

    pub fn participant_id(&self, pub_key: &PublicKey) -> StorageResult<Option<Role>> {
        let view = self.blockchain.view();
        view.find_participant(pub_key)
    }

    pub fn owner_info(&self, id: u16) -> StorageResult<Option<OwnerInfo>> {
        let view = self.blockchain.view();
        if let Some(owner) = view.owners().get(id as u64)? {
            let info = OwnerInfo {
                id: id,
                role: "owner",
                name: owner.name().to_string(),
                pub_key: HexField(*owner.pub_key()),
                ownership: HexField(*owner.ownership_hash()),
            };
            Ok(Some(info))
        } else {
            Ok(None)
        }
    }

    pub fn distributor_info(&self, id: u16) -> StorageResult<Option<DistributorInfo>> {
        let view = self.blockchain.view();
        if let Some(distributor) = view.distributors().get(id as u64)? {
            let available_content = self.available_contents(id)?;
            let mut contracts = Vec::new();
            for contract in view.distributor_contracts(id).values()? {
                contracts.push(ContractInfo::new(contract));
            }

            let info = DistributorInfo {
                id: id,
                role: "distributor",
                name: distributor.name().to_string(),
                pub_key: HexField(*distributor.pub_key()),
                contracts_hash: HexField(*distributor.contracts_hash()),
                available_content: available_content,
                contracts: contracts,
            };
            Ok(Some(info))
        } else {
            Ok(None)
        }
    }

    pub fn available_contents(&self, distributor_id: u16) -> StorageResult<Vec<ContentInfo>> {
        let v = self.blockchain
            .view()
            .list_content()?
            .into_iter()
            .filter(|&(_, ref content)| !content.distributors().contains(&distributor_id))
            .map(|(fingerprint, content)| ContentInfo::new(fingerprint, content))
            .collect();
        Ok(v)
    }
}
<commit_msg>More information about owners and distributors<commit_after>use serde::{Serialize, Serializer};

use exonum::crypto::{PublicKey, Hash, HexValue};
use exonum::storage::{Map, List, Database, Result as StorageResult};
use exonum::blockchain::Blockchain;
use blockchain_explorer::{TransactionInfo, HexField};

use super::{Role,DigitalRightsTx, DigitalRightsBlockchain, ContentShare, Uuid, Fingerprint, Content, Contract, Report, Ownership};

impl Serialize for DigitalRightsTx {
    fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        let mut state;
        match *self {
            DigitalRightsTx::CreateOwner(ref tx) => {
                state = ser.serialize_struct("transaction", 3)?;
                ser.serialize_struct_elt(&mut state, "type", "create_owner")?;
                ser.serialize_struct_elt(&mut state, "name", tx.name())?;
                ser.serialize_struct_elt(&mut state, "pub_key", tx.pub_key().to_hex())?;
            }
            DigitalRightsTx::CreateDistributor(ref tx) => {
                state = ser.serialize_struct("transaction", 3)?;
                ser.serialize_struct_elt(&mut state, "type", "create_distributor")?;
                ser.serialize_struct_elt(&mut state, "name", tx.name())?;
                ser.serialize_struct_elt(&mut state, "pub_key", tx.pub_key().to_hex())?;
            }
            DigitalRightsTx::AddContent(ref tx) => {
                state = ser.serialize_struct("transaction", 8)?;
                ser.serialize_struct_elt(&mut state, "type", "create_distributor")?;
                ser.serialize_struct_elt(&mut state, "pub_key", tx.pub_key().to_hex())?;
                ser.serialize_struct_elt(&mut state, "fingerprint", tx.fingerprint().to_hex())?;
                ser.serialize_struct_elt(&mut state, "title", tx.title())?;
                ser.serialize_struct_elt(&mut state, "price_per_listen", tx.price_per_listen())?;
                ser.serialize_struct_elt(&mut state, "min_plays", tx.min_plays())?;
                ser.serialize_struct_elt(&mut state, "additional_conditions", tx.title())?;
                ser.serialize_struct_elt(&mut state, "owners", tx.owner_shares())?;
            }
            DigitalRightsTx::AddContract(ref tx) => {
                state = ser.serialize_struct("transaction", 3)?;
                ser.serialize_struct_elt(&mut state, "type", "add_contract")?;
                ser.serialize_struct_elt(&mut state, "distributor_id", tx.distributor_id())?;
                ser.serialize_struct_elt(&mut state, "fingerprint", tx.fingerprint().to_hex())?;
            }
            DigitalRightsTx::Report(ref tx) => {
                state = ser.serialize_struct("transaction", 8)?;
                ser.serialize_struct_elt(&mut state, "type", "report")?;
                ser.serialize_struct_elt(&mut state, "pub_key", tx.pub_key().to_hex())?;
                ser.serialize_struct_elt(&mut state, "uuid", tx.uuid().to_hex())?;
                ser.serialize_struct_elt(&mut state, "distributor_id", tx.distributor_id())?;
                ser.serialize_struct_elt(&mut state, "fingerprint", tx.fingerprint())?;
                ser.serialize_struct_elt(&mut state, "time", tx.time().sec)?;
                ser.serialize_struct_elt(&mut state, "plays", tx.plays())?;
                ser.serialize_struct_elt(&mut state, "comment", tx.comment())?;
            }
        }
        ser.serialize_struct_end(state)
    }
}

impl TransactionInfo for DigitalRightsTx {}

#[derive(Debug, Serialize)]
pub struct OwnerInfo {
    pub id: u16,
    pub role: &'static str,
    pub name: String,
    pub pub_key: HexField<PublicKey>,
    pub ownership_hash: HexField<Hash>,
    pub ownership: Vec<OwnershipInfo>,
}

#[derive(Debug, Serialize)]
pub struct DistributorInfo {
    pub id: u16,
    pub role: &'static str,
    pub name: String,
    pub pub_key: HexField<PublicKey>,
    pub available_content: Vec<ContentInfo>,
    pub contracts: Vec<ContractInfo>,
    pub contracts_hash: HexField<Hash>,
}

#[derive(Debug, Serialize)]
pub struct ContentInfo {
    pub title: String,
    pub fingerprint: HexField<Fingerprint>,
    pub additional_conditions: String,
    pub price_per_listen: u64,
    pub min_plays: u64,
    pub distributors: Vec<u16>,
}

#[derive(Debug, Serialize)]
pub struct ContractInfo {
    pub content: ContentInfo,
    pub plays: u64,
    pub amount: u64,
    pub reports_hash: HexField<Hash>,
    pub reports: Vec<ReportInfo>
}

#[derive(Debug, Serialize)]
pub struct OwnershipInfo {
    pub content: ContentInfo,
    pub plays: u64,
    pub amount: u64,
    pub reports_hash: HexField<Hash>,
    pub reports: Vec<ReportInfo>
}

#[derive(Debug, Serialize)]
pub struct ReportInfo {
    pub distributor_id: u16,
    pub fingerprint: HexField<Fingerprint>,
    pub time: u64,
    pub plays: u64,
    pub amount: u64,
    pub comment: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct NewContent {
    pub title: String,
    pub fingerprint: HexField<Fingerprint>,
    pub additional_conditions: String,
    pub price_per_listen: u64,
    pub min_plays: u64,
    pub owners: Vec<ContentShare>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct NewReport {
    pub uuid: HexField<Uuid>,
    pub fingerprint: HexField<Fingerprint>,
    pub time: u64,
    pub plays: u64,
    pub comment: String,
}

impl ContractInfo {
    pub fn new(contract: Contract, content: ContentInfo, reports: Vec<ReportInfo>) -> ContractInfo {
        ContractInfo {
            content: content,
            plays: contract.plays(),
            amount: contract.amount(),
            reports_hash: HexField(*contract.reports_hash()),
            reports: reports
        }
    }
}

impl OwnershipInfo {
    pub fn new(ownership: Ownership, content: ContentInfo, reports: Vec<ReportInfo>) -> OwnershipInfo {
        OwnershipInfo {
            content: content,
            plays: ownership.plays(),
            amount: ownership.amount(),
            reports_hash: HexField(*ownership.reports_hash()),
            reports: reports
        }
    }
}

impl ContentInfo {
    pub fn new(fingerprint: Fingerprint, content: Content) -> ContentInfo {
        ContentInfo {
            title: content.title().to_string(),
            fingerprint: HexField(fingerprint),
            additional_conditions: content.additional_conditions().to_string(),
            price_per_listen: content.price_per_listen(),
            min_plays: content.min_plays(),
            distributors: content.distributors().into()
        }
    }
}

impl ReportInfo {
    pub fn new(report: Report) -> ReportInfo {
        let time = report.time();
        let nsec = (time.sec as u64) * 1_000_000_000 + time.nsec as u64;
        ReportInfo {
            distributor_id: report.distributor_id(),
            fingerprint: HexField(*report.fingerprint()),
            time: nsec,
            plays: report.plays(),
            amount: report.amount(),
            comment: report.comment().into(),
        }
    }
}

pub struct DigitalRightsApi<D: Database> {
    blockchain: DigitalRightsBlockchain<D>,
}

impl<D: Database> DigitalRightsApi<D> {
    pub fn new(b: DigitalRightsBlockchain<D>) -> DigitalRightsApi<D> {
        DigitalRightsApi { blockchain: b }
    }

    pub fn participant_id(&self, pub_key: &PublicKey) -> StorageResult<Option<Role>> {
        let view = self.blockchain.view();
        view.find_participant(pub_key)
    }

    pub fn owner_info(&self, id: u16) -> StorageResult<Option<OwnerInfo>> {
        let view = self.blockchain.view();
        if let Some(owner) = view.owners().get(id as u64)? {
            let mut ownership = Vec::new();
            for owner_content in view.owner_contents(id).values()? {
                let fingerprint = owner_content.fingerprint().clone();
                let r = view.contents().get(&fingerprint)?.unwrap();
                let content = ContentInfo::new(fingerprint, r);
                let reports = self.find_reports(Role::Owner(id), &fingerprint)?;

                ownership.push(OwnershipInfo::new(owner_content, content, reports));
            }

            let info = OwnerInfo {
                id: id,
                role: "owner",
                name: owner.name().to_string(),
                pub_key: HexField(*owner.pub_key()),
                ownership_hash: HexField(*owner.ownership_hash()),
                ownership: ownership
            };
            Ok(Some(info))
        } else {
            Ok(None)
        }
    }

    pub fn distributor_info(&self, id: u16) -> StorageResult<Option<DistributorInfo>> {
        let view = self.blockchain.view();
        if let Some(distributor) = view.distributors().get(id as u64)? {
            let available_content = self.available_contents(id)?;
            let mut contracts = Vec::new();
            for contract in view.distributor_contracts(id).values()? {
                let fingerprint = contract.fingerprint().clone();
                let r = view.contents().get(&fingerprint)?.unwrap();
                let content = ContentInfo::new(fingerprint, r);
                let reports = self.find_reports(Role::Distributor(id), &fingerprint)?;

                contracts.push(ContractInfo::new(contract, content, reports));
            }

            let info = DistributorInfo {
                id: id,
                role: "distributor",
                name: distributor.name().to_string(),
                pub_key: HexField(*distributor.pub_key()),
                contracts_hash: HexField(*distributor.contracts_hash()),
                available_content: available_content,
                contracts: contracts,
            };
            Ok(Some(info))
        } else {
            Ok(None)
        }
    }

    pub fn available_contents(&self, distributor_id: u16) -> StorageResult<Vec<ContentInfo>> {
        let v = self.blockchain
            .view()
            .list_content()?
            .into_iter()
            .filter(|&(_, ref content)| !content.distributors().contains(&distributor_id))
            .map(|(fingerprint, content)| ContentInfo::new(fingerprint, content))
            .collect();
        Ok(v)
    }

    pub fn find_reports(&self, id: Role, fingerprint: &Fingerprint) -> StorageResult<Vec<ReportInfo>> {
        let view = self.blockchain.view();
        let uuids = match id {
            Role::Owner(id) => {
                view
                    .owner_reports(id, fingerprint)
                    .values()?
            }
            Role::Distributor(id) => {
                view
                    .distributor_reports(id, fingerprint)
                    .values()?
            }
        };

        let mut v = Vec::new();
        for uuid in uuids {
            let report = view.reports().get(&uuid)?.unwrap();
            v.push(ReportInfo::new(report));
        }
        Ok(v)
    }
}
<|endoftext|>


<commit_before>macro_rules! reverse_u16(
    ($field:expr) => (
        $field =
            (($field >> 8) & 0x00FF) |
            (($field << 8) & 0xFF00);
    )
)

macro_rules! reverse_u32(
    ($field:expr) => (
        $field =
            (($field >> 24) & 0x000000FF) |
            (($field >>  8) & 0x0000FF00) |
            (($field <<  8) & 0x00FF0000) |
            (($field << 24) & 0xFF000000);
    )
)

macro_rules! implement_endian(
    ($subject:ty, $this:ident, $body:block) => (
        impl Endian for $subject {
            #[cfg(target_endian="little")]
            fn with_big_endian(self) -> $subject {
                let mut $this = self; $body; $this
            }

            #[cfg(target_endian="big")]
            fn with_little_endian(self) -> $subject {
                let mut $this = self; $body; $this
            }
        }
    )
)

pub trait Endian {
    #[cfg(target_endian="little")]
    fn with_big_endian(self) -> Self;

    #[cfg(target_endian="big")]
    fn with_little_endian(self) -> Self;

    #[inline="always"]
    #[cfg(target_endian="little")]
    fn with_little_endian(self) -> Self { self }

    #[inline="always"]
    #[cfg(target_endian="big")]
    fn with_big_endian(self) -> Self { self }
}

pub static CFF_TAG: u32 = 0x4F54544F;

pub struct OffsetTable {
    pub tag: u32,
    pub table_count: u16,
    pub search_range: u16,
    pub entry_selector: u16,
    pub range_shift: u16,
}

implement_endian!(OffsetTable, this, {
    reverse_u32!(this.tag);
    reverse_u16!(this.table_count);
    reverse_u16!(this.search_range);
    reverse_u16!(this.entry_selector);
    reverse_u16!(this.range_shift);
})
<commit_msg>Implemented a new syntax for Endian<commit_after>#[inline="always"]
fn reverse_u16(value: u16) -> u16 {
    ((value >> 8) & 0x00FF) |
    ((value << 8) & 0xFF00)
}

#[inline="always"]
fn reverse_u32(value: u32) -> u32 {
    ((value >> 24) & 0x000000FF) |
    ((value >>  8) & 0x0000FF00) |
    ((value <<  8) & 0x00FF0000) |
    ((value << 24) & 0xFF000000)
}

pub trait Endian {
    #[cfg(target_endian="little")]
    fn with_big_endian(self) -> Self;

    #[cfg(target_endian="big")]
    fn with_little_endian(self) -> Self;

    #[inline="always"]
    #[cfg(target_endian="little")]
    fn with_little_endian(self) -> Self { self }

    #[inline="always"]
    #[cfg(target_endian="big")]
    fn with_big_endian(self) -> Self { self }
}

macro_rules! impl_endian(
    ($subject:ty, $($field:ident as $size:ident),*) => (
        impl Endian for $subject {
            #[cfg(target_endian="little")]
            fn with_big_endian(mut self) -> $subject {
                $(
                    self.$field = concat_idents!(reverse_, $size)(self.$field);
                )*
                self
            }

            #[cfg(target_endian="big")]
            fn with_little_endian(mut self) -> $subject {
                $(
                    self.$field = concat_idents!(reverse_, $size)(self.$field);
                )*
                self
            }
        }
    )
)

pub static CFF_TAG: u32 = 0x4F54544F;

pub struct OffsetTable {
    pub tag: u32,
    pub table_count: u16,
    pub search_range: u16,
    pub entry_selector: u16,
    pub range_shift: u16,
}

impl_endian!(OffsetTable,
    tag as u32,
    table_count as u16,
    search_range as u16,
    entry_selector as u16,
    range_shift as u16
)
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::num::Wrapping;
use std::sync::atomic::{fence, Ordering};

use sys_util::{GuestAddress, GuestMemory};

const VIRTQ_DESC_F_NEXT: u16 = 0x1;
const VIRTQ_DESC_F_WRITE: u16 = 0x2;
#[allow(dead_code)]
const VIRTQ_DESC_F_INDIRECT: u16 = 0x4;

/// An iterator over a single descriptor chain.  Not to be confused with AvailIter,
/// which iterates over the descriptor chain heads in a queue.
pub struct DescIter<'a> {
    next: Option<DescriptorChain<'a>>,
}

impl<'a> DescIter<'a> {
    /// Returns an iterator that only yields the readable descriptors in the chain.
    pub fn readable(self) -> impl Iterator<Item=DescriptorChain<'a>> {
        self.take_while(DescriptorChain::is_read_only)
    }

    /// Returns an iterator that only yields the writable descriptors in the chain.
    pub fn writable(self) -> impl Iterator<Item=DescriptorChain<'a>> {
        self.skip_while(DescriptorChain::is_read_only)
    }
}

impl<'a> Iterator for DescIter<'a> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(current) = self.next.take() {
            self.next = current.next_descriptor();
            Some(current)
        } else {
            None
        }
    }
}

/// A virtio descriptor chain.
#[derive(Clone)]
pub struct DescriptorChain<'a> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    queue_size: u16,
    ttl: u16, // used to prevent infinite chain cycles

    /// Index into the descriptor table
    pub index: u16,

    /// Guest physical address of device specific data
    pub addr: GuestAddress,

    /// Length of device specific data
    pub len: u32,

    /// Includes next, write, and indirect bits
    pub flags: u16,

    /// Index into the descriptor table of the next descriptor if flags has
    /// the next bit set
    pub next: u16,
}

impl<'a> DescriptorChain<'a> {
    fn checked_new(mem: &GuestMemory,
                   desc_table: GuestAddress,
                   queue_size: u16,
                   index: u16)
                   -> Option<DescriptorChain> {
        if index >= queue_size {
            return None;
        }

        let desc_head = match mem.checked_offset(desc_table, (index as u64) * 16) {
            Some(a) => a,
            None => return None,
        };
        // These reads can't fail unless Guest memory is hopelessly broken.
        let addr = GuestAddress(mem.read_obj_from_addr::<u64>(desc_head).unwrap() as u64);
        if mem.checked_offset(desc_head, 16).is_none() {
            return None;
        }
        let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8))
            .unwrap();
        let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12))
            .unwrap();
        let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14))
            .unwrap();
        let chain = DescriptorChain {
            mem: mem,
            desc_table: desc_table,
            queue_size: queue_size,
            ttl: queue_size,
            index: index,
            addr: addr,
            len: len,
            flags: flags,
            next: next,
        };

        if chain.is_valid() { Some(chain) } else { None }
    }

    fn is_valid(&self) -> bool {
        if self.mem
               .checked_offset(self.addr, self.len as u64)
               .is_none() {
            false
        } else if self.has_next() && self.next >= self.queue_size {
            false
        } else {
            true
        }
    }

    /// Gets if this descriptor chain has another descriptor chain linked after it.
    pub fn has_next(&self) -> bool {
        self.flags & VIRTQ_DESC_F_NEXT != 0 && self.ttl > 1
    }

    /// If the driver designated this as a write only descriptor.
    ///
    /// If this is false, this descriptor is read only.
    /// Write only means the the emulated device can write and the driver can read.
    pub fn is_write_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE != 0
    }

    /// If the driver designated this as a read only descriptor.
    ///
    /// If this is false, this descriptor is write only.
    /// Read only means the emulated device can read and the driver can write.
    pub fn is_read_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE == 0
    }

    /// Gets the next descriptor in this descriptor chain, if there is one.
    ///
    /// Note that this is distinct from the next descriptor chain returned by `AvailIter`, which is
    /// the head of the next _available_ descriptor chain.
    pub fn next_descriptor(&self) -> Option<DescriptorChain<'a>> {
        if self.has_next() {
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next)
                .map(|mut c| {
                         c.ttl = self.ttl - 1;
                         c
                     })
        } else {
            None
        }
    }

    /// Produces an iterator over all the descriptors in this chain.
    pub fn into_iter(self) -> DescIter<'a> {
        DescIter {
            next: Some(self),
        }
    }
}

/// Consuming iterator over all available descriptor chain heads in the queue.
pub struct AvailIter<'a, 'b> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    avail_ring: GuestAddress,
    next_index: Wrapping<u16>,
    last_index: Wrapping<u16>,
    queue_size: u16,
    next_avail: &'b mut Wrapping<u16>,
}

impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.next_index == self.last_index {
            return None;
        }

        let offset = (4 + (self.next_index.0 % self.queue_size) * 2) as usize;
        let avail_addr = match self.mem.checked_offset(self.avail_ring, offset as u64) {
            Some(a) => a,
            None => return None,
        };
        // This index is checked below in checked_new
        let desc_index: u16 = self.mem.read_obj_from_addr(avail_addr).unwrap();

        self.next_index += Wrapping(1);

        let ret =
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, desc_index);
        if ret.is_some() {
            *self.next_avail += Wrapping(1);
        }
        ret
    }
}

#[derive(Clone)]
/// A virtio queue's parameters.
pub struct Queue {
    /// The maximal size in elements offered by the device
    pub max_size: u16,

    /// The queue size in elements the driver selected
    pub size: u16,

    /// Inidcates if the queue is finished with configuration
    pub ready: bool,

    /// Guest physical address of the descriptor table
    pub desc_table: GuestAddress,

    /// Guest physical address of the available ring
    pub avail_ring: GuestAddress,

    /// Guest physical address of the used ring
    pub used_ring: GuestAddress,

    next_avail: Wrapping<u16>,
    next_used: Wrapping<u16>,
}

impl Queue {
    /// Constructs an empty virtio queue with the given `max_size`.
    pub fn new(max_size: u16) -> Queue {
        Queue {
            max_size: max_size,
            size: 0,
            ready: false,
            desc_table: GuestAddress(0),
            avail_ring: GuestAddress(0),
            used_ring: GuestAddress(0),
            next_avail: Wrapping(0),
            next_used: Wrapping(0),
        }
    }

    /// Return the actual size of the queue, as the driver may not set up a
    /// queue as big as the device allows.
    pub fn actual_size(&self) -> u16 {
        min(self.size, self.max_size)
    }

    pub fn is_valid(&self, mem: &GuestMemory) -> bool {
        let queue_size = self.actual_size() as usize;
        let desc_table = self.desc_table;
        let desc_table_size = 16 * queue_size;
        let avail_ring = self.avail_ring;
        let avail_ring_size = 6 + 2 * queue_size;
        let used_ring = self.used_ring;
        let used_ring_size = 6 + 8 * queue_size;
        if !self.ready {
            error!("attempt to use virtio queue that is not marked ready");
            false
        } else if self.size > self.max_size || self.size == 0 ||
                  (self.size & (self.size - 1)) != 0 {
            error!("virtio queue with invalid size: {}", self.size);
            false
        } else if desc_table
                      .checked_add(desc_table_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   desc_table.offset(),
                   desc_table_size);
            false
        } else if avail_ring
                      .checked_add(avail_ring_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   avail_ring.offset(),
                   avail_ring_size);
            false
        } else if used_ring
                      .checked_add(used_ring_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   used_ring.offset(),
                   used_ring_size);
            false
        } else {
            true
        }

    }

    /// A consuming iterator over all available descriptor chain heads offered by the driver.
    pub fn iter<'a, 'b>(&'b mut self, mem: &'a GuestMemory) -> AvailIter<'a, 'b> {
        if !self.is_valid(mem) {
            return AvailIter {
                       mem: mem,
                       desc_table: GuestAddress(0),
                       avail_ring: GuestAddress(0),
                       next_index: Wrapping(0),
                       last_index: Wrapping(0),
                       queue_size: 0,
                       next_avail: &mut self.next_avail,
                   };
        }
        let queue_size = self.actual_size();
        let avail_ring = self.avail_ring;

        let index_addr = mem.checked_offset(avail_ring, 2).unwrap();
        // Note that last_index has no invalid values
        let last_index: u16 = mem.read_obj_from_addr::<u16>(index_addr).unwrap();
        let queue_len = Wrapping(last_index) - self.next_avail;

        if queue_len.0 > queue_size {
            return AvailIter {
                mem: mem,
                desc_table: GuestAddress(0),
                avail_ring: GuestAddress(0),
                next_index: Wrapping(0),
                last_index: Wrapping(0),
                queue_size: 0,
                next_avail: &mut self.next_avail,
            };
        }

        AvailIter {
            mem: mem,
            desc_table: self.desc_table,
            avail_ring: avail_ring,
            next_index: self.next_avail,
            last_index: Wrapping(last_index),
            queue_size: queue_size,
            next_avail: &mut self.next_avail,
        }
    }

    /// Puts an available descriptor head into the used ring for use by the guest.
    pub fn add_used(&mut self, mem: &GuestMemory, desc_index: u16, len: u32) {
        if desc_index >= self.actual_size() {
            error!("attempted to add out of bounds descriptor to used ring: {}",
                   desc_index);
            return;
        }

        let used_ring = self.used_ring;
        let next_used = (self.next_used.0 % self.actual_size()) as usize;
        let used_elem = used_ring.unchecked_add((4 + next_used * 8) as u64);

        // These writes can't fail as we are guaranteed to be within the descriptor ring.
        mem.write_obj_at_addr(desc_index as u32, used_elem)
            .unwrap();
        mem.write_obj_at_addr(len as u32, used_elem.unchecked_add(4))
            .unwrap();

        self.next_used += Wrapping(1);

        // This fence ensures all descriptor writes are visible before the index update is.
        fence(Ordering::Release);

        mem.write_obj_at_addr(self.next_used.0 as u16, used_ring.unchecked_add(2))
            .unwrap();
    }
}
<commit_msg>virtio: set default queue size to maximum<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::num::Wrapping;
use std::sync::atomic::{fence, Ordering};

use sys_util::{GuestAddress, GuestMemory};

const VIRTQ_DESC_F_NEXT: u16 = 0x1;
const VIRTQ_DESC_F_WRITE: u16 = 0x2;
#[allow(dead_code)]
const VIRTQ_DESC_F_INDIRECT: u16 = 0x4;

/// An iterator over a single descriptor chain.  Not to be confused with AvailIter,
/// which iterates over the descriptor chain heads in a queue.
pub struct DescIter<'a> {
    next: Option<DescriptorChain<'a>>,
}

impl<'a> DescIter<'a> {
    /// Returns an iterator that only yields the readable descriptors in the chain.
    pub fn readable(self) -> impl Iterator<Item=DescriptorChain<'a>> {
        self.take_while(DescriptorChain::is_read_only)
    }

    /// Returns an iterator that only yields the writable descriptors in the chain.
    pub fn writable(self) -> impl Iterator<Item=DescriptorChain<'a>> {
        self.skip_while(DescriptorChain::is_read_only)
    }
}

impl<'a> Iterator for DescIter<'a> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(current) = self.next.take() {
            self.next = current.next_descriptor();
            Some(current)
        } else {
            None
        }
    }
}

/// A virtio descriptor chain.
#[derive(Clone)]
pub struct DescriptorChain<'a> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    queue_size: u16,
    ttl: u16, // used to prevent infinite chain cycles

    /// Index into the descriptor table
    pub index: u16,

    /// Guest physical address of device specific data
    pub addr: GuestAddress,

    /// Length of device specific data
    pub len: u32,

    /// Includes next, write, and indirect bits
    pub flags: u16,

    /// Index into the descriptor table of the next descriptor if flags has
    /// the next bit set
    pub next: u16,
}

impl<'a> DescriptorChain<'a> {
    fn checked_new(mem: &GuestMemory,
                   desc_table: GuestAddress,
                   queue_size: u16,
                   index: u16)
                   -> Option<DescriptorChain> {
        if index >= queue_size {
            return None;
        }

        let desc_head = match mem.checked_offset(desc_table, (index as u64) * 16) {
            Some(a) => a,
            None => return None,
        };
        // These reads can't fail unless Guest memory is hopelessly broken.
        let addr = GuestAddress(mem.read_obj_from_addr::<u64>(desc_head).unwrap() as u64);
        if mem.checked_offset(desc_head, 16).is_none() {
            return None;
        }
        let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8))
            .unwrap();
        let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12))
            .unwrap();
        let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14))
            .unwrap();
        let chain = DescriptorChain {
            mem: mem,
            desc_table: desc_table,
            queue_size: queue_size,
            ttl: queue_size,
            index: index,
            addr: addr,
            len: len,
            flags: flags,
            next: next,
        };

        if chain.is_valid() { Some(chain) } else { None }
    }

    fn is_valid(&self) -> bool {
        if self.mem
               .checked_offset(self.addr, self.len as u64)
               .is_none() {
            false
        } else if self.has_next() && self.next >= self.queue_size {
            false
        } else {
            true
        }
    }

    /// Gets if this descriptor chain has another descriptor chain linked after it.
    pub fn has_next(&self) -> bool {
        self.flags & VIRTQ_DESC_F_NEXT != 0 && self.ttl > 1
    }

    /// If the driver designated this as a write only descriptor.
    ///
    /// If this is false, this descriptor is read only.
    /// Write only means the the emulated device can write and the driver can read.
    pub fn is_write_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE != 0
    }

    /// If the driver designated this as a read only descriptor.
    ///
    /// If this is false, this descriptor is write only.
    /// Read only means the emulated device can read and the driver can write.
    pub fn is_read_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE == 0
    }

    /// Gets the next descriptor in this descriptor chain, if there is one.
    ///
    /// Note that this is distinct from the next descriptor chain returned by `AvailIter`, which is
    /// the head of the next _available_ descriptor chain.
    pub fn next_descriptor(&self) -> Option<DescriptorChain<'a>> {
        if self.has_next() {
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next)
                .map(|mut c| {
                         c.ttl = self.ttl - 1;
                         c
                     })
        } else {
            None
        }
    }

    /// Produces an iterator over all the descriptors in this chain.
    pub fn into_iter(self) -> DescIter<'a> {
        DescIter {
            next: Some(self),
        }
    }
}

/// Consuming iterator over all available descriptor chain heads in the queue.
pub struct AvailIter<'a, 'b> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    avail_ring: GuestAddress,
    next_index: Wrapping<u16>,
    last_index: Wrapping<u16>,
    queue_size: u16,
    next_avail: &'b mut Wrapping<u16>,
}

impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.next_index == self.last_index {
            return None;
        }

        let offset = (4 + (self.next_index.0 % self.queue_size) * 2) as usize;
        let avail_addr = match self.mem.checked_offset(self.avail_ring, offset as u64) {
            Some(a) => a,
            None => return None,
        };
        // This index is checked below in checked_new
        let desc_index: u16 = self.mem.read_obj_from_addr(avail_addr).unwrap();

        self.next_index += Wrapping(1);

        let ret =
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, desc_index);
        if ret.is_some() {
            *self.next_avail += Wrapping(1);
        }
        ret
    }
}

#[derive(Clone)]
/// A virtio queue's parameters.
pub struct Queue {
    /// The maximal size in elements offered by the device
    pub max_size: u16,

    /// The queue size in elements the driver selected
    pub size: u16,

    /// Inidcates if the queue is finished with configuration
    pub ready: bool,

    /// Guest physical address of the descriptor table
    pub desc_table: GuestAddress,

    /// Guest physical address of the available ring
    pub avail_ring: GuestAddress,

    /// Guest physical address of the used ring
    pub used_ring: GuestAddress,

    next_avail: Wrapping<u16>,
    next_used: Wrapping<u16>,
}

impl Queue {
    /// Constructs an empty virtio queue with the given `max_size`.
    pub fn new(max_size: u16) -> Queue {
        Queue {
            max_size: max_size,
            size: max_size,
            ready: false,
            desc_table: GuestAddress(0),
            avail_ring: GuestAddress(0),
            used_ring: GuestAddress(0),
            next_avail: Wrapping(0),
            next_used: Wrapping(0),
        }
    }

    /// Return the actual size of the queue, as the driver may not set up a
    /// queue as big as the device allows.
    pub fn actual_size(&self) -> u16 {
        min(self.size, self.max_size)
    }

    pub fn is_valid(&self, mem: &GuestMemory) -> bool {
        let queue_size = self.actual_size() as usize;
        let desc_table = self.desc_table;
        let desc_table_size = 16 * queue_size;
        let avail_ring = self.avail_ring;
        let avail_ring_size = 6 + 2 * queue_size;
        let used_ring = self.used_ring;
        let used_ring_size = 6 + 8 * queue_size;
        if !self.ready {
            error!("attempt to use virtio queue that is not marked ready");
            false
        } else if self.size > self.max_size || self.size == 0 ||
                  (self.size & (self.size - 1)) != 0 {
            error!("virtio queue with invalid size: {}", self.size);
            false
        } else if desc_table
                      .checked_add(desc_table_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   desc_table.offset(),
                   desc_table_size);
            false
        } else if avail_ring
                      .checked_add(avail_ring_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   avail_ring.offset(),
                   avail_ring_size);
            false
        } else if used_ring
                      .checked_add(used_ring_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   used_ring.offset(),
                   used_ring_size);
            false
        } else {
            true
        }

    }

    /// A consuming iterator over all available descriptor chain heads offered by the driver.
    pub fn iter<'a, 'b>(&'b mut self, mem: &'a GuestMemory) -> AvailIter<'a, 'b> {
        if !self.is_valid(mem) {
            return AvailIter {
                       mem: mem,
                       desc_table: GuestAddress(0),
                       avail_ring: GuestAddress(0),
                       next_index: Wrapping(0),
                       last_index: Wrapping(0),
                       queue_size: 0,
                       next_avail: &mut self.next_avail,
                   };
        }
        let queue_size = self.actual_size();
        let avail_ring = self.avail_ring;

        let index_addr = mem.checked_offset(avail_ring, 2).unwrap();
        // Note that last_index has no invalid values
        let last_index: u16 = mem.read_obj_from_addr::<u16>(index_addr).unwrap();
        let queue_len = Wrapping(last_index) - self.next_avail;

        if queue_len.0 > queue_size {
            return AvailIter {
                mem: mem,
                desc_table: GuestAddress(0),
                avail_ring: GuestAddress(0),
                next_index: Wrapping(0),
                last_index: Wrapping(0),
                queue_size: 0,
                next_avail: &mut self.next_avail,
            };
        }

        AvailIter {
            mem: mem,
            desc_table: self.desc_table,
            avail_ring: avail_ring,
            next_index: self.next_avail,
            last_index: Wrapping(last_index),
            queue_size: queue_size,
            next_avail: &mut self.next_avail,
        }
    }

    /// Puts an available descriptor head into the used ring for use by the guest.
    pub fn add_used(&mut self, mem: &GuestMemory, desc_index: u16, len: u32) {
        if desc_index >= self.actual_size() {
            error!("attempted to add out of bounds descriptor to used ring: {}",
                   desc_index);
            return;
        }

        let used_ring = self.used_ring;
        let next_used = (self.next_used.0 % self.actual_size()) as usize;
        let used_elem = used_ring.unchecked_add((4 + next_used * 8) as u64);

        // These writes can't fail as we are guaranteed to be within the descriptor ring.
        mem.write_obj_at_addr(desc_index as u32, used_elem)
            .unwrap();
        mem.write_obj_at_addr(len as u32, used_elem.unchecked_add(4))
            .unwrap();

        self.next_used += Wrapping(1);

        // This fence ensures all descriptor writes are visible before the index update is.
        fence(Ordering::Release);

        mem.write_obj_at_addr(self.next_used.0 as u16, used_ring.unchecked_add(2))
            .unwrap();
    }
}
<|endoftext|>


<commit_before>//! NVPTX intrinsics (experimental)
//!
//! These intrinsics form the foundation of the CUDA
//! programming model.
//!
//! The reference is the [CUDA C Programming Guide][cuda_c]. Relevant is also
//! the [LLVM NVPTX Backend documentation][llvm_docs].
//!
//! [cuda_c]:
//! http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html
//! [llvm_docs]:
//! https://llvm.org/docs/NVPTXUsage.html

#[cfg(test)]
use stdsimd_test::assert_instr;

#[allow(improper_ctypes)]
extern "C" {
    #[link_name = "llvm.nvvm.barrier0"]
    fn syncthreads() -> ();
    #[link_name = "llvm.nvvm.read.ptx.sreg.ntid.x"]
    fn block_dim_x() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.ntid.y"]
    fn block_dim_y() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.ntid.z"]
    fn block_dim_z() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.ctaid.x"]
    fn block_idx_x() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.ctaid.y"]
    fn block_idx_y() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.ctaid.z"]
    fn block_idx_z() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.nctaid.x"]
    fn grid_dim_x() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.nctaid.y"]
    fn grid_dim_y() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.nctaid.z"]
    fn grid_dim_z() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.tid.x"]
    fn thread_idx_x() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.tid.y"]
    fn thread_idx_y() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.tid.z"]
    fn thread_idx_z() -> i32;
}

/// Synchronizes all threads in the block.
#[inline]
pub unsafe fn _syncthreads() -> () {
    syncthreads()
}

/// x-th thread-block dimension.
#[inline]
pub unsafe fn _block_dim_x() -> i32 {
    block_dim_x()
}

/// y-th thread-block dimension.
#[inline]
pub unsafe fn _block_dim_y() -> i32 {
    block_dim_y()
}

/// z-th thread-block dimension.
#[inline]
pub unsafe fn _block_dim_z() -> i32 {
    block_dim_z()
}

/// x-th thread-block index.
#[inline]
pub unsafe fn _block_idx_x() -> i32 {
    block_idx_x()
}

/// y-th thread-block index.
#[inline]
pub unsafe fn _block_idx_y() -> i32 {
    block_idx_y()
}

/// z-th thread-block index.
#[inline]
pub unsafe fn _block_idx_z() -> i32 {
    block_idx_z()
}

/// x-th block-grid dimension.
#[inline]
pub unsafe fn _grid_dim_x() -> i32 {
    grid_dim_x()
}

/// y-th block-grid dimension.
#[inline]
pub unsafe fn _grid_dim_y() -> i32 {
    grid_dim_y()
}

/// z-th block-grid dimension.
#[inline]
pub unsafe fn _grid_dim_z() -> i32 {
    grid_dim_z()
}

/// x-th thread index.
#[inline]
pub unsafe fn _thread_idx_x() -> i32 {
    thread_idx_x()
}

/// y-th thread index.
#[inline]
pub unsafe fn _thread_idx_y() -> i32 {
    thread_idx_y()
}

/// z-th thread index.
#[inline]
pub unsafe fn _thread_idx_z() -> i32 {
    thread_idx_z()
}

/// Generates the trap instruction `TRAP`
#[inline]
pub unsafe fn trap() -> ! {
    ::_core::intrinsics::abort()
}
<commit_msg>remove extraneous import<commit_after>//! NVPTX intrinsics (experimental)
//!
//! These intrinsics form the foundation of the CUDA
//! programming model.
//!
//! The reference is the [CUDA C Programming Guide][cuda_c]. Relevant is also
//! the [LLVM NVPTX Backend documentation][llvm_docs].
//!
//! [cuda_c]:
//! http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html
//! [llvm_docs]:
//! https://llvm.org/docs/NVPTXUsage.html

#[allow(improper_ctypes)]
extern "C" {
    #[link_name = "llvm.nvvm.barrier0"]
    fn syncthreads() -> ();
    #[link_name = "llvm.nvvm.read.ptx.sreg.ntid.x"]
    fn block_dim_x() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.ntid.y"]
    fn block_dim_y() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.ntid.z"]
    fn block_dim_z() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.ctaid.x"]
    fn block_idx_x() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.ctaid.y"]
    fn block_idx_y() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.ctaid.z"]
    fn block_idx_z() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.nctaid.x"]
    fn grid_dim_x() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.nctaid.y"]
    fn grid_dim_y() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.nctaid.z"]
    fn grid_dim_z() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.tid.x"]
    fn thread_idx_x() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.tid.y"]
    fn thread_idx_y() -> i32;
    #[link_name = "llvm.nvvm.read.ptx.sreg.tid.z"]
    fn thread_idx_z() -> i32;
}

/// Synchronizes all threads in the block.
#[inline]
pub unsafe fn _syncthreads() -> () {
    syncthreads()
}

/// x-th thread-block dimension.
#[inline]
pub unsafe fn _block_dim_x() -> i32 {
    block_dim_x()
}

/// y-th thread-block dimension.
#[inline]
pub unsafe fn _block_dim_y() -> i32 {
    block_dim_y()
}

/// z-th thread-block dimension.
#[inline]
pub unsafe fn _block_dim_z() -> i32 {
    block_dim_z()
}

/// x-th thread-block index.
#[inline]
pub unsafe fn _block_idx_x() -> i32 {
    block_idx_x()
}

/// y-th thread-block index.
#[inline]
pub unsafe fn _block_idx_y() -> i32 {
    block_idx_y()
}

/// z-th thread-block index.
#[inline]
pub unsafe fn _block_idx_z() -> i32 {
    block_idx_z()
}

/// x-th block-grid dimension.
#[inline]
pub unsafe fn _grid_dim_x() -> i32 {
    grid_dim_x()
}

/// y-th block-grid dimension.
#[inline]
pub unsafe fn _grid_dim_y() -> i32 {
    grid_dim_y()
}

/// z-th block-grid dimension.
#[inline]
pub unsafe fn _grid_dim_z() -> i32 {
    grid_dim_z()
}

/// x-th thread index.
#[inline]
pub unsafe fn _thread_idx_x() -> i32 {
    thread_idx_x()
}

/// y-th thread index.
#[inline]
pub unsafe fn _thread_idx_y() -> i32 {
    thread_idx_y()
}

/// z-th thread index.
#[inline]
pub unsafe fn _thread_idx_z() -> i32 {
    thread_idx_z()
}

/// Generates the trap instruction `TRAP`
#[inline]
pub unsafe fn trap() -> ! {
    ::_core::intrinsics::abort()
}
<|endoftext|>


<commit_before>use crate::ram::types;

pub const CHUNK_SIZE: usize = 2048;

macro_rules! test_nums {
    (
        $t:ident, $io:ident
    ) => {
        mod $t {
            use super::CHUNK_SIZE;
            use crate::ram::chunk::Chunks;
            use crate::ram::types;
            use rand;
            use std;
            #[test]
            fn test() {
                let rand_num = rand::random::<$t>();
                let test_data = vec![
                    std::$t::MIN,
                    std::$t::MAX,
                    rand_num,
                    0 as $t,
                    1 as $t,
                    2 as $t,
                    127 as $t,
                ];
                let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
                let counts = CHUNK_SIZE / types::$io::size(0) as usize;
                let chunk_addr = chunk.segments()[0].addr;
                for d in test_data {
                    for i in 0..counts {
                        let addr = chunk_addr + i * types::$io::size(0);
                        types::$io::write(&d, addr);
                        assert_eq!(*types::$io::read(addr), d);
                    }
                    for i in 0..counts {
                        let addr = chunk_addr + i * types::$io::size(0);
                        assert!(*types::$io::read(addr) == d);
                    }
                }
            }
        }
    };
}

test_nums!(i8, i8_io);
test_nums!(i16, i16_io);
test_nums!(i32, i32_io);
test_nums!(i64, i64_io);

test_nums!(u8, u8_io);
test_nums!(u16, u16_io);
test_nums!(u32, u32_io);
test_nums!(u64, u64_io);

test_nums!(f32, f32_io);
test_nums!(f64, f64_io);

mod pos2d32 {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use rand;
    use std;
    #[test]
    fn test() {
        let test_data = vec![
            types::Pos2d32 {
                x: std::f32::MIN,
                y: std::f32::MAX,
            },
            types::Pos2d32 {
                x: rand::random::<f32>(),
                y: rand::random::<f32>(),
            },
        ];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let counts = CHUNK_SIZE / types::pos2d32_io::size(0) as usize;
        let chunk_addr = chunk.segments()[0].addr;
        for d in test_data {
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos2d32_io::size(0);
                types::pos2d32_io::write(&d, addr);
                assert_eq!(*types::pos2d32_io::read(addr), d);
            }
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos2d32_io::size(0);
                assert_eq!(*types::pos2d32_io::read(addr), d);
            }
        }
    }
}

mod pos2d64 {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use rand;
    use std;
    #[test]
    fn test() {
        let test_data = vec![
            types::Pos2d64 {
                x: std::f64::MIN,
                y: std::f64::MAX,
            },
            types::Pos2d64 {
                x: rand::random::<f64>(),
                y: rand::random::<f64>(),
            },
        ];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let counts = CHUNK_SIZE / types::pos2d64_io::size(0) as usize;
        let chunk_addr = chunk.segments()[0].addr;
        for d in test_data {
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos2d64_io::size(0);
                types::pos2d64_io::write(&d, addr);
                assert_eq!(*types::pos2d64_io::read(addr), d);
            }
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos2d64_io::size(0);
                assert_eq!(*types::pos2d64_io::read(addr), d);
            }
        }
    }
}

mod pos3d32 {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use rand;
    use std;
    #[test]
    fn test() {
        let test_data = vec![
            types::Pos3d32 {
                x: std::f32::MIN,
                y: std::f32::MAX,
                z: rand::random::<f32>(),
            },
            types::Pos3d32 {
                x: rand::random::<f32>(),
                y: rand::random::<f32>(),
                z: rand::random::<f32>(),
            },
        ];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let counts = CHUNK_SIZE / types::pos3d32_io::size(0) as usize;
        let chunk_addr = chunk.segments()[0].addr;
        for d in test_data {
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos3d32_io::size(0);
                types::pos3d32_io::write(&d, addr);
                assert_eq!(*types::pos3d32_io::read(addr), d);
            }
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos3d32_io::size(0);
                assert_eq!(*types::pos3d32_io::read(addr), d);
            }
        }
    }
}

mod pos3d64 {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use rand;
    use std;
    #[test]
    fn test() {
        let test_data = vec![
            types::Pos3d64 {
                x: std::f64::MIN,
                y: std::f64::MAX,
                z: rand::random::<f64>(),
            },
            types::Pos3d64 {
                x: rand::random::<f64>(),
                y: rand::random::<f64>(),
                z: rand::random::<f64>(),
            },
        ];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let counts = CHUNK_SIZE / types::pos3d64_io::size(0) as usize;
        let chunk_addr = chunk.segments()[0].addr;
        for d in test_data {
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos3d64_io::size(0);
                types::pos3d64_io::write(&d, addr);
                assert_eq!(*types::pos3d64_io::read(addr), d);
            }
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos3d64_io::size(0);
                assert_eq!(*types::pos3d64_io::read(addr), d);
            }
        }
    }
}

mod uuid {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use crate::ram::types::Id;
    #[test]
    fn test() {
        let test_data = vec![Id {
            higher: 1,
            lower: 2,
        }];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let counts = CHUNK_SIZE / types::id_io::size(0) as usize;
        let chunk_addr = chunk.segments()[0].addr;
        for d in test_data {
            for i in 0..counts {
                let addr = chunk_addr + i * types::id_io::size(0);
                types::id_io::write(&d, addr);
                assert_eq!(*types::id_io::read(addr), d);
            }
            for i in 0..counts {
                let addr = chunk_addr + i * types::id_io::size(0);
                assert_eq!(*types::id_io::read(addr), d);
            }
        }
    }
}

mod string {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use std::string::String;
    #[test]
    fn test() {
        let test_data = vec!["", "ಬಾ ಇಲ್ಲಿ ಸಂಭವಿಸ", "中文测试文本", "Hello Test", "🏳🌈"];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let mut addr = chunk.segments()[0].addr;
        for d in test_data.clone() {
            let test_str = String::from(d);
            types::string_io::write(&test_str, addr);
            let len = types::string_io::size(addr);
            let dec_str = types::string_io::read(addr);
            assert_eq!(dec_str, test_str);
            println!("{}", dec_str);
            addr += len;
        }
        addr = chunk.segments()[0].addr;
        for d in test_data.clone() {
            let test_str = String::from(d);
            let len = types::string_io::size(addr);
            assert_eq!(types::string_io::read(addr), test_str);
            addr += len;
        }
    }
}

#[test]
fn array_len_type() {
    assert_eq!(
        types::u32_io::size(0),
        types::get_size(types::ARRAY_LEN_TYPE_ID, 0)
    )
}

#[test]
fn null_type() {
    assert_eq!(
        types::u8_io::size(0),
        types::get_size(types::NULL_TYPE_ID, 0)
    )
}

#[test]
fn _in_map() {
    let mut map2 = types::OwnedMap::new();
    map2.insert(&String::from("a"), types::OwnedValue::I32(1));
    map2.insert(&String::from("b"), types::OwnedValue::I64(2));

    let mut map = types::OwnedMap::new();
    map.insert(&String::from("A"), types::OwnedValue::I32(1));
    map.insert(&String::from("B"), types::OwnedValue::Map(map2));

    assert_eq!(map.get(&String::from("A")).i32().unwrap(), &1);
    assert_eq!(map.get_in(&["B", "a"]).i32().unwrap(), &1);

    map.set_in(&["B", "a"], types::OwnedValue::I32(20)).unwrap();
    assert_eq!(map.get_in(&["B", "a"]).i32().unwrap(), &20);

    map.update_in(&["B", "b"], |value: &mut types::OwnedValue| {
        assert_eq!(value.i64().unwrap(), &2);
        *value = types::OwnedValue::U64(30);
    });
    assert_eq!(map.get_in(&["B", "b"]).i64().unwrap(), &30);
}

#[test]
fn index_mut_map() {
    let mut value = types::OwnedValue::Map(types::OwnedMap::new());
    value["a"] = types::OwnedValue::String(String::from("A"));
    value["b"] = types::OwnedValue::Array(vec![types::OwnedValue::U64(5)]);
    assert_eq!(value["a"].string().unwrap(), &String::from("A"));
    assert_eq!(value["b"][0 as usize].u64().unwrap(), &5);
    value["b"][0 as usize] = types::OwnedValue::U64(10);
    assert_eq!(value["b"][0 as usize].u64().unwrap(), &10);
}

#[test]
fn num_cast() {
    assert_eq!(1u32, 1u64 as u32);
}
<commit_msg>fix test<commit_after>use crate::ram::types;

pub const CHUNK_SIZE: usize = 2048;

macro_rules! test_nums {
    (
        $t:ident, $io:ident
    ) => {
        mod $t {
            use super::CHUNK_SIZE;
            use crate::ram::chunk::Chunks;
            use crate::ram::types;
            use rand;
            use std;
            #[test]
            fn test() {
                let rand_num = rand::random::<$t>();
                let test_data = vec![
                    std::$t::MIN,
                    std::$t::MAX,
                    rand_num,
                    0 as $t,
                    1 as $t,
                    2 as $t,
                    127 as $t,
                ];
                let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
                let counts = CHUNK_SIZE / types::$io::size(0) as usize;
                let chunk_addr = chunk.segments()[0].addr;
                for d in test_data {
                    for i in 0..counts {
                        let addr = chunk_addr + i * types::$io::size(0);
                        types::$io::write(&d, addr);
                        assert_eq!(*types::$io::read(addr), d);
                    }
                    for i in 0..counts {
                        let addr = chunk_addr + i * types::$io::size(0);
                        assert!(*types::$io::read(addr) == d);
                    }
                }
            }
        }
    };
}

test_nums!(i8, i8_io);
test_nums!(i16, i16_io);
test_nums!(i32, i32_io);
test_nums!(i64, i64_io);

test_nums!(u8, u8_io);
test_nums!(u16, u16_io);
test_nums!(u32, u32_io);
test_nums!(u64, u64_io);

test_nums!(f32, f32_io);
test_nums!(f64, f64_io);

mod pos2d32 {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use rand;
    use std;
    #[test]
    fn test() {
        let test_data = vec![
            types::Pos2d32 {
                x: std::f32::MIN,
                y: std::f32::MAX,
            },
            types::Pos2d32 {
                x: rand::random::<f32>(),
                y: rand::random::<f32>(),
            },
        ];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let counts = CHUNK_SIZE / types::pos2d32_io::size(0) as usize;
        let chunk_addr = chunk.segments()[0].addr;
        for d in test_data {
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos2d32_io::size(0);
                types::pos2d32_io::write(&d, addr);
                assert_eq!(*types::pos2d32_io::read(addr), d);
            }
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos2d32_io::size(0);
                assert_eq!(*types::pos2d32_io::read(addr), d);
            }
        }
    }
}

mod pos2d64 {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use rand;
    use std;
    #[test]
    fn test() {
        let test_data = vec![
            types::Pos2d64 {
                x: std::f64::MIN,
                y: std::f64::MAX,
            },
            types::Pos2d64 {
                x: rand::random::<f64>(),
                y: rand::random::<f64>(),
            },
        ];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let counts = CHUNK_SIZE / types::pos2d64_io::size(0) as usize;
        let chunk_addr = chunk.segments()[0].addr;
        for d in test_data {
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos2d64_io::size(0);
                types::pos2d64_io::write(&d, addr);
                assert_eq!(*types::pos2d64_io::read(addr), d);
            }
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos2d64_io::size(0);
                assert_eq!(*types::pos2d64_io::read(addr), d);
            }
        }
    }
}

mod pos3d32 {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use rand;
    use std;
    #[test]
    fn test() {
        let test_data = vec![
            types::Pos3d32 {
                x: std::f32::MIN,
                y: std::f32::MAX,
                z: rand::random::<f32>(),
            },
            types::Pos3d32 {
                x: rand::random::<f32>(),
                y: rand::random::<f32>(),
                z: rand::random::<f32>(),
            },
        ];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let counts = CHUNK_SIZE / types::pos3d32_io::size(0) as usize;
        let chunk_addr = chunk.segments()[0].addr;
        for d in test_data {
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos3d32_io::size(0);
                types::pos3d32_io::write(&d, addr);
                assert_eq!(*types::pos3d32_io::read(addr), d);
            }
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos3d32_io::size(0);
                assert_eq!(*types::pos3d32_io::read(addr), d);
            }
        }
    }
}

mod pos3d64 {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use rand;
    use std;
    #[test]
    fn test() {
        let test_data = vec![
            types::Pos3d64 {
                x: std::f64::MIN,
                y: std::f64::MAX,
                z: rand::random::<f64>(),
            },
            types::Pos3d64 {
                x: rand::random::<f64>(),
                y: rand::random::<f64>(),
                z: rand::random::<f64>(),
            },
        ];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let counts = CHUNK_SIZE / types::pos3d64_io::size(0) as usize;
        let chunk_addr = chunk.segments()[0].addr;
        for d in test_data {
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos3d64_io::size(0);
                types::pos3d64_io::write(&d, addr);
                assert_eq!(*types::pos3d64_io::read(addr), d);
            }
            for i in 0..counts {
                let addr = chunk_addr + i * types::pos3d64_io::size(0);
                assert_eq!(*types::pos3d64_io::read(addr), d);
            }
        }
    }
}

mod uuid {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use crate::ram::types::Id;
    #[test]
    fn test() {
        let test_data = vec![Id {
            higher: 1,
            lower: 2,
        }];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let counts = CHUNK_SIZE / types::id_io::size(0) as usize;
        let chunk_addr = chunk.segments()[0].addr;
        for d in test_data {
            for i in 0..counts {
                let addr = chunk_addr + i * types::id_io::size(0);
                types::id_io::write(&d, addr);
                assert_eq!(*types::id_io::read(addr), d);
            }
            for i in 0..counts {
                let addr = chunk_addr + i * types::id_io::size(0);
                assert_eq!(*types::id_io::read(addr), d);
            }
        }
    }
}

mod string {
    use super::CHUNK_SIZE;
    use crate::ram::chunk::Chunks;
    use crate::ram::types;
    use std::string::String;
    #[test]
    fn test() {
        let test_data = vec!["", "ಬಾ ಇಲ್ಲಿ ಸಂಭವಿಸ", "中文测试文本", "Hello Test", "🏳🌈"];
        let chunk = &Chunks::new_dummy(1, CHUNK_SIZE).list[0];
        let mut addr = chunk.segments()[0].addr;
        for d in test_data.clone() {
            let test_str = String::from(d);
            types::string_io::write(&test_str, addr);
            let len = types::string_io::size(addr);
            let dec_str = types::string_io::read(addr);
            assert_eq!(dec_str, test_str);
            println!("{}", dec_str);
            addr += len;
        }
        addr = chunk.segments()[0].addr;
        for d in test_data.clone() {
            let test_str = String::from(d);
            let len = types::string_io::size(addr);
            assert_eq!(types::string_io::read(addr), test_str);
            addr += len;
        }
    }
}

#[test]
fn array_len_type() {
    assert_eq!(
        types::u32_io::size(0),
        types::get_size(types::ARRAY_LEN_TYPE_ID, 0)
    )
}

#[test]
fn null_type() {
    assert_eq!(
        types::u8_io::size(0),
        types::get_size(types::NULL_TYPE_ID, 0)
    )
}

#[test]
fn _in_map() {
    let mut map2 = types::OwnedMap::new();
    map2.insert(&String::from("a"), types::OwnedValue::I32(1));
    map2.insert(&String::from("b"), types::OwnedValue::I64(2));

    let mut map = types::OwnedMap::new();
    map.insert(&String::from("A"), types::OwnedValue::I32(1));
    map.insert(&String::from("B"), types::OwnedValue::Map(map2));

    assert_eq!(map.get(&String::from("A")).i32().unwrap(), &1);
    assert_eq!(map.get_in(&["B", "a"]).i32().unwrap(), &1);

    map.set_in(&["B", "a"], types::OwnedValue::I32(20)).unwrap();
    assert_eq!(map.get_in(&["B", "a"]).i32().unwrap(), &20);

    map.update_in(&["B", "b"], |value: &mut types::OwnedValue| {
        assert_eq!(value.i64().unwrap(), &2);
        *value = types::OwnedValue::I64(30);
    });
    assert_eq!(map.get_in(&["B", "b"]).i64().unwrap(), &30);
}

#[test]
fn index_mut_map() {
    let mut value = types::OwnedValue::Map(types::OwnedMap::new());
    value["a"] = types::OwnedValue::String(String::from("A"));
    value["b"] = types::OwnedValue::Array(vec![types::OwnedValue::U64(5)]);
    assert_eq!(value["a"].string().unwrap(), &String::from("A"));
    assert_eq!(value["b"][0 as usize].u64().unwrap(), &5);
    value["b"][0 as usize] = types::OwnedValue::U64(10);
    assert_eq!(value["b"][0 as usize].u64().unwrap(), &10);
}

#[test]
fn num_cast() {
    assert_eq!(1u32, 1u64 as u32);
}
<|endoftext|>