<commit_before>//! Render output types and related functions.

use std::fmt;
use serde::de::{self, Deserialize, Deserializer, Visitor, Unexpected};
use serde::ser::{Serialize, Serializer};
use serde_derive::Serialize;

/// Output types.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
  Int(TypeChan),
  #[serde(rename = "uint")]
  UInt(TypeChan),
  Float(TypeChan),
  Bool(TypeChan)
}

/// Output type channels. Can be 1, 2, 3 or 4 channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub enum TypeChan {
  One,
  Two,
  Three,
  Four
}

impl Serialize for TypeChan {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
    match *self {
      TypeChan::One => serializer.serialize_u8(1),
      TypeChan::Two => serializer.serialize_u8(2),
      TypeChan::Three => serializer.serialize_u8(3),
      TypeChan::Four => serializer.serialize_u8(4),
    }
  }
}

impl<'de> Deserialize<'de> for TypeChan {
  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  where D: Deserializer<'de> {
    struct V;

    impl<'de> Visitor<'de> for V {
      type Value = TypeChan;

      fn expecting(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        f.write_str("a valid type channel")
      }

      fn visit_u64<E>(self, x: u64) -> Result<Self::Value, E> where E: de::Error {
        match x {
          1 => Ok(TypeChan::One),
          2 => Ok(TypeChan::Two),
          3 => Ok(TypeChan::Three),
          4 => Ok(TypeChan::Four),
          x => Err(E::invalid_value(Unexpected::Unsigned(x as u64), &"1, 2, 3 or 4"))
        }
      }
    }

    deserializer.deserialize_u64(V)
  }
}

/// Associate an output type to a given type.
pub trait Output {
  const OUTPUT: Type;
}

/// Render outputs.
pub trait Outputs {
  /// Get the types of the output.
  fn ty() -> &'static [Type];
}

impl<A> Outputs for A where A: Output {
  fn ty() -> &'static [Type] {
    &[A::OUTPUT]
  }
}

macro_rules! multi_output_impl {
  ($($t:tt),*) => {
    impl<$($t),*> Outputs for ($($t),*) where $($t: Output),* {
      fn ty() -> &'static [Type] {
        &[$($t::OUTPUT),*]
      }
    }
  }
}

multi_output_impl!(A, B);
multi_output_impl!(A, B, C);
multi_output_impl!(A, B, C, D);
multi_output_impl!(A, B, C, D, E);
multi_output_impl!(A, B, C, D, E, F);
multi_output_impl!(A, B, C, D, E, F, G);
multi_output_impl!(A, B, C, D, E, F, G, H);
multi_output_impl!(A, B, C, D, E, F, G, H, I);
multi_output_impl!(A, B, C, D, E, F, G, H, I, J);
multi_output_impl!(A, B, C, D, E, F, G, H, I, J, K);
multi_output_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

/// One-dimensional integral output a.k.a. red channel.
pub struct RI;

impl Output for RI {
  const OUTPUT: Type = Type::Int(TypeChan::One);
}

/// Two dimensional integral output a.k.a. red-green channels.
pub struct RGI;

impl Output for RGI {
  const OUTPUT: Type = Type::Int(TypeChan::Two);
}

/// Three dimensional integral output a.k.a. red-green-blue channels.
pub struct RGBI;

impl Output for RGBI {
  const OUTPUT: Type = Type::Int(TypeChan::Three);
}

/// Four dimensional integral output a.k.a. red-green-blue-alpha channels.
pub struct RGBAI;

impl Output for RGBAI {
  const OUTPUT: Type = Type::Int(TypeChan::Four);
}

/// One-dimensional unigned integral output a.k.a. red channel.
pub struct RU;

impl Output for RU {
  const OUTPUT: Type = Type::UInt(TypeChan::One);
}

/// Two dimensional unsigned integral output a.k.a. red-green channels.
pub struct RGU;

impl Output for RGU {
  const OUTPUT: Type = Type::UInt(TypeChan::Two);
}

/// Three dimensional unsigned integral output a.k.a. red-green-blue channels.
pub struct RGBU;

impl Output for RGBU {
  const OUTPUT: Type = Type::UInt(TypeChan::Three);
}

/// Four dimensional unsigned integral output a.k.a. red-green-blue-alpha channels.
pub struct RGBAU;

impl Output for RGBAU {
  const OUTPUT: Type = Type::UInt(TypeChan::Four);
}

/// One-dimensional floating output a.k.a. red channel.
pub struct RF;

impl Output for RF {
  const OUTPUT: Type = Type::Float(TypeChan::One);
}

/// Two dimensional floating output a.k.a. red-green channels.
pub struct RGF;

impl Output for RGF {
  const OUTPUT: Type = Type::Float(TypeChan::Two);
}

/// Three dimensional floating output a.k.a. red-green-blue channels.
pub struct RGBF;

impl Output for RGBF {
  const OUTPUT: Type = Type::Float(TypeChan::Three);
}

/// Four dimensional floating output a.k.a. red-green-blue-alpha channels.
pub struct RGBAF;

impl Output for RGBAF {
  const OUTPUT: Type = Type::Float(TypeChan::Four);
}

/// One-dimensional boolean output a.k.a. red channel.
pub struct RZ;

impl Output for RZ {
  const OUTPUT: Type = Type::Bool(TypeChan::One);
}

/// Two dimensional boolean output a.k.a. red-green channels.
pub struct RGZ;

impl Output for RGZ {
  const OUTPUT: Type = Type::Bool(TypeChan::Two);
}

/// Three dimensional boolean output a.k.a. red-green-blue channels.
pub struct RGBZ;

impl Output for RGBZ {
  const OUTPUT: Type = Type::Bool(TypeChan::Three);
}

/// Four dimensional boolean output a.k.a. red-green-blue-alpha channels.
pub struct RGBAZ;

impl Output for RGBAZ {
  const OUTPUT: Type = Type::Bool(TypeChan::Four);
}

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

  #[test]
  fn serialize_type_chan() {
    use serde_json::to_string;

    assert_eq!(to_string(&TypeChan::One).unwrap(), "1");
    assert_eq!(to_string(&TypeChan::Two).unwrap(), "2");
    assert_eq!(to_string(&TypeChan::Three).unwrap(),"3");
    assert_eq!(to_string(&TypeChan::Four).unwrap(), "4");
  }

  #[test]
  fn serialize_type() {
    use serde_json::to_string;

    assert_eq!(to_string(&RF::OUTPUT).unwrap(), "{\"float\":1}");
    assert_eq!(to_string(&RGF::OUTPUT).unwrap(), "{\"float\":2}");
    assert_eq!(to_string(&RGBF::OUTPUT).unwrap(), "{\"float\":3}");
    assert_eq!(to_string(&RGBAF::OUTPUT).unwrap(), "{\"float\":4}");
    assert_eq!(to_string(&RI::OUTPUT).unwrap(), "{\"int\":1}");
    assert_eq!(to_string(&RGI::OUTPUT).unwrap(), "{\"int\":2}");
    assert_eq!(to_string(&RGBI::OUTPUT).unwrap(), "{\"int\":3}");
    assert_eq!(to_string(&RGBAI::OUTPUT).unwrap(), "{\"int\":4}");
    assert_eq!(to_string(&RU::OUTPUT).unwrap(), "{\"uint\":1}");
    assert_eq!(to_string(&RGU::OUTPUT).unwrap(), "{\"uint\":2}");
    assert_eq!(to_string(&RGBU::OUTPUT).unwrap(), "{\"uint\":3}");
    assert_eq!(to_string(&RGBAU::OUTPUT).unwrap(), "{\"uint\":4}");
    assert_eq!(to_string(&RZ::OUTPUT).unwrap(), "{\"bool\":1}");
    assert_eq!(to_string(&RGZ::OUTPUT).unwrap(), "{\"bool\":2}");
    assert_eq!(to_string(&RGBZ::OUTPUT).unwrap(), "{\"bool\":3}");
    assert_eq!(to_string(&RGBAZ::OUTPUT).unwrap(), "{\"bool\":4}");
  }

  #[test]
  fn deserialize_type_chan() {
    use serde_json::from_str;

    assert_eq!(from_str::<TypeChan>("1").unwrap(), TypeChan::One);
    assert_eq!(from_str::<TypeChan>("2").unwrap(), TypeChan::Two);
    assert_eq!(from_str::<TypeChan>("3").unwrap(), TypeChan::Three);
    assert_eq!(from_str::<TypeChan>("4").unwrap(), TypeChan::Four);
    assert!(from_str::<TypeChan>("5").is_err());
  }

  #[test]
  fn deserialize_type() {
    use serde_json::from_str;

    assert_eq!(from_str::<TypeChan>("1").unwrap(), TypeChan::One);
    assert_eq!(from_str::<TypeChan>("2").unwrap(), TypeChan::Two);
    assert_eq!(from_str::<TypeChan>("3").unwrap(), TypeChan::Three);
    assert_eq!(from_str::<TypeChan>("4").unwrap(), TypeChan::Four);
  }
}
<commit_msg>Fix tests.<commit_after>//! Render output types and related functions.

use std::fmt;
use serde::de::{self, Deserialize, Deserializer, Visitor, Unexpected};
use serde::ser::{Serialize, Serializer};
use serde_derive::{Deserialize, Serialize};

/// Output types.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
  Int(TypeChan),
  #[serde(rename = "uint")]
  UInt(TypeChan),
  Float(TypeChan),
  Bool(TypeChan)
}

/// Output type channels. Can be 1, 2, 3 or 4 channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub enum TypeChan {
  One,
  Two,
  Three,
  Four
}

impl Serialize for TypeChan {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
    match *self {
      TypeChan::One => serializer.serialize_u8(1),
      TypeChan::Two => serializer.serialize_u8(2),
      TypeChan::Three => serializer.serialize_u8(3),
      TypeChan::Four => serializer.serialize_u8(4),
    }
  }
}

impl<'de> Deserialize<'de> for TypeChan {
  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  where D: Deserializer<'de> {
    struct V;

    impl<'de> Visitor<'de> for V {
      type Value = TypeChan;

      fn expecting(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        f.write_str("a valid type channel")
      }

      fn visit_u64<E>(self, x: u64) -> Result<Self::Value, E> where E: de::Error {
        match x {
          1 => Ok(TypeChan::One),
          2 => Ok(TypeChan::Two),
          3 => Ok(TypeChan::Three),
          4 => Ok(TypeChan::Four),
          x => Err(E::invalid_value(Unexpected::Unsigned(x as u64), &"1, 2, 3 or 4"))
        }
      }
    }

    deserializer.deserialize_u64(V)
  }
}

/// Associate an output type to a given type.
pub trait Output {
  const OUTPUT: Type;
}

/// Render outputs.
pub trait Outputs {
  /// Get the types of the output.
  fn ty() -> &'static [Type];
}

impl<A> Outputs for A where A: Output {
  fn ty() -> &'static [Type] {
    &[A::OUTPUT]
  }
}

macro_rules! multi_output_impl {
  ($($t:tt),*) => {
    impl<$($t),*> Outputs for ($($t),*) where $($t: Output),* {
      fn ty() -> &'static [Type] {
        &[$($t::OUTPUT),*]
      }
    }
  }
}

multi_output_impl!(A, B);
multi_output_impl!(A, B, C);
multi_output_impl!(A, B, C, D);
multi_output_impl!(A, B, C, D, E);
multi_output_impl!(A, B, C, D, E, F);
multi_output_impl!(A, B, C, D, E, F, G);
multi_output_impl!(A, B, C, D, E, F, G, H);
multi_output_impl!(A, B, C, D, E, F, G, H, I);
multi_output_impl!(A, B, C, D, E, F, G, H, I, J);
multi_output_impl!(A, B, C, D, E, F, G, H, I, J, K);
multi_output_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

/// One-dimensional integral output a.k.a. red channel.
pub struct RI;

impl Output for RI {
  const OUTPUT: Type = Type::Int(TypeChan::One);
}

/// Two dimensional integral output a.k.a. red-green channels.
pub struct RGI;

impl Output for RGI {
  const OUTPUT: Type = Type::Int(TypeChan::Two);
}

/// Three dimensional integral output a.k.a. red-green-blue channels.
pub struct RGBI;

impl Output for RGBI {
  const OUTPUT: Type = Type::Int(TypeChan::Three);
}

/// Four dimensional integral output a.k.a. red-green-blue-alpha channels.
pub struct RGBAI;

impl Output for RGBAI {
  const OUTPUT: Type = Type::Int(TypeChan::Four);
}

/// One-dimensional unigned integral output a.k.a. red channel.
pub struct RU;

impl Output for RU {
  const OUTPUT: Type = Type::UInt(TypeChan::One);
}

/// Two dimensional unsigned integral output a.k.a. red-green channels.
pub struct RGU;

impl Output for RGU {
  const OUTPUT: Type = Type::UInt(TypeChan::Two);
}

/// Three dimensional unsigned integral output a.k.a. red-green-blue channels.
pub struct RGBU;

impl Output for RGBU {
  const OUTPUT: Type = Type::UInt(TypeChan::Three);
}

/// Four dimensional unsigned integral output a.k.a. red-green-blue-alpha channels.
pub struct RGBAU;

impl Output for RGBAU {
  const OUTPUT: Type = Type::UInt(TypeChan::Four);
}

/// One-dimensional floating output a.k.a. red channel.
pub struct RF;

impl Output for RF {
  const OUTPUT: Type = Type::Float(TypeChan::One);
}

/// Two dimensional floating output a.k.a. red-green channels.
pub struct RGF;

impl Output for RGF {
  const OUTPUT: Type = Type::Float(TypeChan::Two);
}

/// Three dimensional floating output a.k.a. red-green-blue channels.
pub struct RGBF;

impl Output for RGBF {
  const OUTPUT: Type = Type::Float(TypeChan::Three);
}

/// Four dimensional floating output a.k.a. red-green-blue-alpha channels.
pub struct RGBAF;

impl Output for RGBAF {
  const OUTPUT: Type = Type::Float(TypeChan::Four);
}

/// One-dimensional boolean output a.k.a. red channel.
pub struct RZ;

impl Output for RZ {
  const OUTPUT: Type = Type::Bool(TypeChan::One);
}

/// Two dimensional boolean output a.k.a. red-green channels.
pub struct RGZ;

impl Output for RGZ {
  const OUTPUT: Type = Type::Bool(TypeChan::Two);
}

/// Three dimensional boolean output a.k.a. red-green-blue channels.
pub struct RGBZ;

impl Output for RGBZ {
  const OUTPUT: Type = Type::Bool(TypeChan::Three);
}

/// Four dimensional boolean output a.k.a. red-green-blue-alpha channels.
pub struct RGBAZ;

impl Output for RGBAZ {
  const OUTPUT: Type = Type::Bool(TypeChan::Four);
}

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

  #[test]
  fn serialize_type_chan() {
    use serde_json::to_string;

    assert_eq!(to_string(&TypeChan::One).unwrap(), "1");
    assert_eq!(to_string(&TypeChan::Two).unwrap(), "2");
    assert_eq!(to_string(&TypeChan::Three).unwrap(),"3");
    assert_eq!(to_string(&TypeChan::Four).unwrap(), "4");
  }

  #[test]
  fn serialize_type() {
    use serde_json::to_string;

    assert_eq!(to_string(&RF::OUTPUT).unwrap(), "{\"float\":1}");
    assert_eq!(to_string(&RGF::OUTPUT).unwrap(), "{\"float\":2}");
    assert_eq!(to_string(&RGBF::OUTPUT).unwrap(), "{\"float\":3}");
    assert_eq!(to_string(&RGBAF::OUTPUT).unwrap(), "{\"float\":4}");
    assert_eq!(to_string(&RI::OUTPUT).unwrap(), "{\"int\":1}");
    assert_eq!(to_string(&RGI::OUTPUT).unwrap(), "{\"int\":2}");
    assert_eq!(to_string(&RGBI::OUTPUT).unwrap(), "{\"int\":3}");
    assert_eq!(to_string(&RGBAI::OUTPUT).unwrap(), "{\"int\":4}");
    assert_eq!(to_string(&RU::OUTPUT).unwrap(), "{\"uint\":1}");
    assert_eq!(to_string(&RGU::OUTPUT).unwrap(), "{\"uint\":2}");
    assert_eq!(to_string(&RGBU::OUTPUT).unwrap(), "{\"uint\":3}");
    assert_eq!(to_string(&RGBAU::OUTPUT).unwrap(), "{\"uint\":4}");
    assert_eq!(to_string(&RZ::OUTPUT).unwrap(), "{\"bool\":1}");
    assert_eq!(to_string(&RGZ::OUTPUT).unwrap(), "{\"bool\":2}");
    assert_eq!(to_string(&RGBZ::OUTPUT).unwrap(), "{\"bool\":3}");
    assert_eq!(to_string(&RGBAZ::OUTPUT).unwrap(), "{\"bool\":4}");
  }

  #[test]
  fn deserialize_type_chan() {
    use serde_json::from_str;

    assert_eq!(from_str::<TypeChan>("1").unwrap(), TypeChan::One);
    assert_eq!(from_str::<TypeChan>("2").unwrap(), TypeChan::Two);
    assert_eq!(from_str::<TypeChan>("3").unwrap(), TypeChan::Three);
    assert_eq!(from_str::<TypeChan>("4").unwrap(), TypeChan::Four);
    assert!(from_str::<TypeChan>("5").is_err());
  }

  #[test]
  fn deserialize_type() {
    use serde_json::from_str;

    assert_eq!(from_str::<Type>("{\"float\":1}").unwrap(), RF::OUTPUT);
    assert_eq!(from_str::<Type>("{\"float\":2}").unwrap(), RGF::OUTPUT);
    assert_eq!(from_str::<Type>("{\"float\":3}").unwrap(), RGBF::OUTPUT);
    assert_eq!(from_str::<Type>("{\"float\":4}").unwrap(), RGBAF::OUTPUT);
    assert_eq!(from_str::<Type>("{\"int\":1}").unwrap(), RI::OUTPUT);
    assert_eq!(from_str::<Type>("{\"int\":2}").unwrap(), RGI::OUTPUT);
    assert_eq!(from_str::<Type>("{\"int\":3}").unwrap(), RGBI::OUTPUT);
    assert_eq!(from_str::<Type>("{\"int\":4}").unwrap(), RGBAI::OUTPUT);
    assert_eq!(from_str::<Type>("{\"uint\":1}").unwrap(), RU::OUTPUT);
    assert_eq!(from_str::<Type>("{\"uint\":2}").unwrap(), RGU::OUTPUT);
    assert_eq!(from_str::<Type>("{\"uint\":3}").unwrap(), RGBU::OUTPUT);
    assert_eq!(from_str::<Type>("{\"uint\":4}").unwrap(), RGBAU::OUTPUT);
    assert_eq!(from_str::<Type>("{\"bool\":1}").unwrap(), RZ::OUTPUT);
    assert_eq!(from_str::<Type>("{\"bool\":2}").unwrap(), RGZ::OUTPUT);
    assert_eq!(from_str::<Type>("{\"bool\":3}").unwrap(), RGBZ::OUTPUT);
    assert_eq!(from_str::<Type>("{\"bool\":4}").unwrap(), RGBAZ::OUTPUT);
  }
}
<|endoftext|>


<commit_before>use std::io;
use std::cmp::PartialEq;
use std::fmt:: { Display, Formatter, Result };
use std::collections::btree_map:: { BTreeMap };
use std::convert::{ From };
use lcov_parser:: { BranchData };
use merger::ops:: { TryMerge, MergeResult, MergeBranch, BranchError };
use record:: { RecordWrite };
use report::summary:: { Summary };
use report::attribute:: { LineNumber, ExecutionCount };
use report::counter:: { Hit, HitFoundCounter, FoundCounter, HitCounter };

/// Units of the branch
///
/// # Examples
///
/// ```
/// use lcov_merge::branch::BranchUnit;
///
/// let branch1 = BranchUnit::new(1, 1);
/// let branch2 = BranchUnit::new(1, 1);
///
/// assert!(branch1 == branch2);
///
/// let not_eq_branch1 = BranchUnit::new(1, 1);
/// let not_eq_branch2 = BranchUnit::new(1, 2);
///
/// assert!(not_eq_branch1 != not_eq_branch2);
/// ```
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone)]
pub struct BranchUnit(u32, u32);

impl BranchUnit {
    pub fn new(block: u32, branch: u32) -> BranchUnit {
        BranchUnit(block, branch)
    }
    pub fn block(&self) -> &u32 {
        &self.0
    }
    pub fn branch(&self) -> &u32 {
        &self.1
    }
}

impl Display for BranchUnit {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}-{}", self.0, self.1)
    }
}

#[derive(Debug, Clone)]
pub struct Branch {
    line_number: LineNumber,
    block: u32,
    branch: u32,
    execution_count: ExecutionCount
}

impl Branch {
    pub fn new(
        line_number: LineNumber,
        block: u32,
        branch: u32,
        execution_count: ExecutionCount
    ) -> Self {
        Branch {
            line_number: line_number,
            block: block,
            branch: branch,
            execution_count: execution_count
        }
    }
    pub fn line_number(&self) -> &LineNumber {
        &self.line_number
    }
    pub fn block(&self) -> &u32 {
        &self.block
    }
    pub fn branch(&self) -> &u32 {
        &self.branch
    }
    pub fn execution_count(&self) -> &ExecutionCount {
        &self.execution_count
    }
}

impl PartialEq<BranchData> for Branch {
    fn eq(&self, data: &BranchData) -> bool {
        if self.line_number != data.line {
            return false;
        }
        let branch_matched = self.block == data.block && self.branch == data.branch;

        if !branch_matched {
            return false;
        }
        return true;
    }
}

impl PartialEq<Branch> for Branch {
    fn eq(&self, other: &Branch) -> bool {
        if self.line_number != *other.line_number() {
            return false;
        }
        let branch_matched = self.block == *other.block() && self.branch == *other.branch();

        if !branch_matched {
            return false;
        }
        return true;
    }
}

impl<'a> From<&'a BranchData> for Branch {
    fn from(data: &'a BranchData) -> Self {
        Branch::new(
            data.line,
            data.block,
            data.branch,
            data.taken
        )
    }
}

impl<'a> TryMerge<&'a BranchData> for Branch {
    type Err = BranchError;

    fn try_merge(&mut self, data: &'a BranchData) -> MergeResult<Self::Err> {
        if self != data {
            return Err(
                BranchError::Mismatch(
                    MergeBranch::from(&self.clone()),
                    MergeBranch::from(data)
                )
            );
        }
        self.execution_count += data.taken;
        Ok(())
    }
}

impl<'a> TryMerge<&'a Branch> for Branch {
    type Err = BranchError;

    fn try_merge(&mut self, other: &'a Branch) -> MergeResult<Self::Err> {
        if self != other {
            return Err(
                BranchError::Mismatch(
                    MergeBranch::from(&self.clone()),
                    MergeBranch::from(other)
                )
            );
        }
        self.execution_count += *other.execution_count();
        Ok(())
    }
}

impl Hit for Branch {
    fn is_hit(&self) -> bool {
        self.execution_count.is_hit()
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct BranchBlocks {
    blocks: BTreeMap<BranchUnit, Branch>
}

impl BranchBlocks {
    pub fn new() -> Self {
        BranchBlocks {
            blocks: BTreeMap::new()
        }
    }
}

impl_summary!(BranchBlocks, blocks<BranchUnit, Branch>);

impl HitCounter for BranchBlocks {
    fn hit_count(&self) -> usize {
        self.iter()
            .filter(|&(_, branch)| branch.is_hit())
            .count()
    }
}

impl FoundCounter for BranchBlocks {
    fn found_count(&self) -> usize {
        self.blocks.len()
    }
}

impl HitFoundCounter for BranchBlocks {}

impl<'a> TryMerge<&'a BranchData> for BranchBlocks {
    type Err = BranchError;

    fn try_merge(&mut self, data: &'a BranchData) -> MergeResult<Self::Err> {
        let unit = BranchUnit::new(data.block, data.branch);
        if !self.blocks.contains_key(&unit) {
            self.blocks.insert(unit, Branch::from(data));
            return Ok(());
        }
        let mut block = self.blocks.get_mut(&unit).unwrap();
        block.try_merge(data)
    }
}

impl_try_merge_self_summary!(BranchBlocks:blocks, BranchError);

#[derive(Debug, Clone)]
pub struct Branches {
    branches: BTreeMap<LineNumber, BranchBlocks>
}

impl Branches {
    pub fn new() -> Self {
        Branches {
            branches: BTreeMap::new()
        }
    }
}

impl HitCounter for Branches {
    fn hit_count(&self) -> usize {
        self.iter()
            .map(|(_, blocks)| blocks.hit_count() )
            .fold(0, |p, n| p + n)
    }
}

impl FoundCounter for Branches {
    fn found_count(&self) -> usize {
        self.iter()
            .map(|(_, blocks)| blocks.found_count() )
            .fold(0, |p, n| p + n)
    }
}

impl HitFoundCounter for Branches {}

impl_summary!(Branches, branches<LineNumber, BranchBlocks>);

impl RecordWrite for Branches {
    fn write_records<T: io::Write>(&self, output: &mut T) -> io::Result<()> {
        write!(output, "{}", self)
    }
}

impl Display for Branches {
    fn fmt(&self, f: &mut Formatter) -> Result {
        if self.is_empty() {
            return Ok(());
        }
        for (line_number, blocks) in self.iter() {
            for (_, branch) in blocks.iter() {
                try!(writeln!(f, "BRDA:{},{},{},{}",
                    line_number, branch.block(), branch.branch(), branch.execution_count()));
            }
        }
        try!(writeln!(f, "BRF:{}", self.found_count()));
        try!(writeln!(f, "BRH:{}", self.hit_count()));
        Ok(())
    }
}

impl_try_merge_self_summary!(Branches:branches, BranchError);

impl<'a> TryMerge<&'a BranchData> for Branches {
    type Err = BranchError;

    fn try_merge(&mut self, data: &'a BranchData) -> MergeResult<Self::Err> {
        if self.branches.contains_key(&data.line) {
            let mut blocks = self.branches.get_mut(&data.line).unwrap();
            blocks.try_merge(data)
        } else {
            let blocks = {
                let mut blocks = BranchBlocks::new();
                let _ = try!(blocks.try_merge(data));
                blocks
            };
            self.branches.insert(
                data.line.clone(),
                blocks
            );
            Ok(())
        }
    }
}

#[cfg(test)]
mod tests {
    use std::collections:: { HashMap };
    use lcov_parser:: { BranchData };
    use merger::ops::*;
    use report::branch:: { Branch, BranchUnit, Branches, BranchBlocks };
    use report::summary:: { Summary };
    use report::counter:: { FoundCounter, HitCounter };

    #[test]
    fn branch_unit() {
        let branch1 = BranchUnit(1, 1);
        let branch2 = BranchUnit(1, 2);

        assert!(branch1 != branch2);

        let same_branch1 = BranchUnit(1, 1);
        let same_branch2 = BranchUnit(1, 1);

        assert_eq!(same_branch1, same_branch2);
    }

    #[test]
    fn branch_unit_as_hash_key() {
        let mut container = HashMap::new();
        container.insert(BranchUnit(1, 1), 1);

        assert!( container.contains_key(&BranchUnit(1, 1)) );
    }

    #[test]
    fn add_branch_data() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };

        branches.try_merge(b1).unwrap();
        branches.try_merge(b2).unwrap();

        let branch = Branch::new(1, 0, 1, 2);
        assert_eq!(branches.get(&BranchUnit::new(0, 1)), Some(&branch));
    }

    #[test]
    fn append_branches() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };

        branches.try_merge(b1).unwrap();
        branches.try_merge(b2).unwrap();

        let cloned_branches = branches.clone();
        branches.try_merge(&cloned_branches).unwrap();

        let branch = Branch::new(1, 0, 1, 2);
        assert_eq!(branches.get(&BranchUnit::new(0, 1)), Some(&branch));
    }

    #[test]
    fn branch_blocks_hit_count_and_found_count() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 2, taken: 0 };

        branches.try_merge(b1).unwrap();
        branches.try_merge(b2).unwrap();

        assert_eq!(branches.hit_count(), 1);
        assert_eq!(branches.found_count(), 2);
    }

    #[test]
    fn branches_hit_count_and_found_count() {
        let mut branches = Branches::new();
        branches.try_merge(&BranchData { line: 1, block: 0, branch: 1, taken: 1 }).unwrap();
        branches.try_merge(&BranchData { line: 1, block: 0, branch: 2, taken: 0 }).unwrap();

        assert_eq!(branches.hit_count(), 1);
        assert_eq!(branches.found_count(), 2);
    }
}
<commit_msg>fold to sum<commit_after>use std::io;
use std::cmp::PartialEq;
use std::fmt:: { Display, Formatter, Result };
use std::collections::btree_map:: { BTreeMap };
use std::convert::{ From };
use lcov_parser:: { BranchData };
use merger::ops:: { TryMerge, MergeResult, MergeBranch, BranchError };
use record:: { RecordWrite };
use report::summary:: { Summary };
use report::attribute:: { LineNumber, ExecutionCount };
use report::counter:: { Hit, HitFoundCounter, FoundCounter, HitCounter };

/// Units of the branch
///
/// # Examples
///
/// ```
/// use lcov_merge::branch::BranchUnit;
///
/// let branch1 = BranchUnit::new(1, 1);
/// let branch2 = BranchUnit::new(1, 1);
///
/// assert!(branch1 == branch2);
///
/// let not_eq_branch1 = BranchUnit::new(1, 1);
/// let not_eq_branch2 = BranchUnit::new(1, 2);
///
/// assert!(not_eq_branch1 != not_eq_branch2);
/// ```
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone)]
pub struct BranchUnit(u32, u32);

impl BranchUnit {
    pub fn new(block: u32, branch: u32) -> BranchUnit {
        BranchUnit(block, branch)
    }
    pub fn block(&self) -> &u32 {
        &self.0
    }
    pub fn branch(&self) -> &u32 {
        &self.1
    }
}

impl Display for BranchUnit {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}-{}", self.0, self.1)
    }
}

#[derive(Debug, Clone)]
pub struct Branch {
    line_number: LineNumber,
    block: u32,
    branch: u32,
    execution_count: ExecutionCount
}

impl Branch {
    pub fn new(
        line_number: LineNumber,
        block: u32,
        branch: u32,
        execution_count: ExecutionCount
    ) -> Self {
        Branch {
            line_number: line_number,
            block: block,
            branch: branch,
            execution_count: execution_count
        }
    }
    pub fn line_number(&self) -> &LineNumber {
        &self.line_number
    }
    pub fn block(&self) -> &u32 {
        &self.block
    }
    pub fn branch(&self) -> &u32 {
        &self.branch
    }
    pub fn execution_count(&self) -> &ExecutionCount {
        &self.execution_count
    }
}

impl PartialEq<BranchData> for Branch {
    fn eq(&self, data: &BranchData) -> bool {
        if self.line_number != data.line {
            return false;
        }
        let branch_matched = self.block == data.block && self.branch == data.branch;

        if !branch_matched {
            return false;
        }
        return true;
    }
}

impl PartialEq<Branch> for Branch {
    fn eq(&self, other: &Branch) -> bool {
        if self.line_number != *other.line_number() {
            return false;
        }
        let branch_matched = self.block == *other.block() && self.branch == *other.branch();

        if !branch_matched {
            return false;
        }
        return true;
    }
}

impl<'a> From<&'a BranchData> for Branch {
    fn from(data: &'a BranchData) -> Self {
        Branch::new(
            data.line,
            data.block,
            data.branch,
            data.taken
        )
    }
}

impl<'a> TryMerge<&'a BranchData> for Branch {
    type Err = BranchError;

    fn try_merge(&mut self, data: &'a BranchData) -> MergeResult<Self::Err> {
        if self != data {
            return Err(
                BranchError::Mismatch(
                    MergeBranch::from(&self.clone()),
                    MergeBranch::from(data)
                )
            );
        }
        self.execution_count += data.taken;
        Ok(())
    }
}

impl<'a> TryMerge<&'a Branch> for Branch {
    type Err = BranchError;

    fn try_merge(&mut self, other: &'a Branch) -> MergeResult<Self::Err> {
        if self != other {
            return Err(
                BranchError::Mismatch(
                    MergeBranch::from(&self.clone()),
                    MergeBranch::from(other)
                )
            );
        }
        self.execution_count += *other.execution_count();
        Ok(())
    }
}

impl Hit for Branch {
    fn is_hit(&self) -> bool {
        self.execution_count.is_hit()
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct BranchBlocks {
    blocks: BTreeMap<BranchUnit, Branch>
}

impl BranchBlocks {
    pub fn new() -> Self {
        BranchBlocks {
            blocks: BTreeMap::new()
        }
    }
}

impl_summary!(BranchBlocks, blocks<BranchUnit, Branch>);

impl HitCounter for BranchBlocks {
    fn hit_count(&self) -> usize {
        self.iter()
            .filter(|&(_, branch)| branch.is_hit())
            .count()
    }
}

impl FoundCounter for BranchBlocks {
    fn found_count(&self) -> usize {
        self.blocks.len()
    }
}

impl HitFoundCounter for BranchBlocks {}

impl<'a> TryMerge<&'a BranchData> for BranchBlocks {
    type Err = BranchError;

    fn try_merge(&mut self, data: &'a BranchData) -> MergeResult<Self::Err> {
        let unit = BranchUnit::new(data.block, data.branch);
        if !self.blocks.contains_key(&unit) {
            self.blocks.insert(unit, Branch::from(data));
            return Ok(());
        }
        let mut block = self.blocks.get_mut(&unit).unwrap();
        block.try_merge(data)
    }
}

impl_try_merge_self_summary!(BranchBlocks:blocks, BranchError);

#[derive(Debug, Clone)]
pub struct Branches {
    branches: BTreeMap<LineNumber, BranchBlocks>
}

impl Branches {
    pub fn new() -> Self {
        Branches {
            branches: BTreeMap::new()
        }
    }
}

impl HitCounter for Branches {
    fn hit_count(&self) -> usize {
        self.iter()
            .map(|(_, blocks)| blocks.hit_count() )
            .sum()
    }
}

impl FoundCounter for Branches {
    fn found_count(&self) -> usize {
        self.iter()
            .map(|(_, blocks)| blocks.found_count() )
            .sum()
    }
}

impl HitFoundCounter for Branches {}

impl_summary!(Branches, branches<LineNumber, BranchBlocks>);

impl RecordWrite for Branches {
    fn write_records<T: io::Write>(&self, output: &mut T) -> io::Result<()> {
        write!(output, "{}", self)
    }
}

impl Display for Branches {
    fn fmt(&self, f: &mut Formatter) -> Result {
        if self.is_empty() {
            return Ok(());
        }
        for (line_number, blocks) in self.iter() {
            for (_, branch) in blocks.iter() {
                try!(writeln!(f, "BRDA:{},{},{},{}",
                    line_number, branch.block(), branch.branch(), branch.execution_count()));
            }
        }
        try!(writeln!(f, "BRF:{}", self.found_count()));
        try!(writeln!(f, "BRH:{}", self.hit_count()));
        Ok(())
    }
}

impl_try_merge_self_summary!(Branches:branches, BranchError);

impl<'a> TryMerge<&'a BranchData> for Branches {
    type Err = BranchError;

    fn try_merge(&mut self, data: &'a BranchData) -> MergeResult<Self::Err> {
        if self.branches.contains_key(&data.line) {
            let mut blocks = self.branches.get_mut(&data.line).unwrap();
            blocks.try_merge(data)
        } else {
            let blocks = {
                let mut blocks = BranchBlocks::new();
                let _ = try!(blocks.try_merge(data));
                blocks
            };
            self.branches.insert(
                data.line.clone(),
                blocks
            );
            Ok(())
        }
    }
}

#[cfg(test)]
mod tests {
    use std::collections:: { HashMap };
    use lcov_parser:: { BranchData };
    use merger::ops::*;
    use report::branch:: { Branch, BranchUnit, Branches, BranchBlocks };
    use report::summary:: { Summary };
    use report::counter:: { FoundCounter, HitCounter };

    #[test]
    fn branch_unit() {
        let branch1 = BranchUnit(1, 1);
        let branch2 = BranchUnit(1, 2);

        assert!(branch1 != branch2);

        let same_branch1 = BranchUnit(1, 1);
        let same_branch2 = BranchUnit(1, 1);

        assert_eq!(same_branch1, same_branch2);
    }

    #[test]
    fn branch_unit_as_hash_key() {
        let mut container = HashMap::new();
        container.insert(BranchUnit(1, 1), 1);

        assert!( container.contains_key(&BranchUnit(1, 1)) );
    }

    #[test]
    fn add_branch_data() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };

        branches.try_merge(b1).unwrap();
        branches.try_merge(b2).unwrap();

        let branch = Branch::new(1, 0, 1, 2);
        assert_eq!(branches.get(&BranchUnit::new(0, 1)), Some(&branch));
    }

    #[test]
    fn append_branches() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };

        branches.try_merge(b1).unwrap();
        branches.try_merge(b2).unwrap();

        let cloned_branches = branches.clone();
        branches.try_merge(&cloned_branches).unwrap();

        let branch = Branch::new(1, 0, 1, 2);
        assert_eq!(branches.get(&BranchUnit::new(0, 1)), Some(&branch));
    }

    #[test]
    fn branch_blocks_hit_count_and_found_count() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 2, taken: 0 };

        branches.try_merge(b1).unwrap();
        branches.try_merge(b2).unwrap();

        assert_eq!(branches.hit_count(), 1);
        assert_eq!(branches.found_count(), 2);
    }

    #[test]
    fn branches_hit_count_and_found_count() {
        let mut branches = Branches::new();
        branches.try_merge(&BranchData { line: 1, block: 0, branch: 1, taken: 1 }).unwrap();
        branches.try_merge(&BranchData { line: 1, block: 0, branch: 2, taken: 0 }).unwrap();

        assert_eq!(branches.hit_count(), 1);
        assert_eq!(branches.found_count(), 2);
    }
}
<|endoftext|>


<commit_before>use context::CommandContext;
use version::Api;
use version::Version;

use DrawError;
use gl;

/// Blend effect that the GPU will use for blending.
///
/// Blending happens at the end of the rendering process, when the GPU wants to write the
/// pixels over pixels that already exist in the framebuffer. The blending function allows
/// you to choose how it should merge the two.
///
/// If you want to add transparent objects one over another, use
/// `Blend::alpha_blending()`.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Blend {
    /// The blending function for color channels.
    pub color: BlendingFunction,
    /// The blending function for alpha channels.
    pub alpha: BlendingFunction,
    /// A constant color that can be used in the blending functions.
    pub constant_value: (f32, f32, f32, f32),
}

impl Blend {
    /// Returns a blend effect to add transparent objects over others.
    pub fn alpha_blending() -> Blend {
        Blend {
            color: BlendingFunction::Addition {
                source: LinearBlendingFactor::SourceAlpha,
                destination: LinearBlendingFactor::OneMinusSourceAlpha,
            },
            alpha: BlendingFunction::Addition {
                source: LinearBlendingFactor::SourceAlpha,
                destination: LinearBlendingFactor::OneMinusSourceAlpha
            },
            constant_value: (0.0, 0.0, 0.0, 0.0)
        }
    }
}

impl Default for Blend {
    fn default() -> Blend {
        Blend {
            color: BlendingFunction::AlwaysReplace,
            alpha: BlendingFunction::AlwaysReplace,
            constant_value: (1.0, 1.0, 1.0, 1.0),
        }
    }
}

/// Function that the GPU will use for blending.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BlendingFunction {
    /// Simply overwrite the destination pixel with the source pixel.
    ///
    /// The alpha channels are simply ignored. This is the default mode.
    ///
    /// For example writing `(0.5, 0.9, 0.4, 0.2)` over `(0.9, 0.1, 0.4, 0.3)` will
    /// result in `(0.5, 0.9, 0.4, 0.2)`.
    AlwaysReplace,

    /// For each individual component (red, green, blue, and alpha), the minimum value is chosen
    /// between the source and the destination.
    ///
    /// For example writing `(0.5, 0.9, 0.4, 0.2)` over `(0.9, 0.1, 0.4, 0.3)` will
    /// result in `(0.5, 0.1, 0.4, 0.2)`.
    Min,

    /// For each individual component (red, green, blue, and alpha), the maximum value is chosen
    /// between the source and the destination.
    ///
    /// For example writing `(0.5, 0.9, 0.4, 0.2)` over `(0.9, 0.1, 0.4, 0.3)` will
    /// result in `(0.9, 0.9, 0.4, 0.3)`.
    Max,

    /// For each individual component (red, green, blue, and alpha), a weighted addition
    /// between the source and the destination.
    ///
    /// The result is equal to `source_component * source_factor + dest_component * dest_factor`,
    /// where `source_factor` and `dest_factor` are the values of `source` and `destination` of
    /// this enum.
    Addition {
        /// The factor to apply to the source pixel.
        source: LinearBlendingFactor,

        /// The factor to apply to the destination pixel.
        destination: LinearBlendingFactor,
    },

    /// For each individual component (red, green, blue, and alpha), a weighted substraction
    /// of the source by the destination.
    ///
    /// The result is equal to `source_component * source_factor - dest_component * dest_factor`,
    /// where `source_factor` and `dest_factor` are the values of `source` and `destination` of
    /// this enum.
    Subtraction {
        /// The factor to apply to the source pixel.
        source: LinearBlendingFactor,

        /// The factor to apply to the destination pixel.
        destination: LinearBlendingFactor,
    },

    /// For each individual component (red, green, blue, and alpha), a weighted substraction
    /// of the destination by the source.
    ///
    /// The result is equal to `-source_component * source_factor + dest_component * dest_factor`,
    /// where `source_factor` and `dest_factor` are the values of `source` and `destination` of
    /// this enum.
    ReverseSubtraction {
        /// The factor to apply to the source pixel.
        source: LinearBlendingFactor,

        /// The factor to apply to the destination pixel.
        destination: LinearBlendingFactor,
    },
}

/// Indicates which value to multiply each component with.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LinearBlendingFactor {
    /// Multiply the source or destination component by zero, which always
    /// gives `0.0`.
    Zero,

    /// Multiply the source or destination component by one, which always
    /// gives you the original value.
    One,

    /// Multiply the source or destination component by its corresponding value
    /// in the source.
    ///
    /// If you apply this to the source components, you get the values squared.
    SourceColor,

    /// Equivalent to `1 - SourceColor`.
    OneMinusSourceColor,

    /// Multiply the source or destination component by its corresponding value
    /// in the destination.
    ///
    /// If you apply this to the destination components, you get the values squared.
    DestinationColor,

    /// Equivalent to `1 - DestinationColor`.
    OneMinusDestinationColor,

    /// Multiply the source or destination component by the alpha value of the source.
    SourceAlpha,

    /// Multiply the source or destination component by the smallest value of
    /// `SourceAlpha` and `1 - DestinationAlpha`.
    SourceAlphaSaturate,

    /// Multiply the source or destination component by `1.0` minus the alpha value of the source.
    OneMinusSourceAlpha,

    /// Multiply the source or destination component by the alpha value of the destination.
    DestinationAlpha,

    /// Multiply the source or destination component by `1.0` minus the alpha value of the
    /// destination.
    OneMinusDestinationAlpha,

    /// Multiply the source or destination component by the corresponding value
    /// in `Blend::const_value`.
    ConstantColor,

    /// Multiply the source or destination compoent by `1.0` minus the corresponding
    /// value in `Blend::const_value`.
    OneMinusConstantColor,

    /// Multiply the source or destination component by the alpha value of `Blend::const_value`.
    ConstantAlpha,

    /// Multiply the source or destination componet by `1.0` minus the alpha value of
    /// `Blend::const_value`.
    OneMinusConstantAlpha,
}

impl LinearBlendingFactor {
    fn to_glenum(&self) -> gl::types::GLenum {
        match *self {
            LinearBlendingFactor::Zero => gl::ZERO,
            LinearBlendingFactor::One => gl::ONE,
            LinearBlendingFactor::SourceColor => gl::SRC_COLOR,
            LinearBlendingFactor::OneMinusSourceColor => gl::ONE_MINUS_SRC_COLOR,
            LinearBlendingFactor::DestinationColor => gl::DST_COLOR,
            LinearBlendingFactor::OneMinusDestinationColor => gl::ONE_MINUS_DST_COLOR,
            LinearBlendingFactor::SourceAlpha => gl::SRC_ALPHA,
            LinearBlendingFactor::OneMinusSourceAlpha => gl::ONE_MINUS_SRC_ALPHA,
            LinearBlendingFactor::DestinationAlpha => gl::DST_ALPHA,
            LinearBlendingFactor::OneMinusDestinationAlpha => gl::ONE_MINUS_DST_ALPHA,
            LinearBlendingFactor::SourceAlphaSaturate => gl::SRC_ALPHA_SATURATE,
            LinearBlendingFactor::ConstantColor => gl::CONSTANT_COLOR,
            LinearBlendingFactor::OneMinusConstantColor => gl::ONE_MINUS_CONSTANT_COLOR,
            LinearBlendingFactor::ConstantAlpha => gl::CONSTANT_ALPHA,
            LinearBlendingFactor::OneMinusConstantAlpha => gl::ONE_MINUS_CONSTANT_ALPHA,
        }
    }
}

pub fn sync_blending(ctxt: &mut CommandContext, blend: Blend) -> Result<(), DrawError> {
    #[inline(always)]
    fn blend_eq(ctxt: &mut CommandContext, blending_function: BlendingFunction)
                -> Result<gl::types::GLenum, DrawError>
    {
        match blending_function {
            BlendingFunction::AlwaysReplace |
            BlendingFunction::Addition { .. } => Ok(gl::FUNC_ADD),
            BlendingFunction::Subtraction { .. } => Ok(gl::FUNC_SUBTRACT),
            BlendingFunction::ReverseSubtraction { .. } => Ok(gl::FUNC_REVERSE_SUBTRACT),

            BlendingFunction::Min => {
                if ctxt.version <= &Version(Api::GlEs, 2, 0) &&
                   !ctxt.extensions.gl_ext_blend_minmax
                {
                    Err(DrawError::BlendingParameterNotSupported)
                } else {
                    Ok(gl::MIN)
                }
            },

            BlendingFunction::Max => {
                if ctxt.version <= &Version(Api::GlEs, 2, 0) &&
                   !ctxt.extensions.gl_ext_blend_minmax
                {
                    Err(DrawError::BlendingParameterNotSupported)
                } else {
                    Ok(gl::MAX)
                }
            },
        }
    }

    #[inline(always)]
    fn blending_factors(blending_function: BlendingFunction)
                        -> Option<(LinearBlendingFactor, LinearBlendingFactor)>
    {
        match blending_function {
            BlendingFunction::AlwaysReplace |
            BlendingFunction::Min |
            BlendingFunction::Max => None,
            BlendingFunction::Addition { source, destination } =>
                Some((source, destination)),
            BlendingFunction::Subtraction { source, destination } =>
                Some((source, destination)),
            BlendingFunction::ReverseSubtraction { source, destination } =>
                Some((source, destination)),
        }
    }

    if let (BlendingFunction::AlwaysReplace, BlendingFunction::AlwaysReplace) =
           (blend.color, blend.alpha)
    {
        // Both color and alpha always replace. This equals no blending.
        if ctxt.state.enabled_blend {
            unsafe { ctxt.gl.Disable(gl::BLEND); }
            ctxt.state.enabled_blend = false;
        }

    } else {
        if !ctxt.state.enabled_blend {
            unsafe { ctxt.gl.Enable(gl::BLEND); }
            ctxt.state.enabled_blend = true;
        }

        let (color_eq, alpha_eq) = (try!(blend_eq(ctxt, blend.color)),
                                    try!(blend_eq(ctxt, blend.alpha)));
        if ctxt.state.blend_equation != (color_eq, alpha_eq) {
            unsafe { ctxt.gl.BlendEquationSeparate(color_eq, alpha_eq); }
            ctxt.state.blend_equation = (color_eq, alpha_eq);
        }

        // Map to dummy factors if the blending equation does not use the factors.
        let (color_factor_src, color_factor_dst) = blending_factors(blend.color)
            .unwrap_or((LinearBlendingFactor::One, LinearBlendingFactor::Zero));
        let (alpha_factor_src, alpha_factor_dst) = blending_factors(blend.alpha)
            .unwrap_or((LinearBlendingFactor::One, LinearBlendingFactor::Zero));

        // Updating the blending color if necessary.
        if color_factor_src == LinearBlendingFactor::ConstantColor ||
           color_factor_src == LinearBlendingFactor::OneMinusConstantColor ||
           color_factor_dst == LinearBlendingFactor::ConstantColor ||
           color_factor_dst == LinearBlendingFactor::OneMinusConstantColor ||
           alpha_factor_src == LinearBlendingFactor::ConstantColor ||
           alpha_factor_src == LinearBlendingFactor::OneMinusConstantColor ||
           alpha_factor_dst == LinearBlendingFactor::ConstantColor ||
           alpha_factor_dst == LinearBlendingFactor::OneMinusConstantColor
        {
            if ctxt.state.blend_color != blend.constant_value {
                let (r, g, b, a) = blend.constant_value;
                unsafe { ctxt.gl.BlendColor(r, g, b, a); }
                ctxt.state.blend_color = blend.constant_value;
            }
        }

        // Updating the blending function if necessary.
        let color_factor_src = color_factor_src.to_glenum();
        let color_factor_dst = color_factor_dst.to_glenum();
        let alpha_factor_src = alpha_factor_src.to_glenum();
        let alpha_factor_dst = alpha_factor_dst.to_glenum();
        if ctxt.state.blend_func != (color_factor_src, color_factor_dst,
                                     alpha_factor_src, alpha_factor_dst)
        {
            unsafe {
                ctxt.gl.BlendFuncSeparate(color_factor_src, color_factor_dst,
                                          alpha_factor_src, alpha_factor_dst);
            }

            ctxt.state.blend_func = (color_factor_src, color_factor_dst,
                                     alpha_factor_src, alpha_factor_dst);
        }
    }

    Ok(())
}
<commit_msg>Update BlendColor when the blending equation uses ConstantAlpha<commit_after>use context::CommandContext;
use version::Api;
use version::Version;

use DrawError;
use gl;

/// Blend effect that the GPU will use for blending.
///
/// Blending happens at the end of the rendering process, when the GPU wants to write the
/// pixels over pixels that already exist in the framebuffer. The blending function allows
/// you to choose how it should merge the two.
///
/// If you want to add transparent objects one over another, use
/// `Blend::alpha_blending()`.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Blend {
    /// The blending function for color channels.
    pub color: BlendingFunction,
    /// The blending function for alpha channels.
    pub alpha: BlendingFunction,
    /// A constant color that can be used in the blending functions.
    pub constant_value: (f32, f32, f32, f32),
}

impl Blend {
    /// Returns a blend effect to add transparent objects over others.
    pub fn alpha_blending() -> Blend {
        Blend {
            color: BlendingFunction::Addition {
                source: LinearBlendingFactor::SourceAlpha,
                destination: LinearBlendingFactor::OneMinusSourceAlpha,
            },
            alpha: BlendingFunction::Addition {
                source: LinearBlendingFactor::SourceAlpha,
                destination: LinearBlendingFactor::OneMinusSourceAlpha
            },
            constant_value: (0.0, 0.0, 0.0, 0.0)
        }
    }
}

impl Default for Blend {
    fn default() -> Blend {
        Blend {
            color: BlendingFunction::AlwaysReplace,
            alpha: BlendingFunction::AlwaysReplace,
            constant_value: (1.0, 1.0, 1.0, 1.0),
        }
    }
}

/// Function that the GPU will use for blending.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BlendingFunction {
    /// Simply overwrite the destination pixel with the source pixel.
    ///
    /// The alpha channels are simply ignored. This is the default mode.
    ///
    /// For example writing `(0.5, 0.9, 0.4, 0.2)` over `(0.9, 0.1, 0.4, 0.3)` will
    /// result in `(0.5, 0.9, 0.4, 0.2)`.
    AlwaysReplace,

    /// For each individual component (red, green, blue, and alpha), the minimum value is chosen
    /// between the source and the destination.
    ///
    /// For example writing `(0.5, 0.9, 0.4, 0.2)` over `(0.9, 0.1, 0.4, 0.3)` will
    /// result in `(0.5, 0.1, 0.4, 0.2)`.
    Min,

    /// For each individual component (red, green, blue, and alpha), the maximum value is chosen
    /// between the source and the destination.
    ///
    /// For example writing `(0.5, 0.9, 0.4, 0.2)` over `(0.9, 0.1, 0.4, 0.3)` will
    /// result in `(0.9, 0.9, 0.4, 0.3)`.
    Max,

    /// For each individual component (red, green, blue, and alpha), a weighted addition
    /// between the source and the destination.
    ///
    /// The result is equal to `source_component * source_factor + dest_component * dest_factor`,
    /// where `source_factor` and `dest_factor` are the values of `source` and `destination` of
    /// this enum.
    Addition {
        /// The factor to apply to the source pixel.
        source: LinearBlendingFactor,

        /// The factor to apply to the destination pixel.
        destination: LinearBlendingFactor,
    },

    /// For each individual component (red, green, blue, and alpha), a weighted substraction
    /// of the source by the destination.
    ///
    /// The result is equal to `source_component * source_factor - dest_component * dest_factor`,
    /// where `source_factor` and `dest_factor` are the values of `source` and `destination` of
    /// this enum.
    Subtraction {
        /// The factor to apply to the source pixel.
        source: LinearBlendingFactor,

        /// The factor to apply to the destination pixel.
        destination: LinearBlendingFactor,
    },

    /// For each individual component (red, green, blue, and alpha), a weighted substraction
    /// of the destination by the source.
    ///
    /// The result is equal to `-source_component * source_factor + dest_component * dest_factor`,
    /// where `source_factor` and `dest_factor` are the values of `source` and `destination` of
    /// this enum.
    ReverseSubtraction {
        /// The factor to apply to the source pixel.
        source: LinearBlendingFactor,

        /// The factor to apply to the destination pixel.
        destination: LinearBlendingFactor,
    },
}

/// Indicates which value to multiply each component with.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LinearBlendingFactor {
    /// Multiply the source or destination component by zero, which always
    /// gives `0.0`.
    Zero,

    /// Multiply the source or destination component by one, which always
    /// gives you the original value.
    One,

    /// Multiply the source or destination component by its corresponding value
    /// in the source.
    ///
    /// If you apply this to the source components, you get the values squared.
    SourceColor,

    /// Equivalent to `1 - SourceColor`.
    OneMinusSourceColor,

    /// Multiply the source or destination component by its corresponding value
    /// in the destination.
    ///
    /// If you apply this to the destination components, you get the values squared.
    DestinationColor,

    /// Equivalent to `1 - DestinationColor`.
    OneMinusDestinationColor,

    /// Multiply the source or destination component by the alpha value of the source.
    SourceAlpha,

    /// Multiply the source or destination component by the smallest value of
    /// `SourceAlpha` and `1 - DestinationAlpha`.
    SourceAlphaSaturate,

    /// Multiply the source or destination component by `1.0` minus the alpha value of the source.
    OneMinusSourceAlpha,

    /// Multiply the source or destination component by the alpha value of the destination.
    DestinationAlpha,

    /// Multiply the source or destination component by `1.0` minus the alpha value of the
    /// destination.
    OneMinusDestinationAlpha,

    /// Multiply the source or destination component by the corresponding value
    /// in `Blend::const_value`.
    ConstantColor,

    /// Multiply the source or destination compoent by `1.0` minus the corresponding
    /// value in `Blend::const_value`.
    OneMinusConstantColor,

    /// Multiply the source or destination component by the alpha value of `Blend::const_value`.
    ConstantAlpha,

    /// Multiply the source or destination componet by `1.0` minus the alpha value of
    /// `Blend::const_value`.
    OneMinusConstantAlpha,
}

impl LinearBlendingFactor {
    fn to_glenum(&self) -> gl::types::GLenum {
        match *self {
            LinearBlendingFactor::Zero => gl::ZERO,
            LinearBlendingFactor::One => gl::ONE,
            LinearBlendingFactor::SourceColor => gl::SRC_COLOR,
            LinearBlendingFactor::OneMinusSourceColor => gl::ONE_MINUS_SRC_COLOR,
            LinearBlendingFactor::DestinationColor => gl::DST_COLOR,
            LinearBlendingFactor::OneMinusDestinationColor => gl::ONE_MINUS_DST_COLOR,
            LinearBlendingFactor::SourceAlpha => gl::SRC_ALPHA,
            LinearBlendingFactor::OneMinusSourceAlpha => gl::ONE_MINUS_SRC_ALPHA,
            LinearBlendingFactor::DestinationAlpha => gl::DST_ALPHA,
            LinearBlendingFactor::OneMinusDestinationAlpha => gl::ONE_MINUS_DST_ALPHA,
            LinearBlendingFactor::SourceAlphaSaturate => gl::SRC_ALPHA_SATURATE,
            LinearBlendingFactor::ConstantColor => gl::CONSTANT_COLOR,
            LinearBlendingFactor::OneMinusConstantColor => gl::ONE_MINUS_CONSTANT_COLOR,
            LinearBlendingFactor::ConstantAlpha => gl::CONSTANT_ALPHA,
            LinearBlendingFactor::OneMinusConstantAlpha => gl::ONE_MINUS_CONSTANT_ALPHA,
        }
    }
}

pub fn sync_blending(ctxt: &mut CommandContext, blend: Blend) -> Result<(), DrawError> {
    #[inline(always)]
    fn blend_eq(ctxt: &mut CommandContext, blending_function: BlendingFunction)
                -> Result<gl::types::GLenum, DrawError>
    {
        match blending_function {
            BlendingFunction::AlwaysReplace |
            BlendingFunction::Addition { .. } => Ok(gl::FUNC_ADD),
            BlendingFunction::Subtraction { .. } => Ok(gl::FUNC_SUBTRACT),
            BlendingFunction::ReverseSubtraction { .. } => Ok(gl::FUNC_REVERSE_SUBTRACT),

            BlendingFunction::Min => {
                if ctxt.version <= &Version(Api::GlEs, 2, 0) &&
                   !ctxt.extensions.gl_ext_blend_minmax
                {
                    Err(DrawError::BlendingParameterNotSupported)
                } else {
                    Ok(gl::MIN)
                }
            },

            BlendingFunction::Max => {
                if ctxt.version <= &Version(Api::GlEs, 2, 0) &&
                   !ctxt.extensions.gl_ext_blend_minmax
                {
                    Err(DrawError::BlendingParameterNotSupported)
                } else {
                    Ok(gl::MAX)
                }
            },
        }
    }

    #[inline(always)]
    fn blending_factors(blending_function: BlendingFunction)
                        -> Option<(LinearBlendingFactor, LinearBlendingFactor)>
    {
        match blending_function {
            BlendingFunction::AlwaysReplace |
            BlendingFunction::Min |
            BlendingFunction::Max => None,
            BlendingFunction::Addition { source, destination } =>
                Some((source, destination)),
            BlendingFunction::Subtraction { source, destination } =>
                Some((source, destination)),
            BlendingFunction::ReverseSubtraction { source, destination } =>
                Some((source, destination)),
        }
    }

    if let (BlendingFunction::AlwaysReplace, BlendingFunction::AlwaysReplace) =
           (blend.color, blend.alpha)
    {
        // Both color and alpha always replace. This equals no blending.
        if ctxt.state.enabled_blend {
            unsafe { ctxt.gl.Disable(gl::BLEND); }
            ctxt.state.enabled_blend = false;
        }

    } else {
        if !ctxt.state.enabled_blend {
            unsafe { ctxt.gl.Enable(gl::BLEND); }
            ctxt.state.enabled_blend = true;
        }

        let (color_eq, alpha_eq) = (try!(blend_eq(ctxt, blend.color)),
                                    try!(blend_eq(ctxt, blend.alpha)));
        if ctxt.state.blend_equation != (color_eq, alpha_eq) {
            unsafe { ctxt.gl.BlendEquationSeparate(color_eq, alpha_eq); }
            ctxt.state.blend_equation = (color_eq, alpha_eq);
        }

        // Map to dummy factors if the blending equation does not use the factors.
        let (color_factor_src, color_factor_dst) = blending_factors(blend.color)
            .unwrap_or((LinearBlendingFactor::One, LinearBlendingFactor::Zero));
        let (alpha_factor_src, alpha_factor_dst) = blending_factors(blend.alpha)
            .unwrap_or((LinearBlendingFactor::One, LinearBlendingFactor::Zero));

        // Updating the blending color if necessary.
        if color_factor_src == LinearBlendingFactor::ConstantColor ||
           color_factor_src == LinearBlendingFactor::OneMinusConstantColor ||
           color_factor_dst == LinearBlendingFactor::ConstantColor ||
           color_factor_dst == LinearBlendingFactor::OneMinusConstantColor ||
           alpha_factor_src == LinearBlendingFactor::ConstantColor ||
           alpha_factor_src == LinearBlendingFactor::OneMinusConstantColor ||
           alpha_factor_dst == LinearBlendingFactor::ConstantColor ||
           alpha_factor_dst == LinearBlendingFactor::OneMinusConstantColor ||
           color_factor_src == LinearBlendingFactor::ConstantAlpha ||
           color_factor_src == LinearBlendingFactor::OneMinusConstantAlpha ||
           color_factor_dst == LinearBlendingFactor::ConstantAlpha ||
           color_factor_dst == LinearBlendingFactor::OneMinusConstantAlpha ||
           alpha_factor_src == LinearBlendingFactor::ConstantAlpha ||
           alpha_factor_src == LinearBlendingFactor::OneMinusConstantAlpha ||
           alpha_factor_dst == LinearBlendingFactor::ConstantAlpha ||
           alpha_factor_dst == LinearBlendingFactor::OneMinusConstantAlpha
        {
            if ctxt.state.blend_color != blend.constant_value {
                let (r, g, b, a) = blend.constant_value;
                unsafe { ctxt.gl.BlendColor(r, g, b, a); }
                ctxt.state.blend_color = blend.constant_value;
            }
        }

        // Updating the blending function if necessary.
        let color_factor_src = color_factor_src.to_glenum();
        let color_factor_dst = color_factor_dst.to_glenum();
        let alpha_factor_src = alpha_factor_src.to_glenum();
        let alpha_factor_dst = alpha_factor_dst.to_glenum();
        if ctxt.state.blend_func != (color_factor_src, color_factor_dst,
                                     alpha_factor_src, alpha_factor_dst)
        {
            unsafe {
                ctxt.gl.BlendFuncSeparate(color_factor_src, color_factor_dst,
                                          alpha_factor_src, alpha_factor_dst);
            }

            ctxt.state.blend_func = (color_factor_src, color_factor_dst,
                                     alpha_factor_src, alpha_factor_dst);
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use na::{Mat2, DMat};
use std::collections::HashMap;
use std::num::*;
use itertools::Itertools;
use std::cell::RefCell;
use std::rc::Rc;

mod test;

#[test]
fn test_which_grid() {
    let loc = (-6., 6.);
    let i_rn = (-10.0, 10.0);
    let j_rn = (-10.0, 10.0);
    let i_bins = 10 as usize;
    let j_bins = 10 as usize;

    let result = grid_helpers::which_grid(loc, i_rn, j_rn, i_bins, j_bins).unwrap();
    assert_eq!((2, 8), result);

}

mod grid_helpers {
    pub fn which_grid(val: (f64, f64), i_range: (f64, f64), j_range: (f64, f64), i_bins: usize, j_bins: usize) -> Result<(usize, usize), String> {
        let i_size = (i_range.1 - i_range.0) / i_bins as f64;
        let i_number_of_sizes = ((val.0 - i_range.0) / i_size) as usize;
        let j_size = (j_range.1 - j_range.0) / j_bins as f64;
        let j_number_of_sizes = ((val.1 - j_range.0) / j_size) as usize;

        assert!(i_number_of_sizes < i_bins);
        assert!(j_number_of_sizes < j_bins);

        Ok((i_number_of_sizes, j_number_of_sizes))
    }

//
//        fn get_value_at_time(&self, time: u32, lambda: f64, dats: Vec<((usize,usize),Dat)>) -> Result<f64, String> {
//
//    //TODO time - 1 is wrong, it should be biggest time smaller than current
//    let coeff = self.compute_decay_coeff_at_time(time, time - 5, lambda);
//
//    let sum_vals = dats.iter().fold(0.0, |sum, x| sum + x.1.val);
//    println!("sum vals: {}", sum_vals);
//    let new_d = coeff * sum_vals + 1.0;
//    println!("new D: {}", new_d);
//
//    Ok(new_d)
//    }

//        fn compute_decay_coeff_at_time(&self, t_n: u32, t_l: u32, lambda: f64) -> f64 {
//    lambda.powf((t_n - t_l) as f64)
//    }
}

impl Default for DStreamProps {
    fn default() -> DStreamProps {
        DStreamProps {
            c_m: 3.0,
            c_l: 0.8,
            lambda: 0.998,
            beta: 0.3,
            i_bins: 10 as usize,
            j_bins: 10 as usize,
            i_range: (-10.0, 10.0),
            j_range: (-10.0, 10.0),
        }
    }
}
pub struct DStreamProps {
    c_m: f64,
    c_l: f64,
    lambda: f64,
    beta: f64,
    i_bins: usize,
    j_bins: usize,
    i_range: (f64, f64),
    j_range: (f64, f64),
}

/*

input data: [(x, y, v)]

///some impl
for some time t in 0..:
  _.put t, [(x, y, v)]

//some other impl
fn put (t, [(x, y, v)]):
  [(i, j, sum_vals)] = [x,y,v].map(i,j,v).groupby(i,j).reduce(_+_)
  foreach:
    g = density_grids[i, j]
    g.update(t, sum_vals)
    print g.get()
*/

#[derive(Clone)]
pub struct RawData {
    x: f64,
    y: f64,
    v: f64,
}

#[derive(Clone)]
#[derive(Debug)]
#[derive(Copy)]
struct BucketPoint {
    t: u32,
    v: f64,
}
#[derive(Clone)]
struct GridData {
    i: usize,
    j: usize,
    v: f64,
}
struct TheWorld {
    g_vec: Vec<((usize, usize), DG)>,
}

#[test]
fn test_new_put_works() {
    let raw_data_1 = RawData{x: 1.0, y: -1.0, v: 123.45};
    let raw_data_2 = RawData{x: 5.0, y: -7.0, v: 23.45};
    let raw_data_3 = RawData{x: 5.0, y: -7.0, v: 83.45};
    let raw_data_4 = RawData{x: 15.0, y: -17.0, v: 83.45};

    let rd_vec = vec!(raw_data_1, raw_data_2, raw_data_3, raw_data_4);

    let t = 1;

    let default_vec : Vec<BucketPoint> = Vec::new();
    let mut world = TheWorld{g_vec: Vec::new()};
    world.init(default_vec);
    let res1 = world.put(t, rd_vec.clone());
    let res2 = world.put(t + 1, rd_vec.clone());
    let res3 = world.put(t + 2, rd_vec.clone());

}

impl TheWorld {
    fn init(&mut self, def_bucket: Vec<BucketPoint>) {
        println!("init");
        let props: DStreamProps = DStreamProps { ..Default::default() };

        for i in 0..props.i_bins {
            for j in 0..props.j_bins {
                let z_clone = def_bucket.clone();
                let some_default_dg = DG {i: i, j: j, updates_and_vals: z_clone};
                (self.g_vec).push(((i as usize, j as usize), some_default_dg));
            }
        }
    }
    fn do_time_steps() {}
    fn do_one_time_step(t: u32, data: Vec<RawData>) {}

    fn get_by_idx(&mut self, idx: (usize, usize))-> DG {
        let  vec_f: Vec<((usize, usize), DG)> = self.g_vec.clone().into_iter().filter(|i| i.0 == idx).collect();
        vec_f[0].1.clone()
    }
    fn update_by_idx(&mut self, idx: (usize, usize), dg: DG) -> Result<(), String> {
        self.g_vec.retain(|i| i.0 != idx);
        self.g_vec.push((idx, dg));
        Ok(())
    }
    fn put(&mut self, t: u32, dat: Vec<RawData>) -> Result<(), String> {

        fn validate_range(loc2d: (f64, f64)) -> bool {

            let props: DStreamProps = DStreamProps { ..Default::default() };

            if ((loc2d.0 <= props.i_range.1) &&
            (loc2d.0 >= props.i_range.0) &&
            (loc2d.1 <= props.j_range.1) &&
            (loc2d.1 >= props.j_range.0)) {
                println!("valid!");
            } else {
                println!("invalid! -- bad input range");
                return false
            }
            return true
        }
        let with_idxs: Vec<GridData> = dat
            .iter()
            .filter(|rd| validate_range((rd.x, rd.y)))
            .map(|rd| self.which_idxs(rd).unwrap())
            .collect();

        let props: DStreamProps = DStreamProps { ..Default::default() };

        for (key, group) in with_idxs.iter().group_by(|gd| (gd.i, gd.j)) {
            println!("--put: key, g size: ({},{}) : {}", key.0, key.1, group.len());

            let the_vec_of_vals: Vec<f64> = group.iter().map(|t| t.v).collect();

            let mut some_default_dg = DG {i: key.0, j: key.1, updates_and_vals: Vec::<BucketPoint>::new()};

            let teh_dg: &mut DG = &mut self.get_by_idx(key);
            let update_dg_result = teh_dg.update(t, the_vec_of_vals);
            let udpate_world_result = self.update_by_idx(key, teh_dg.clone());
        }
        Ok(())
    }
    fn which_idxs(&self, dat: &RawData) -> Result<GridData, String> {

        let props: DStreamProps = DStreamProps { ..Default::default() };

        let idxs = grid_helpers::which_grid((dat.x, dat.y), props.i_range, props.j_range,props.i_bins, props.j_bins).unwrap();

        Ok((GridData{i:idxs.0,j:idxs.1,v:dat.v}))

    }
}

#[derive(Debug)]
#[derive(Clone)]
//#[derive(Copy)] TODO: how to make this work?
struct DG {
    i: usize,
    j: usize,
    updates_and_vals: Vec<BucketPoint>,
}
impl DG {
    fn get_at_time(&self, t: u32) -> f64 {
        let last_update_time_and_value = self.get_last_update_and_value_to(t);
        let coeff = self.coeff(t, last_update_time_and_value.0);
        let d = coeff * last_update_time_and_value.1 + 1.0;

        d
    }
    fn update(&mut self, t: u32, vals: Vec<f64>) -> Result<(), String> {
        let sum = vals.clone().iter().fold(0.0, |sum, x| sum + x);
        self.updates_and_vals.push(BucketPoint {t: t, v: sum});
        println!("  times updated dg: {}", self.updates_and_vals.len());
        Ok(())
    }

    fn get_last_update_and_value_to(&self, t: u32) -> (u32, f64) {
        //TODO
        (1, 123.232)
    }

    fn coeff(&self, t_n: u32, t_l: u32) -> f64 {
        //TODO
        100.0343
    }

 }

#[test]
fn test_initialize_clustering() {

    let result = initialize_clustering(Vec::new());
    assert_eq!(Ok(()), result);
}

pub fn initialize_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update density of all grids in grid_list
    //assign each dense grid to a distinct cluster
    //label all other grids as NO_CLASS; bad grids!
    /*
    do until no change in cluster labels
          foreach cluster c
            foreach outside grid g of c
                foreach neighboring grid h of g
                    if h belongs to cluster c'
                        if |c| > |c'| label all grids in c' as c
                        else label all grids in c as c'
                    else if (h is translational) label h as in c
    end do
    */
    Ok(())
}

pub fn adjust_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update the density of all grids in grid_list
    /*
    foreach grid g whose attribute (dense/sparse/transitional) is changed since last call to adjust_clustering()
        if g is a sparse grid
            delete g from its cluster c, label g as NO_CLASS
            if (c becomes unconnected) split c into two clusters
        else if g is a dense grid
            among all neighboring grids of g, find out the grid h whoe cluster c_h has the largest size
            if h is a dense grid
                if (g is labelled as NO_CLASS) label g as in c_h
                else if (g is in cluster c and |c| > |c_h|)
                    label all grids in c_h as in c
                else if (g is in cluster c and |c| <= |c_h|)
                    label all grids in c as in c_h
            else if h is a transitional grid
                if ((g is NO_CLASS) and (h is an outside grid if g is added to c_h)) label g as in c_h
                else if (g is in cluster c and |c| >= |c_h|)
                    move h from cluster c_h to c
        else if (g is transitional grid)
            among neighboring clusters of g, find the largest one c'
            satisfying that g is an outside grid if added to it and
            label g as in c'
    */

    Ok(())
}<commit_msg>test get last update, and get at time<commit_after>use na::{Mat2, DMat};
use std::collections::HashMap;
use std::num::*;
use itertools::Itertools;
use std::cell::RefCell;
use std::rc::Rc;

mod test;

impl Default for DStreamProps {
    fn default() -> DStreamProps {
        DStreamProps {
            c_m: 3.0,
            c_l: 0.8,
            lambda: 0.998,
            beta: 0.3,
            i_bins: 10 as usize,
            j_bins: 10 as usize,
            i_range: (-10.0, 10.0),
            j_range: (-10.0, 10.0),
        }
    }
}
pub struct DStreamProps {
    c_m: f64,
    c_l: f64,
    lambda: f64,
    beta: f64,
    i_bins: usize,
    j_bins: usize,
    i_range: (f64, f64),
    j_range: (f64, f64),
}

#[derive(Clone)]
pub struct RawData {
    x: f64,
    y: f64,
    v: f64,
}

#[derive(Clone)]
#[derive(Debug)]
#[derive(Copy)]
struct BucketPoint {
    t: u32,
    v: f64,
}
#[derive(Clone)]
struct GridData {
    i: usize,
    j: usize,
    v: f64,
}
struct TheWorld {
    g_vec: Vec<((usize, usize), DG)>,
}

#[test]
fn test_new_put_works() {
    let raw_data_1 = RawData{x: 1.0, y: -1.0, v: 123.45};
    let raw_data_2 = RawData{x: 5.0, y: -7.0, v: 23.45};
    let raw_data_3 = RawData{x: 5.0, y: -7.0, v: 83.45};
    let raw_data_4 = RawData{x: 15.0, y: -17.0, v: 83.45};

    let rd_vec = vec!(raw_data_1, raw_data_2, raw_data_3, raw_data_4);

    let t = 1;

    let default_vec : Vec<BucketPoint> = Vec::new();
    let mut world = TheWorld{g_vec: Vec::new()};
    world.init(default_vec);
    let res1 = world.put(t, rd_vec.clone());
    let res2 = world.put(t + 1, rd_vec.clone());
    let res3 = world.put(t + 2, rd_vec.clone());

}

impl TheWorld {

    #[test]
    fn test_which_grid() {
        let loc = (-6., 6.);
        let i_rn = (-10.0, 10.0);
        let j_rn = (-10.0, 10.0);
        let i_bins = 10 as usize;
        let j_bins = 10 as usize;

        let result = TheWorld::which_grid(loc, i_rn, j_rn, i_bins, j_bins).unwrap();
        assert_eq!((2, 8), result);

    }
    fn which_grid(val: (f64, f64), i_range: (f64, f64), j_range: (f64, f64), i_bins: usize, j_bins: usize) -> Result<(usize, usize), String> {
        let i_size = (i_range.1 - i_range.0) / i_bins as f64;
        let i_number_of_sizes = ((val.0 - i_range.0) / i_size) as usize;
        let j_size = (j_range.1 - j_range.0) / j_bins as f64;
        let j_number_of_sizes = ((val.1 - j_range.0) / j_size) as usize;

        assert!(i_number_of_sizes < i_bins);
        assert!(j_number_of_sizes < j_bins);

        Ok((i_number_of_sizes, j_number_of_sizes))
    }

    fn init(&mut self, def_bucket: Vec<BucketPoint>) {
        println!("init");
        let props: DStreamProps = DStreamProps { ..Default::default() };

        for i in 0..props.i_bins {
            for j in 0..props.j_bins {
                let z_clone = def_bucket.clone();
                let some_default_dg = DG {i: i, j: j, updates_and_vals: z_clone};
                (self.g_vec).push(((i as usize, j as usize), some_default_dg));
            }
        }
    }
    fn do_time_steps() {}
    fn do_one_time_step(t: u32, data: Vec<RawData>) {}

    fn get_by_idx(&mut self, idx: (usize, usize))-> DG {
        let  vec_f: Vec<((usize, usize), DG)> = self.g_vec.clone().into_iter().filter(|i| i.0 == idx).collect();
        vec_f[0].1.clone()
    }
    fn update_by_idx(&mut self, idx: (usize, usize), dg: DG) -> Result<(), String> {
        self.g_vec.retain(|i| i.0 != idx);
        self.g_vec.push((idx, dg));
        Ok(())
    }
    fn put(&mut self, t: u32, dat: Vec<RawData>) -> Result<(), String> {

        fn validate_range(loc2d: (f64, f64)) -> bool {

            let props: DStreamProps = DStreamProps { ..Default::default() };

            if ((loc2d.0 <= props.i_range.1) &&
            (loc2d.0 >= props.i_range.0) &&
            (loc2d.1 <= props.j_range.1) &&
            (loc2d.1 >= props.j_range.0)) {
                println!("valid!");
            } else {
                println!("invalid! -- bad input range");
                return false
            }
            return true
        }
        let with_idxs: Vec<GridData> = dat
            .iter()
            .filter(|rd| validate_range((rd.x, rd.y)))
            .map(|rd| self.which_idxs(rd).unwrap())
            .collect();

        let props: DStreamProps = DStreamProps { ..Default::default() };

        for (key, group) in with_idxs.iter().group_by(|gd| (gd.i, gd.j)) {
            println!("--put: key, g size: ({},{}) : {}", key.0, key.1, group.len());

            let the_vec_of_vals: Vec<f64> = group.iter().map(|t| t.v).collect();

            let mut some_default_dg = DG {i: key.0, j: key.1, updates_and_vals: Vec::<BucketPoint>::new()};

            let teh_dg: &mut DG = &mut self.get_by_idx(key);
            let update_dg_result = teh_dg.update(t, the_vec_of_vals);
            let udpate_world_result = self.update_by_idx(key, teh_dg.clone());
        }
        Ok(())
    }
    fn which_idxs(&self, dat: &RawData) -> Result<GridData, String> {

        let props: DStreamProps = DStreamProps { ..Default::default() };

        let idxs = TheWorld::which_grid((dat.x, dat.y), props.i_range, props.j_range,props.i_bins, props.j_bins).unwrap();

        Ok((GridData{i:idxs.0,j:idxs.1,v:dat.v}))

    }
}

#[test]
fn test_dg_update_and_get() {
    let mut dg = DG {i: 0, j:0, updates_and_vals: Vec::new()};
    dg.update(1, vec!(100.0));
    dg.update(10, vec!(200.0));
    dg.update(20, vec!(300.0));
    let v_at_t = dg.get_at_time(30);
    println!("v: {}", v_at_t);
}

#[derive(Debug)]
#[derive(Clone)]
//#[derive(Copy)] TODO: how to make this work?
struct DG {
    i: usize,
    j: usize,
    updates_and_vals: Vec<BucketPoint>,
}
impl DG {
    fn get_at_time(&self, t: u32) -> f64 {
        let last_update_time_and_value = self.get_last_update_and_value_to(t);
        let coeff = self.coeff(t, last_update_time_and_value.0);
        let d = coeff * last_update_time_and_value.1 + 1.0;

        d
    }
    fn update(&mut self, t: u32, vals: Vec<f64>) -> Result<(), String> {
        let sum = vals.clone().iter().fold(0.0, |sum, x| sum + x);
        self.updates_and_vals.push(BucketPoint {t: t, v: sum});
        println!("  times updated dg: {}", self.updates_and_vals.len());
        Ok(())
    }

    fn get_last_update_and_value_to(&self, t: u32) -> (u32, f64) {
        let a: BucketPoint = self.updates_and_vals.clone().into_iter().filter(|bp| bp.t < t).max_by_key(|bp| bp.t).unwrap();
        let t_l = a.t;
        let v_l = a.v;
        println!("last update relative to {} is (t: {}, v: {})", t, t_l, v_l);
        (t_l, v_l)
    }

    fn coeff(&self, t_n: u32, t_l: u32) -> f64 {
        let props: DStreamProps = DStreamProps { ..Default::default() };
        props.lambda.powf((t_n - t_l) as f64)
    }

 }

#[test]
fn test_initialize_clustering() {

    let result = initialize_clustering(Vec::new());
    assert_eq!(Ok(()), result);
}

pub fn initialize_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update density of all grids in grid_list
    //assign each dense grid to a distinct cluster
    //label all other grids as NO_CLASS; bad grids!
    /*
    do until no change in cluster labels
          foreach cluster c
            foreach outside grid g of c
                foreach neighboring grid h of g
                    if h belongs to cluster c'
                        if |c| > |c'| label all grids in c' as c
                        else label all grids in c as c'
                    else if (h is translational) label h as in c
    end do
    */
    Ok(())
}

pub fn adjust_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update the density of all grids in grid_list
    /*
    foreach grid g whose attribute (dense/sparse/transitional) is changed since last call to adjust_clustering()
        if g is a sparse grid
            delete g from its cluster c, label g as NO_CLASS
            if (c becomes unconnected) split c into two clusters
        else if g is a dense grid
            among all neighboring grids of g, find out the grid h whoe cluster c_h has the largest size
            if h is a dense grid
                if (g is labelled as NO_CLASS) label g as in c_h
                else if (g is in cluster c and |c| > |c_h|)
                    label all grids in c_h as in c
                else if (g is in cluster c and |c| <= |c_h|)
                    label all grids in c as in c_h
            else if h is a transitional grid
                if ((g is NO_CLASS) and (h is an outside grid if g is added to c_h)) label g as in c_h
                else if (g is in cluster c and |c| >= |c_h|)
                    move h from cluster c_h to c
        else if (g is transitional grid)
            among neighboring clusters of g, find the largest one c'
            satisfying that g is an outside grid if added to it and
            label g as in c'
    */

    Ok(())
}<|endoftext|>


<commit_before>use screen::*;
use context::Context;
use resource_manager::Textures;
use graphics::Texture;
use piston_window::{self, PistonWindow};

pub struct Battle {
    a: Texture,
}

impl Battle {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        Battle { a: context.resource_manager.load_texture(window, Textures::EmptyTile) }
    }
}

impl Screen for Battle {
    fn on_input(&mut self, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        use piston_window::{Input, Button, Key};

        let mut result = Vec::new();

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Escape) => {
                        result.push(InputResult::PushScreen(Box::new(MainMenu::new(&window, context))));
                    }
                    _ => {}
                }
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, _args: &piston_window::RenderArgs, window: &PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);
            piston_window::image(&self.a, context.transform, graphics);
        });
    }

    fn on_update(&mut self, _args: &piston_window::UpdateArgs) {}
}
<commit_msg>'a' -> 'empty_tile'<commit_after>use screen::*;
use context::Context;
use resource_manager::Textures;
use graphics::Texture;
use piston_window::{self, PistonWindow};

pub struct Battle {
    empty_tile: Texture,
}

impl Battle {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        Battle { empty_tile: context.resource_manager.load_texture(window, Textures::EmptyTile) }
    }
}

impl Screen for Battle {
    fn on_input(&mut self, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        use piston_window::{Input, Button, Key};

        let mut result = Vec::new();

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Escape) => {
                        result.push(InputResult::PushScreen(Box::new(MainMenu::new(&window, context))));
                    }
                    _ => {}
                }
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, _args: &piston_window::RenderArgs, window: &PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);
            piston_window::image(&self.a, context.transform, graphics);
        });
    }

    fn on_update(&mut self, _args: &piston_window::UpdateArgs) {}
}
<|endoftext|>


<commit_before>//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[cfg(test)]
mod tests;

use core::num::*;

macro_rules! type_alias_no_nz {
    {
      $Docfile:tt, $Alias:ident = $Real:ty;
      $( $Cfg:tt )*
    } => {
        #[doc = include_str!($Docfile)]
        $( $Cfg )*
        #[stable(feature = "raw_os", since = "1.1.0")]
        pub type $Alias = $Real;
    }
}

// To verify that the NonZero types in this file's macro invocations correspond
//
//  perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
//
// NB this does not check that the main c_* types are right.

macro_rules! type_alias {
    {
      $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty;
      $( $Cfg:tt )*
    } => {
        type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* }

        #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")]
        #[unstable(feature = "raw_os_nonzero", issue = "82363")]
        $( $Cfg )*
        pub type $NZAlias = $NZReal;
    }
}

type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
#[doc(cfg(all()))]
#[cfg(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
))]}
type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8;
#[doc(cfg(all()))]
#[cfg(not(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
)))]}
type_alias! { "schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; }
type_alias! { "uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; }
type_alias! { "short.md", c_short = i16, NonZero_c_short = NonZeroI16; }
type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
#[doc(cfg(all()))]
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
#[doc(cfg(all()))]
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
#[doc(cfg(all()))]
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
#[doc(cfg(all()))]
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
type_alias_no_nz! { "float.md", c_float = f32; }
type_alias_no_nz! { "double.md", c_double = f64; }

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;

/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`usize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_size_t = usize;

/// Equivalent to C's `ssize_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`isize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_ssize_t = isize;
<commit_msg>Auto merge of #90421 - thomcc:friendship-ended-with-ssize_t-now-ptrdiff_t-is-my-best-friend, r=joshtriplett<commit_after>//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[cfg(test)]
mod tests;

use core::num::*;

macro_rules! type_alias_no_nz {
    {
      $Docfile:tt, $Alias:ident = $Real:ty;
      $( $Cfg:tt )*
    } => {
        #[doc = include_str!($Docfile)]
        $( $Cfg )*
        #[stable(feature = "raw_os", since = "1.1.0")]
        pub type $Alias = $Real;
    }
}

// To verify that the NonZero types in this file's macro invocations correspond
//
//  perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
//
// NB this does not check that the main c_* types are right.

macro_rules! type_alias {
    {
      $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty;
      $( $Cfg:tt )*
    } => {
        type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* }

        #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")]
        #[unstable(feature = "raw_os_nonzero", issue = "82363")]
        $( $Cfg )*
        pub type $NZAlias = $NZReal;
    }
}

type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
#[doc(cfg(all()))]
#[cfg(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
))]}
type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8;
#[doc(cfg(all()))]
#[cfg(not(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
)))]}
type_alias! { "schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; }
type_alias! { "uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; }
type_alias! { "short.md", c_short = i16, NonZero_c_short = NonZeroI16; }
type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
#[doc(cfg(all()))]
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
#[doc(cfg(all()))]
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
#[doc(cfg(all()))]
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
#[doc(cfg(all()))]
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
type_alias_no_nz! { "float.md", c_float = f32; }
type_alias_no_nz! { "double.md", c_double = f64; }

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;

/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`usize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_size_t = usize;

/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`isize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_ptrdiff_t = isize;

/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type.
///
/// This type is currently always [`isize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_ssize_t = isize;
<|endoftext|>