<commit_before>//! Pixel manipulations.

use image::Pixel;
use conv::ValueInto;
use math::cast;
use definitions::Clamp;

/// Adds pixels with the given weights. Results are clamped to prevent arithmetical overflows.
pub fn weighted_sum<P: Pixel>(left: P, right: P, left_weight: f32, right_weight: f32) -> P
    where P::Subpixel: ValueInto<f32> + Clamp<f32>
{
    left.map2(&right, |p, q| weighted_channel_sum(p, q, left_weight, right_weight))
}

/// Equivalent to `weighted_sum(left, right, left_weight, 1 - left_weight).
pub fn interpolate<P: Pixel>(left: P, right: P, left_weight: f32) -> P
    where P::Subpixel: ValueInto<f32> + Clamp<f32>
{
    weighted_sum(left, right, left_weight, 1.0 - left_weight)
}

#[inline(always)]
fn weighted_channel_sum<C>(left: C, right: C, left_weight: f32, right_weight: f32) -> C
    where C: ValueInto<f32> + Clamp<f32>
{
    Clamp::clamp(cast(left) * left_weight + cast(right) * right_weight)
}

#[cfg(test)]
mod test {
    use super::*;
    use image::{Rgb, Luma};
    use test::{Bencher, black_box};

    #[test]
    fn test_weighted_channel_sum() {
        // Midpoint
        assert_eq!(weighted_channel_sum(10u8, 20u8, 0.5, 0.5), 15u8);
        // Mainly left
        assert_eq!(weighted_channel_sum(10u8, 20u8, 0.9, 0.1), 11u8);
        // Clamped
        assert_eq!(weighted_channel_sum(150u8, 150u8, 1.8, 0.8), 255u8);
    }

    #[test]
    fn test_weighted_sum() {
        let left = Rgb([10u8, 20u8, 30u8]);
        let right = Rgb([100u8, 80u8, 60u8]);
        let sum = weighted_sum(left, right, 0.7, 0.3);
        assert_eq!(sum, Rgb([37, 38, 39]));
    }

    #[bench]
    fn bench_weighted_sum_rgb(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Rgb([10u8, 20u8, 33u8]));
            let right = black_box(Rgb([80u8, 70u8, 60u8]));
            let left_weight = black_box(0.3);
            let right_weight = black_box(0.7);
            black_box(weighted_sum(left, right, left_weight, right_weight));
        })
    }

    #[bench]
    fn bench_weighted_sum_gray(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Luma([10u8]));
            let right = black_box(Luma([80u8]));
            let left_weight = black_box(0.3);
            let right_weight = black_box(0.7);
            black_box(weighted_sum(left, right, left_weight, right_weight));
        })
    }

    #[bench]
    fn bench_interpolate_rgb(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Rgb([10u8, 20u8, 33u8]));
            let right = black_box(Rgb([80u8, 70u8, 60u8]));
            let left_weight = black_box(0.3);
            black_box(interpolate(left, right, left_weight));
        })
    }

    #[bench]
    fn bench_interpolate_gray(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Luma([10u8]));
            let right = black_box(Luma([80u8]));
            let left_weight = black_box(0.3);
            black_box(interpolate(left, right, left_weight));
        })
    }
}
<commit_msg>Run rustfmt on pixelops.rs<commit_after>//! Pixel manipulations.

use image::Pixel;
use conv::ValueInto;
use math::cast;
use definitions::Clamp;

/// Adds pixels with the given weights. Results are clamped to prevent arithmetical overflows.
pub fn weighted_sum<P: Pixel>(left: P, right: P, left_weight: f32, right_weight: f32) -> P
where
    P::Subpixel: ValueInto<f32> + Clamp<f32>,
{
    left.map2(&right, |p, q| {
        weighted_channel_sum(p, q, left_weight, right_weight)
    })
}

/// Equivalent to `weighted_sum(left, right, left_weight, 1 - left_weight).
pub fn interpolate<P: Pixel>(left: P, right: P, left_weight: f32) -> P
where
    P::Subpixel: ValueInto<f32> + Clamp<f32>,
{
    weighted_sum(left, right, left_weight, 1.0 - left_weight)
}

#[inline(always)]
fn weighted_channel_sum<C>(left: C, right: C, left_weight: f32, right_weight: f32) -> C
where
    C: ValueInto<f32> + Clamp<f32>,
{
    Clamp::clamp(cast(left) * left_weight + cast(right) * right_weight)
}

#[cfg(test)]
mod test {
    use super::*;
    use image::{Rgb, Luma};
    use test::{Bencher, black_box};

    #[test]
    fn test_weighted_channel_sum() {
        // Midpoint
        assert_eq!(weighted_channel_sum(10u8, 20u8, 0.5, 0.5), 15u8);
        // Mainly left
        assert_eq!(weighted_channel_sum(10u8, 20u8, 0.9, 0.1), 11u8);
        // Clamped
        assert_eq!(weighted_channel_sum(150u8, 150u8, 1.8, 0.8), 255u8);
    }

    #[test]
    fn test_weighted_sum() {
        let left = Rgb([10u8, 20u8, 30u8]);
        let right = Rgb([100u8, 80u8, 60u8]);
        let sum = weighted_sum(left, right, 0.7, 0.3);
        assert_eq!(sum, Rgb([37, 38, 39]));
    }

    #[bench]
    fn bench_weighted_sum_rgb(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Rgb([10u8, 20u8, 33u8]));
            let right = black_box(Rgb([80u8, 70u8, 60u8]));
            let left_weight = black_box(0.3);
            let right_weight = black_box(0.7);
            black_box(weighted_sum(left, right, left_weight, right_weight));
        })
    }

    #[bench]
    fn bench_weighted_sum_gray(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Luma([10u8]));
            let right = black_box(Luma([80u8]));
            let left_weight = black_box(0.3);
            let right_weight = black_box(0.7);
            black_box(weighted_sum(left, right, left_weight, right_weight));
        })
    }

    #[bench]
    fn bench_interpolate_rgb(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Rgb([10u8, 20u8, 33u8]));
            let right = black_box(Rgb([80u8, 70u8, 60u8]));
            let left_weight = black_box(0.3);
            black_box(interpolate(left, right, left_weight));
        })
    }

    #[bench]
    fn bench_interpolate_gray(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Luma([10u8]));
            let right = black_box(Luma([80u8]));
            let left_weight = black_box(0.3);
            black_box(interpolate(left, right, left_weight));
        })
    }
}
<|endoftext|>


<commit_before>use qdowncast::QDowncastable;
use qindex_multi::MultiIndexable;

use std::any::{Any, TypeId};
use std::borrow::Borrow;
use std::collections::btree_map::{self, BTreeMap};
use std::ops::{Index, IndexMut};

// ++++++++++++++++++++ ServiceReflect ++++++++++++++++++++

/// Our `Reflect`-derivative.
/// This supplies necessary information for retrieving an service at compile-time.
pub trait ServiceReflect: Any {
    fn option_name() -> &'static str;
}

// ++++++++++++++++++++ GetSerectError ++++++++++++++++++++

#[derive(Debug, Clone)]
pub enum GetSerivceError<'a> {
    TypeMismatch{ option_name: &'a str, expected: TypeId, found: TypeId },
    MissingOption(&'a str),
}

impl<'a> GetSerectError<'a> {
    pub fn type_mismatch<Expected>(found: TypeId) -> GetSerivceError<'static>
        where Expected: ServiceReflect
    {
        GetSerectError::TypeMismatch{
            option_name: Expected::option_name(),
            expected: TypeId::of::<Expected>(),
            found: found,
        }
    }
}

pub type GetSerectResult<'a, T> = Result<T, GetSerectError<'a>>;

// ++++++++++++++++++++ WiringOption ++++++++++++++++++++

/// TODO expose this to the user?
enum WiringOption<Ser: Any + ?Sized> {
    /// An option with zero or more alternatives. May be wired to one of its services.
    Multi{
        wired: Option<usize>,
        alternatives: Vec<(String, Box<Ser>)>,
    },
    /// A single alternative option. Is always wired to exactly one service.
    Single(Box<Ser>),
}

impl<Ser: Any + ?Sized> WiringOption<Ser> {
    fn has_alternative(&self, alt_name: &str) -> bool {
        match self {
            &WiringOption::Multi{ ref alternatives, .. } => {
                alternatives.iter().any(|e| &*e.0 == alt_name)
            }
            _ => false,
        }
    }

    fn add_alternative(&mut self, alt_name: String, service: Box<Ser>){
        assert!(!self.has_alternative(&alt_name),
                "Alternative '{}' already exists,", alt_name);

        match self {
            &mut WiringOption::Multi{ ref mut alternatives, .. } => {
                alternatives.push((alt_name, service));
            }
            _ => {
                panic!("can't add alternative '{}' to single alternative option", alt_name);
            }
        }
    }

    fn wire_alternative(&mut self, alt_name: &str) {
        assert!(self.has_alternative(&alt_name),
                "Can't wire missing alternative '{}'", alt_name);

        match self {
            &mut WiringOption::Multi{ ref mut wired, ref alternatives } => {
                *wired = Some(alternatives.iter().position(|e| &*e.0 == alt_name).unwrap());
            }
            _ => { unreachable!() }
        }
    }

    fn service(&self) -> Option<&Ser> {
        match self {
            &WiringOption::Single(ref service) => Some(&**service),
            &WiringOption::Multi{ wired, ref alternatives } => match wired {
                Some(idx) => Some(&*alternatives[idx].1),
                None => None,
            }
        }
    }

    fn service_mut(&mut self) -> Option<&mut Ser> {
        match self {
            &mut WiringOption::Single(ref mut service) => Some(&mut**service),
            &mut WiringOption::Multi{ wired, ref mut alternatives } => match wired {
                Some(idx) => Some(&mut*alternatives[idx].1),
                None => None,
            }
        }
    }
}

// ++++++++++++++++++++ ServiceMap ++++++++++++++++++++

pub trait DefaultBase: Any {}
impl<T: Any + ?Sized> DefaultBase for T {}
qdowncastable!(DefaultBase);
qdowncast_methods!(DefaultBase);

pub struct ServiceMap<Ser: Any + ?Sized = DefaultBase> {
    options: BTreeMap<String, WiringOption<Ser>>,
}

impl<Ser: Any + ?Sized> ServiceMap<Ser> {
    /// Gets the service wired to option `opt_name` immutably.
    pub fn get_service(&self, opt_name: &str) -> Option<&Ser> {
        self.options.get(opt_name).and_then(|option| option.service())
    }

    /// Gets the service wired to option `opt_name` mutably.
    pub fn get_service_mut(&mut self, opt_name: &str) -> Option<&mut Ser> {
        self.options.get_mut(opt_name).and_then(|option| option.service_mut())
    }

    /// Gets the service wired to option `opt_name` immutably, then tries to downcast it.
    pub fn get<T>(&self) -> GetSerectResult<&T>
        where T: ServiceReflect, Ser: QDowncastable<T>
    {
        match self.get_service(T::option_name()) {
            Some(base) => {
                let ty = (&*base).get_type_id();
                match QDowncastable::downcast_ref(base) {
                    Some(ret) => Ok(ret),
                    None => Err(GetSerectError::type_mismatch::<T>(ty))
                }
            }
            None => Err(GetSerectError::MissingOption(T::option_name()))
        }
    }

    /// Gets the service wired to option `opt_name` mutably, then tries to downcast it.
    pub fn get_mut<T>(&mut self) -> GetSerectResult<&mut T>
        where T: ServiceReflect, Ser: QDowncastable<T>
    {
        match self.get_service_mut(T::option_name()) {
            Some(base) => {
                let ty = (&*base).get_type_id();
                match QDowncastable::downcast_mut(base) {
                    Some(ret) => Ok(ret),
                    None => Err(GetSerectError::type_mismatch::<T>(ty))
                }
            }
            None => Err(GetSerectError::MissingOption(T::option_name()))
        }
    }

    /// Iterate over all wired services immutably.
    pub fn iter(&self) -> Iter<Ser> {
        Iter{ options: self.options.iter() }
    }

    /// Iterate over all wired services mutably.
    pub fn iter_mut(&mut self) -> IterMut<Ser> {
        IterMut{ options: self.options.iter_mut() }
    }
}

/// TODO impl more Iterator-traits?
#[derive(Clone)]
pub struct Iter<'a, Ser: Any + ?Sized = DefaultBase> {
    options: btree_map::Iter<'a, String, WiringOption<Ser>>,
}

impl<'a, Ser: Any + ?Sized> Iterator for Iter<'a, Ser> {
    type Item = (&'a str, &'a Ser);
    fn next(&mut self) -> Option<Self::Item> {
        match self.options.next() {
            Some((opt_name, option)) => match option.service() {
                Some(service) => Some((&opt_name, service)),
                None => self.next(),
            },
            None => None,
        }
    }
}

/// TODO impl more Iterator-traits?
pub struct IterMut<'a, Ser: Any + ?Sized = DefaultBase> {
    options: btree_map::IterMut<'a, String, WiringOption<Ser>>,
}

impl<'a, Ser: Any + ?Sized> Iterator for IterMut<'a, Ser> {
    type Item = (&'a str, &'a mut Ser);
    fn next(&mut self) -> Option<Self::Item> {
        match self.options.next() {
            Some((opt_name, option)) => match option.service_mut() {
                Some(service) => Some((&opt_name, service)),
                None => self.next(),
            },
            None => None,
        }
    }
}

impl<'a, Ser: Any + ?Sized> IntoIterator for &'a ServiceMap<Ser> {
    type Item = <Self::IntoIter as Iterator>::Item;
    type IntoIter = Iter<'a, Ser>;
    fn into_iter(self) -> Self::IntoIter { self.iter() }
}

impl<'a, Ser: Any + ?Sized> IntoIterator for &'a mut ServiceMap<Ser> {
    type Item = <Self::IntoIter as Iterator>::Item;
    type IntoIter = IterMut<'a, Ser>;
    fn into_iter(self) -> Self::IntoIter { self.iter_mut() }
}

impl<'a, Str, Ser: ?Sized> Index<&'a Str> for ServiceMap<Ser>
    where Str: Ord + Borrow<str>, Ser: Any
{
    type Output = Ser;
    fn index(&self, name: &'a Str) -> &Self::Output {
        self.get_service(name.borrow()).unwrap()
    }
}

impl<'a, Str, Ser: ?Sized> IndexMut<&'a Str> for ServiceMap<Ser>
    where Str: Ord + Borrow<str>, Ser: Any
{
    fn index_mut(&mut self, name: &'a Str) -> &mut Self::Output {
        self.get_service_mut(name.borrow()).unwrap()
    }
}

unsafe impl<'a, Str, Ser: ?Sized> MultiIndexable<&'a Str> for ServiceMap<Ser>
    where Str: Ord + Borrow<str>, Ser: Any
{}

// ++++++++++++++++++++ ServiceRegister ++++++++++++++++++++

pub struct ServiceRegister<Ser: Any + ?Sized = DefaultBase>{
    services: ServiceMap<Ser>
}

// TODO: remove duplicated code
impl<Ser: Any + ?Sized> ServiceRegister<Ser> {
    pub fn new() -> ServiceRegister<Ser> {
        ServiceRegister{
            services: ServiceMap{ options: BTreeMap::new() }
        }
    }

    pub fn services(&self) -> &ServiceMap<Ser> { &self.services }
    pub fn services_mut(&mut self) -> &mut ServiceMap<Ser> { &mut self.services }
    pub fn into_services(self) -> ServiceMap<Ser> { self.services }

    /// Adds a option to the register.
    pub fn add_option(&mut self, name: String){
        assert!(!self.services.options.contains_key(&name), "option '{}' already exists!", &name);

        self.services.options.insert(name, WiringOption::Multi{
            wired: None, alternatives: Vec::new()
        });
    }

    /// Adds an alternative to an option of the register.
    pub fn add_alternative(&mut self, opt_name: &str, alt_name: String, service: Box<Ser>){
        let option = self.services.options.get_mut(opt_name);
        let option = option.expect(&format!("option '{}' doesn't exist", &opt_name));

        option.add_alternative(alt_name, service);
    }

    /// Wires an alternative of an option of this register.
    pub fn wire_alternative(&mut self, opt_name: &str, alt_name: &str){
        let option = self.services.options.get_mut(opt_name);
        let option = option.expect(&format!("option '{}' doesn't exist", &opt_name));

        option.wire_alternative(alt_name);
    }

    /// Adds a single alternative option to the register.
    pub fn add_single(&mut self, name: String, service: Box<Ser>){
        assert!(self.services.options.contains_key(&name), "option '{}' already exists!", &name);

        self.services.options.insert(name, WiringOption::Single(service));
    }
}

<commit_msg>rename GetSerectError => GetServiceError<commit_after>use qdowncast::QDowncastable;
use qindex_multi::MultiIndexable;

use std::any::{Any, TypeId};
use std::borrow::Borrow;
use std::collections::btree_map::{self, BTreeMap};
use std::ops::{Index, IndexMut};

// ++++++++++++++++++++ ServiceReflect ++++++++++++++++++++

/// Our `Reflect`-derivative.
/// This supplies necessary information for retrieving an service at compile-time.
pub trait ServiceReflect: Any {
    fn option_name() -> &'static str;
}

// ++++++++++++++++++++ GetServiceError ++++++++++++++++++++

#[derive(Debug, Clone)]
pub enum GetServiceError<'a> {
    TypeMismatch{ option_name: &'a str, expected: TypeId, found: TypeId },
    MissingOption(&'a str),
}

impl<'a> GetServiceError<'a> {
    pub fn type_mismatch<Expected>(found: TypeId) -> GetServiceError<'static>
        where Expected: ServiceReflect
    {
        GetServiceError::TypeMismatch{
            option_name: Expected::option_name(),
            expected: TypeId::of::<Expected>(),
            found: found,
        }
    }
}

pub type GetSerectResult<'a, T> = Result<T, GetServiceError<'a>>;

// ++++++++++++++++++++ WiringOption ++++++++++++++++++++

/// TODO expose this to the user?
enum WiringOption<Ser: Any + ?Sized> {
    /// An option with zero or more alternatives. May be wired to one of its services.
    Multi{
        wired: Option<usize>,
        alternatives: Vec<(String, Box<Ser>)>,
    },
    /// A single alternative option. Is always wired to exactly one service.
    Single(Box<Ser>),
}

impl<Ser: Any + ?Sized> WiringOption<Ser> {
    fn has_alternative(&self, alt_name: &str) -> bool {
        match self {
            &WiringOption::Multi{ ref alternatives, .. } => {
                alternatives.iter().any(|e| &*e.0 == alt_name)
            }
            _ => false,
        }
    }

    fn add_alternative(&mut self, alt_name: String, service: Box<Ser>){
        assert!(!self.has_alternative(&alt_name),
                "Alternative '{}' already exists,", alt_name);

        match self {
            &mut WiringOption::Multi{ ref mut alternatives, .. } => {
                alternatives.push((alt_name, service));
            }
            _ => {
                panic!("can't add alternative '{}' to single alternative option", alt_name);
            }
        }
    }

    fn wire_alternative(&mut self, alt_name: &str) {
        assert!(self.has_alternative(&alt_name),
                "Can't wire missing alternative '{}'", alt_name);

        match self {
            &mut WiringOption::Multi{ ref mut wired, ref alternatives } => {
                *wired = Some(alternatives.iter().position(|e| &*e.0 == alt_name).unwrap());
            }
            _ => { unreachable!() }
        }
    }

    fn service(&self) -> Option<&Ser> {
        match self {
            &WiringOption::Single(ref service) => Some(&**service),
            &WiringOption::Multi{ wired, ref alternatives } => match wired {
                Some(idx) => Some(&*alternatives[idx].1),
                None => None,
            }
        }
    }

    fn service_mut(&mut self) -> Option<&mut Ser> {
        match self {
            &mut WiringOption::Single(ref mut service) => Some(&mut**service),
            &mut WiringOption::Multi{ wired, ref mut alternatives } => match wired {
                Some(idx) => Some(&mut*alternatives[idx].1),
                None => None,
            }
        }
    }
}

// ++++++++++++++++++++ ServiceMap ++++++++++++++++++++

pub trait DefaultBase: Any {}
impl<T: Any + ?Sized> DefaultBase for T {}
qdowncastable!(DefaultBase);
qdowncast_methods!(DefaultBase);

pub struct ServiceMap<Ser: Any + ?Sized = DefaultBase> {
    options: BTreeMap<String, WiringOption<Ser>>,
}

impl<Ser: Any + ?Sized> ServiceMap<Ser> {
    /// Gets the service wired to option `opt_name` immutably.
    pub fn get_service(&self, opt_name: &str) -> Option<&Ser> {
        self.options.get(opt_name).and_then(|option| option.service())
    }

    /// Gets the service wired to option `opt_name` mutably.
    pub fn get_service_mut(&mut self, opt_name: &str) -> Option<&mut Ser> {
        self.options.get_mut(opt_name).and_then(|option| option.service_mut())
    }

    /// Gets the service wired to option `opt_name` immutably, then tries to downcast it.
    pub fn get<T>(&self) -> GetSerectResult<&T>
        where T: ServiceReflect, Ser: QDowncastable<T>
    {
        match self.get_service(T::option_name()) {
            Some(base) => {
                let ty = (&*base).get_type_id();
                match QDowncastable::downcast_ref(base) {
                    Some(ret) => Ok(ret),
                    None => Err(GetServiceError::type_mismatch::<T>(ty))
                }
            }
            None => Err(GetServiceError::MissingOption(T::option_name()))
        }
    }

    /// Gets the service wired to option `opt_name` mutably, then tries to downcast it.
    pub fn get_mut<T>(&mut self) -> GetSerectResult<&mut T>
        where T: ServiceReflect, Ser: QDowncastable<T>
    {
        match self.get_service_mut(T::option_name()) {
            Some(base) => {
                let ty = (&*base).get_type_id();
                match QDowncastable::downcast_mut(base) {
                    Some(ret) => Ok(ret),
                    None => Err(GetServiceError::type_mismatch::<T>(ty))
                }
            }
            None => Err(GetServiceError::MissingOption(T::option_name()))
        }
    }

    /// Iterate over all wired services immutably.
    pub fn iter(&self) -> Iter<Ser> {
        Iter{ options: self.options.iter() }
    }

    /// Iterate over all wired services mutably.
    pub fn iter_mut(&mut self) -> IterMut<Ser> {
        IterMut{ options: self.options.iter_mut() }
    }
}

/// TODO impl more Iterator-traits?
#[derive(Clone)]
pub struct Iter<'a, Ser: Any + ?Sized = DefaultBase> {
    options: btree_map::Iter<'a, String, WiringOption<Ser>>,
}

impl<'a, Ser: Any + ?Sized> Iterator for Iter<'a, Ser> {
    type Item = (&'a str, &'a Ser);
    fn next(&mut self) -> Option<Self::Item> {
        match self.options.next() {
            Some((opt_name, option)) => match option.service() {
                Some(service) => Some((&opt_name, service)),
                None => self.next(),
            },
            None => None,
        }
    }
}

/// TODO impl more Iterator-traits?
pub struct IterMut<'a, Ser: Any + ?Sized = DefaultBase> {
    options: btree_map::IterMut<'a, String, WiringOption<Ser>>,
}

impl<'a, Ser: Any + ?Sized> Iterator for IterMut<'a, Ser> {
    type Item = (&'a str, &'a mut Ser);
    fn next(&mut self) -> Option<Self::Item> {
        match self.options.next() {
            Some((opt_name, option)) => match option.service_mut() {
                Some(service) => Some((&opt_name, service)),
                None => self.next(),
            },
            None => None,
        }
    }
}

impl<'a, Ser: Any + ?Sized> IntoIterator for &'a ServiceMap<Ser> {
    type Item = <Self::IntoIter as Iterator>::Item;
    type IntoIter = Iter<'a, Ser>;
    fn into_iter(self) -> Self::IntoIter { self.iter() }
}

impl<'a, Ser: Any + ?Sized> IntoIterator for &'a mut ServiceMap<Ser> {
    type Item = <Self::IntoIter as Iterator>::Item;
    type IntoIter = IterMut<'a, Ser>;
    fn into_iter(self) -> Self::IntoIter { self.iter_mut() }
}

impl<'a, Str, Ser: ?Sized> Index<&'a Str> for ServiceMap<Ser>
    where Str: Ord + Borrow<str>, Ser: Any
{
    type Output = Ser;
    fn index(&self, name: &'a Str) -> &Self::Output {
        self.get_service(name.borrow()).unwrap()
    }
}

impl<'a, Str, Ser: ?Sized> IndexMut<&'a Str> for ServiceMap<Ser>
    where Str: Ord + Borrow<str>, Ser: Any
{
    fn index_mut(&mut self, name: &'a Str) -> &mut Self::Output {
        self.get_service_mut(name.borrow()).unwrap()
    }
}

unsafe impl<'a, Str, Ser: ?Sized> MultiIndexable<&'a Str> for ServiceMap<Ser>
    where Str: Ord + Borrow<str>, Ser: Any
{}

// ++++++++++++++++++++ ServiceRegister ++++++++++++++++++++

pub struct ServiceRegister<Ser: Any + ?Sized = DefaultBase>{
    services: ServiceMap<Ser>
}

// TODO: remove duplicated code
impl<Ser: Any + ?Sized> ServiceRegister<Ser> {
    pub fn new() -> ServiceRegister<Ser> {
        ServiceRegister{
            services: ServiceMap{ options: BTreeMap::new() }
        }
    }

    pub fn services(&self) -> &ServiceMap<Ser> { &self.services }
    pub fn services_mut(&mut self) -> &mut ServiceMap<Ser> { &mut self.services }
    pub fn into_services(self) -> ServiceMap<Ser> { self.services }

    /// Adds a option to the register.
    pub fn add_option(&mut self, name: String){
        assert!(!self.services.options.contains_key(&name), "option '{}' already exists!", &name);

        self.services.options.insert(name, WiringOption::Multi{
            wired: None, alternatives: Vec::new()
        });
    }

    /// Adds an alternative to an option of the register.
    pub fn add_alternative(&mut self, opt_name: &str, alt_name: String, service: Box<Ser>){
        let option = self.services.options.get_mut(opt_name);
        let option = option.expect(&format!("option '{}' doesn't exist", &opt_name));

        option.add_alternative(alt_name, service);
    }

    /// Wires an alternative of an option of this register.
    pub fn wire_alternative(&mut self, opt_name: &str, alt_name: &str){
        let option = self.services.options.get_mut(opt_name);
        let option = option.expect(&format!("option '{}' doesn't exist", &opt_name));

        option.wire_alternative(alt_name);
    }

    /// Adds a single alternative option to the register.
    pub fn add_single(&mut self, name: String, service: Box<Ser>){
        assert!(self.services.options.contains_key(&name), "option '{}' already exists!", &name);

        self.services.options.insert(name, WiringOption::Single(service));
    }
}

<|endoftext|>


<commit_before>use internal::ColorComponent;
use quack::{ GetFrom, Get, SetAt, Set, Pair };
use context::{ Context, Transform, ViewTransform };
use vecmath::{
    get_scale,
    hsv,
    identity,
    margin_rectangle,
    multiply,
    orient,
    relative_rectangle,
    relative_source_rectangle,
    rotate_radians,
    scale,
    shear,
    translate,
    Matrix2d,
    Scalar,
    Vec2d,
};
use radians::Radians;
use Color;
use Rect;
use SrcRect;

/// Implemented by contexts that contains color.
pub trait Colored: Sized {
    /// Multiplies with red, green, blue and alpha values.
    fn mul_rgba(
        &self,
        r: ColorComponent,
        g: ColorComponent,
        b: ColorComponent,
        a: ColorComponent
    ) -> Self;

    /// Mixes the current color with white.
    ///
    /// 0 is black and 1 is white.
    #[inline(always)]
    fn tint(&self, f: ColorComponent) -> Self {
        self.mul_rgba(f, f, f, 1.0)
    }

    /// Mixes the current color with black.
    ///
    /// 0 is white and 1 is black.
    #[inline(always)]
    fn shade(&self, f: ColorComponent) -> Self {
        let f = 1.0 - f;
        self.mul_rgba(f, f, f, 1.0)
    }

    /// Rotates hue by degrees.
    #[inline(always)]
    fn hue_deg(&self, angle: ColorComponent) -> Self {
        let pi: ColorComponent = Radians::_180();
        self.hue_rad(angle * pi / 180.0)
    }

    /// Rotates hue by radians.
    fn hue_rad(&self, angle: ColorComponent) -> Self;
}

impl<T: Get<Color> + Set<Color> + Clone> Colored for T {
    #[inline(always)]
    fn mul_rgba(
        &self,
        r: ColorComponent,
        g: ColorComponent,
        b: ColorComponent,
        a: ColorComponent
    ) -> Self {
        let Color(col) = self.get();
        self.clone().set(Color([col[0] * r, col[1] * g, col[2] * b, col[3] * a]))
    }

    #[inline(always)]
    fn hue_rad(&self, angle: ColorComponent) -> Self {
        let Color(val) = self.get();
        self.clone().set(Color(hsv(val, angle, 1.0, 1.0)))
    }
}

/// Should be implemented by contexts that have rectangle information.
pub trait Rectangled: Sized {
    /// Shrinks the current rectangle equally by all sides.
    fn margin(&self, m: Scalar) -> Self;

    /// Expands the current rectangle equally by all sides.
    #[inline(always)]
    fn expand(&self, m: Scalar) -> Self {
        self.margin(-m)
    }

    /// Moves to a relative rectangle using the current rectangle as tile.
    fn rel(&self, x: Scalar, y: Scalar) -> Self;
}

impl<T: Get<Rect> + Set<Rect> + Clone> Rectangled for T {
    #[inline(always)]
    fn margin(&self, m: Scalar) -> Self {
        let Rect(val) = self.get();
        self.clone().set(Rect(margin_rectangle(val, m)))
    }

    #[inline(always)]
    fn rel(&self, x: Scalar, y: Scalar) -> Self {
        let Rect(val) = self.get();
        self.clone().set(Rect(relative_rectangle(val, [x, y])))
    }
}

/// Should be implemented by contexts that
/// have source rectangle information.
pub trait SourceRectangled {
    /// Adds a source rectangle.
    fn src_rect(&self, x: i32, y: i32, w: i32, h: i32) -> Self;

    /// Moves to a relative source rectangle using
    /// the current source rectangle as tile.
    fn src_rel(&self, x: i32, y: i32) -> Self;

    /// Flips the source rectangle horizontally.
    fn src_flip_h(&self) -> Self;

    /// Flips the source rectangle vertically.
    fn src_flip_v(&self) -> Self;

    /// Flips the source rectangle horizontally and vertically.
    fn src_flip_hv(&self) -> Self;
}

impl<T: Get<SrcRect>
      + Set<SrcRect>
      + Clone
> SourceRectangled for T {
    #[inline(always)]
    fn src_rect(&self, x: i32, y: i32, w: i32, h: i32) -> Self {
        self.clone().set(SrcRect([x, y, w, h]))
    }

    #[inline(always)]
    fn src_rel(&self, x: i32, y: i32) -> Self {
        let SrcRect(val) = self.get();
        self.clone().set(SrcRect(
            relative_source_rectangle(val, x, y)
        ))
    }

    #[inline(always)]
    fn src_flip_h(&self) -> Self {
        let SrcRect(source_rect) = self.get();
        self.clone().set(SrcRect([
            source_rect[0] + source_rect[2],
            source_rect[1],
            -source_rect[2],
            source_rect[3]
        ]))
    }

    #[inline(always)]
    fn src_flip_v(&self) -> Self {
        let SrcRect(source_rect) = self.get();
        self.clone().set(SrcRect([
            source_rect[0],
            source_rect[1] + source_rect[3],
            source_rect[2],
            -source_rect[3]
        ]))
    }

    #[inline(always)]
    fn src_flip_hv(&self) -> Self {
        let SrcRect(source_rect) = self.get();
        self.clone().set(SrcRect([
            source_rect[0] + source_rect[2],
            source_rect[1] + source_rect[3],
            -source_rect[2],
            -source_rect[3]
        ]))
    }
}

/// Implemented by contexts that can transform.
pub trait Transformed: Sized {
    /// Appends transform to the current one.
    fn append_transform(self, transform: Matrix2d) -> Self;

    /// Prepends transform to the current one.
    fn prepend_transform(self, transform: Matrix2d) -> Self;

    /// Translate x an y in local coordinates.
    fn trans(self, x: Scalar, y: Scalar) -> Self;

    /// Rotates degrees in local coordinates.
    #[inline(always)]
    fn rot_deg(self, angle: Scalar) -> Self {
        let pi: Scalar = Radians::_180();
        self.rot_rad(angle * pi / 180.0)
    }

    /// Rotate radians in local coordinates.
    fn rot_rad(self, angle: Scalar) -> Self;

    /// Orients x axis to look at point locally.
    ///
    /// Leaves x axis unchanged if the point to
    /// look at is the origin.
    fn orient(self, x: Scalar, y: Scalar) -> Self;

    /// Scales in local coordinates.
    fn scale(self, sx: Scalar, sy: Scalar) -> Self;

    /// Scales in both directions in local coordinates.
    #[inline(always)]
    fn zoom(self, s: Scalar) -> Self {
        self.scale(s, s)
    }

    /// Flips vertically in local coordinates.
    #[inline(always)]
    fn flip_v(self) -> Self {
        self.scale(1.0, -1.0)
    }

    /// Flips horizontally in local coordinates.
    #[inline(always)]
    fn flip_h(self) -> Self {
        self.scale(-1.0, 1.0)
    }

    /// Flips horizontally and vertically in local coordinates.
    #[inline(always)]
    fn flip_hv(self) -> Self {
        self.scale(-1.0, -1.0)
    }

    /// Shears in local coordinates.
    fn shear(self, v: Vec2d) -> Self;
}

impl Transformed for Matrix2d
{
    #[inline(always)]
    fn append_transform(self, transform: Matrix2d) -> Self {
        multiply(self, transform)
    }

    #[inline(always)]
    fn prepend_transform(self, transform: Matrix2d) -> Self {
        multiply(transform, self)
    }

    #[inline(always)]
    fn trans(self, x: Scalar, y: Scalar) -> Self {
        let trans = translate([x, y]);
        multiply(self, trans)
    }

    #[inline(always)]
    fn rot_rad(self, angle: Scalar) -> Self {
        let rot = rotate_radians(angle);
        multiply(self, rot)
    }

    #[inline(always)]
    fn orient(self, x: Scalar, y: Scalar) -> Self {
        let orient = orient(x, y);
        multiply(self, orient)
    }

    #[inline(always)]
    fn scale(self, sx: Scalar, sy: Scalar) -> Self {
        let scale = scale(sx, sy);
        multiply(self, scale)
    }

    #[inline(always)]
    fn shear(self, v: Vec2d) -> Self {
        let shear = shear(v);
        multiply(self, shear)
    }
}

impl Transformed for Context
{
    #[inline(always)]
    fn append_transform(mut self, transform: Matrix2d) -> Self {
        self.transform = self.transform.append_transform(transform);
        self
    }

    #[inline(always)]
    fn prepend_transform(mut self, transform: Matrix2d) -> Self {
        self.transform = self.transform.prepend_transform(transform);
        self
    }

    #[inline(always)]
    fn trans(mut self, x: Scalar, y: Scalar) -> Self {
        self.transform = self.transform.trans(x, y);
        self
    }

    #[inline(always)]
    fn rot_rad(mut self, angle: Scalar) -> Self {
        self.transform = self.transform.rot_rad(angle);
        self
    }

    #[inline(always)]
    fn orient(mut self, x: Scalar, y: Scalar) -> Self {
        self.transform = self.transform.orient(x, y);
        self
    }

    #[inline(always)]
    fn scale(mut self, sx: Scalar, sy: Scalar) -> Self {
        self.transform = self.transform.scale(sx, sy);
        self
    }

    #[inline(always)]
    fn shear(mut self, v: Vec2d) -> Self {
        self.transform = self.transform.shear(v);
        self
    }
}

/// Should be implemented by contexts that
/// draws something relative to view.
pub trait ViewTransformed {
    /// Moves the current transform to the view coordinate system.
    ///
    /// This is usually [0.0, 0.0] in the upper left corner
    /// with the x axis pointing to the right
    /// and the y axis pointing down.
    #[inline(always)]
    fn view(&self) -> Self;

    /// Moves the current transform to the default coordinate system.
    ///
    /// This is usually [0.0, 0.0] in the center
    /// with the x axis pointing to the right
    /// and the y axis pointing up.
    fn reset(&self) -> Self;

    /// Stores the current transform as new view.
    fn store_view(&self) -> Self;

    /// Computes the current view size.
    fn get_view_size(&self) -> (Scalar, Scalar);
}

impl<T: Clone> ViewTransformed for T
    where
        (ViewTransform, Self): Pair<Data = ViewTransform, Object = Self>
            + GetFrom + SetAt,
        (Transform, Self): Pair<Data = Transform, Object = Self>
            + GetFrom + SetAt,
{
    #[inline(always)]
    fn view(&self) -> Self {
        let ViewTransform(mat) = self.get();
        self.clone().set(Transform(mat))
    }

    #[inline(always)]
    fn reset(&self) -> Self {
        self.clone().set(Transform(identity()))
    }

    #[inline(always)]
    fn store_view(&self) -> Self {
        let Transform(mat) = self.get();
        self.clone().set(ViewTransform(mat))
    }

    #[inline(always)]
    fn get_view_size(&self) -> (Scalar, Scalar) {
        let ViewTransform(mat) = self.get();
        let scale = get_scale(mat);
        (2.0 / scale[0], 2.0 / scale[1])
    }
}
<commit_msg>Implemented `ViewTransformed` for `Context`<commit_after>use internal::ColorComponent;
use quack::{ Get, Set };
use context::Context;
use vecmath::{
    get_scale,
    hsv,
    identity,
    margin_rectangle,
    multiply,
    orient,
    relative_rectangle,
    relative_source_rectangle,
    rotate_radians,
    scale,
    shear,
    translate,
    Matrix2d,
    Scalar,
    Vec2d,
};
use radians::Radians;
use Color;
use Rect;
use SrcRect;

/// Implemented by contexts that contains color.
pub trait Colored: Sized {
    /// Multiplies with red, green, blue and alpha values.
    fn mul_rgba(
        &self,
        r: ColorComponent,
        g: ColorComponent,
        b: ColorComponent,
        a: ColorComponent
    ) -> Self;

    /// Mixes the current color with white.
    ///
    /// 0 is black and 1 is white.
    #[inline(always)]
    fn tint(&self, f: ColorComponent) -> Self {
        self.mul_rgba(f, f, f, 1.0)
    }

    /// Mixes the current color with black.
    ///
    /// 0 is white and 1 is black.
    #[inline(always)]
    fn shade(&self, f: ColorComponent) -> Self {
        let f = 1.0 - f;
        self.mul_rgba(f, f, f, 1.0)
    }

    /// Rotates hue by degrees.
    #[inline(always)]
    fn hue_deg(&self, angle: ColorComponent) -> Self {
        let pi: ColorComponent = Radians::_180();
        self.hue_rad(angle * pi / 180.0)
    }

    /// Rotates hue by radians.
    fn hue_rad(&self, angle: ColorComponent) -> Self;
}

impl<T: Get<Color> + Set<Color> + Clone> Colored for T {
    #[inline(always)]
    fn mul_rgba(
        &self,
        r: ColorComponent,
        g: ColorComponent,
        b: ColorComponent,
        a: ColorComponent
    ) -> Self {
        let Color(col) = self.get();
        self.clone().set(Color([col[0] * r, col[1] * g, col[2] * b, col[3] * a]))
    }

    #[inline(always)]
    fn hue_rad(&self, angle: ColorComponent) -> Self {
        let Color(val) = self.get();
        self.clone().set(Color(hsv(val, angle, 1.0, 1.0)))
    }
}

/// Should be implemented by contexts that have rectangle information.
pub trait Rectangled: Sized {
    /// Shrinks the current rectangle equally by all sides.
    fn margin(&self, m: Scalar) -> Self;

    /// Expands the current rectangle equally by all sides.
    #[inline(always)]
    fn expand(&self, m: Scalar) -> Self {
        self.margin(-m)
    }

    /// Moves to a relative rectangle using the current rectangle as tile.
    fn rel(&self, x: Scalar, y: Scalar) -> Self;
}

impl<T: Get<Rect> + Set<Rect> + Clone> Rectangled for T {
    #[inline(always)]
    fn margin(&self, m: Scalar) -> Self {
        let Rect(val) = self.get();
        self.clone().set(Rect(margin_rectangle(val, m)))
    }

    #[inline(always)]
    fn rel(&self, x: Scalar, y: Scalar) -> Self {
        let Rect(val) = self.get();
        self.clone().set(Rect(relative_rectangle(val, [x, y])))
    }
}

/// Should be implemented by contexts that
/// have source rectangle information.
pub trait SourceRectangled {
    /// Adds a source rectangle.
    fn src_rect(&self, x: i32, y: i32, w: i32, h: i32) -> Self;

    /// Moves to a relative source rectangle using
    /// the current source rectangle as tile.
    fn src_rel(&self, x: i32, y: i32) -> Self;

    /// Flips the source rectangle horizontally.
    fn src_flip_h(&self) -> Self;

    /// Flips the source rectangle vertically.
    fn src_flip_v(&self) -> Self;

    /// Flips the source rectangle horizontally and vertically.
    fn src_flip_hv(&self) -> Self;
}

impl<T: Get<SrcRect>
      + Set<SrcRect>
      + Clone
> SourceRectangled for T {
    #[inline(always)]
    fn src_rect(&self, x: i32, y: i32, w: i32, h: i32) -> Self {
        self.clone().set(SrcRect([x, y, w, h]))
    }

    #[inline(always)]
    fn src_rel(&self, x: i32, y: i32) -> Self {
        let SrcRect(val) = self.get();
        self.clone().set(SrcRect(
            relative_source_rectangle(val, x, y)
        ))
    }

    #[inline(always)]
    fn src_flip_h(&self) -> Self {
        let SrcRect(source_rect) = self.get();
        self.clone().set(SrcRect([
            source_rect[0] + source_rect[2],
            source_rect[1],
            -source_rect[2],
            source_rect[3]
        ]))
    }

    #[inline(always)]
    fn src_flip_v(&self) -> Self {
        let SrcRect(source_rect) = self.get();
        self.clone().set(SrcRect([
            source_rect[0],
            source_rect[1] + source_rect[3],
            source_rect[2],
            -source_rect[3]
        ]))
    }

    #[inline(always)]
    fn src_flip_hv(&self) -> Self {
        let SrcRect(source_rect) = self.get();
        self.clone().set(SrcRect([
            source_rect[0] + source_rect[2],
            source_rect[1] + source_rect[3],
            -source_rect[2],
            -source_rect[3]
        ]))
    }
}

/// Implemented by contexts that can transform.
pub trait Transformed: Sized {
    /// Appends transform to the current one.
    fn append_transform(self, transform: Matrix2d) -> Self;

    /// Prepends transform to the current one.
    fn prepend_transform(self, transform: Matrix2d) -> Self;

    /// Translate x an y in local coordinates.
    fn trans(self, x: Scalar, y: Scalar) -> Self;

    /// Rotates degrees in local coordinates.
    #[inline(always)]
    fn rot_deg(self, angle: Scalar) -> Self {
        let pi: Scalar = Radians::_180();
        self.rot_rad(angle * pi / 180.0)
    }

    /// Rotate radians in local coordinates.
    fn rot_rad(self, angle: Scalar) -> Self;

    /// Orients x axis to look at point locally.
    ///
    /// Leaves x axis unchanged if the point to
    /// look at is the origin.
    fn orient(self, x: Scalar, y: Scalar) -> Self;

    /// Scales in local coordinates.
    fn scale(self, sx: Scalar, sy: Scalar) -> Self;

    /// Scales in both directions in local coordinates.
    #[inline(always)]
    fn zoom(self, s: Scalar) -> Self {
        self.scale(s, s)
    }

    /// Flips vertically in local coordinates.
    #[inline(always)]
    fn flip_v(self) -> Self {
        self.scale(1.0, -1.0)
    }

    /// Flips horizontally in local coordinates.
    #[inline(always)]
    fn flip_h(self) -> Self {
        self.scale(-1.0, 1.0)
    }

    /// Flips horizontally and vertically in local coordinates.
    #[inline(always)]
    fn flip_hv(self) -> Self {
        self.scale(-1.0, -1.0)
    }

    /// Shears in local coordinates.
    fn shear(self, v: Vec2d) -> Self;
}

impl Transformed for Matrix2d {
    #[inline(always)]
    fn append_transform(self, transform: Matrix2d) -> Self {
        multiply(self, transform)
    }

    #[inline(always)]
    fn prepend_transform(self, transform: Matrix2d) -> Self {
        multiply(transform, self)
    }

    #[inline(always)]
    fn trans(self, x: Scalar, y: Scalar) -> Self {
        let trans = translate([x, y]);
        multiply(self, trans)
    }

    #[inline(always)]
    fn rot_rad(self, angle: Scalar) -> Self {
        let rot = rotate_radians(angle);
        multiply(self, rot)
    }

    #[inline(always)]
    fn orient(self, x: Scalar, y: Scalar) -> Self {
        let orient = orient(x, y);
        multiply(self, orient)
    }

    #[inline(always)]
    fn scale(self, sx: Scalar, sy: Scalar) -> Self {
        let scale = scale(sx, sy);
        multiply(self, scale)
    }

    #[inline(always)]
    fn shear(self, v: Vec2d) -> Self {
        let shear = shear(v);
        multiply(self, shear)
    }
}

impl Transformed for Context {
    #[inline(always)]
    fn append_transform(mut self, transform: Matrix2d) -> Self {
        self.transform = self.transform.append_transform(transform);
        self
    }

    #[inline(always)]
    fn prepend_transform(mut self, transform: Matrix2d) -> Self {
        self.transform = self.transform.prepend_transform(transform);
        self
    }

    #[inline(always)]
    fn trans(mut self, x: Scalar, y: Scalar) -> Self {
        self.transform = self.transform.trans(x, y);
        self
    }

    #[inline(always)]
    fn rot_rad(mut self, angle: Scalar) -> Self {
        self.transform = self.transform.rot_rad(angle);
        self
    }

    #[inline(always)]
    fn orient(mut self, x: Scalar, y: Scalar) -> Self {
        self.transform = self.transform.orient(x, y);
        self
    }

    #[inline(always)]
    fn scale(mut self, sx: Scalar, sy: Scalar) -> Self {
        self.transform = self.transform.scale(sx, sy);
        self
    }

    #[inline(always)]
    fn shear(mut self, v: Vec2d) -> Self {
        self.transform = self.transform.shear(v);
        self
    }
}

/// Should be implemented by contexts that
/// draws something relative to view.
pub trait ViewTransformed {
    /// Moves the current transform to the view coordinate system.
    ///
    /// This is usually [0.0, 0.0] in the upper left corner
    /// with the x axis pointing to the right
    /// and the y axis pointing down.
    #[inline(always)]
    fn view(self) -> Self;

    /// Moves the current transform to the default coordinate system.
    ///
    /// This is usually [0.0, 0.0] in the center
    /// with the x axis pointing to the right
    /// and the y axis pointing up.
    fn reset(self) -> Self;

    /// Stores the current transform as new view.
    fn store_view(self) -> Self;

    /// Computes the current view size.
    fn get_view_size(&self) -> (Scalar, Scalar);
}

impl ViewTransformed for Context {
    #[inline(always)]
    fn view(mut self) -> Self {
        self.transform = self.view;
        self
    }

    #[inline(always)]
    fn reset(mut self) -> Self {
        self.transform = identity();
        self
    }

    #[inline(always)]
    fn store_view(mut self) -> Self {
        self.view = self.transform;
        self
    }

    #[inline(always)]
    fn get_view_size(&self) -> (Scalar, Scalar) {
        let scale = get_scale(self.view);
        (2.0 / scale[0], 2.0 / scale[1])
    }
}
<|endoftext|>


<commit_before>use console;
use glium;
use glium::backend::glutin_backend::GlutinFacade as Display;
use mvp;
use pixset::PixLike;
use shaders;
use units;
use utils;

fn get_screen_size(display: &Display) -> units::Size2D {
    let factor = display.get_window().unwrap().hidpi_factor();
    let (width, height) = display.get_framebuffer_dimensions();
    units::Size2D::new(
        (width as f32 / factor) as i32,
        (height as f32 / factor) as i32,
    )
}

pub struct Renderer<'a> {
    pub screen_size: units::Size2D,
    pub size: units::Size2D,
    pub display: &'a Display,
    pub program: glium::Program,
    pub indices: glium::IndexBuffer<u16>,
    pub texture: glium::texture::Texture2d,
    pub vertex_buffer: console::VertexBuffer,
}

impl<'a> Renderer<'a> {
    pub fn new<P: PixLike>(display: &'a Display, tileset: &[u8], empty: P) -> Self {
        let screen_size = get_screen_size(display);
        let size = units::Size2D::new(
            (screen_size.width / empty.tile_size()),
            (screen_size.height / empty.tile_size()),
        );

        let program = program(display);
        let indices = indices(display, size);
        let texture = texture(display, tileset);
        let vertex_buffer = console::VertexBuffer::new(size, empty);

        Renderer {
            size: size,
            screen_size: screen_size,
            display: display,
            program: program,
            indices: indices,
            texture: texture,
            vertex_buffer: vertex_buffer,
        }
    }

    pub fn render(&self) {
        use glium::Surface;

        let vb = glium::VertexBuffer::new(self.display, &self.vertex_buffer.data()).unwrap();

        let cam_uniforms = {
            let mat4_id = utils::mat4_id();
            let ortho_projection = utils::ortho_projection(self.screen_size);

            // 1, 0, 0, X
            // 0, 1, 0, Y
            // 0, 0, 1, 0
            // 0, 0, 0, 1

            let cam = [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0],
            ]; // X, Y

            let tileset = self.texture
                .sampled()
                .magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest);

            uniform! {
                mvp: mvp::model_view_projection(mat4_id, cam, ortho_projection),
                tileset: tileset,
            }
        };

        let mut target = self.display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        target
            .draw(
                &vb,
                &self.indices,
                &self.program,
                &cam_uniforms,
                &Default::default(),
            )
            .unwrap();
        target.finish().unwrap();
    }

    pub fn set<P: PixLike>(&mut self, screen_loc: units::ScreenTile2D, tile: console::Tile<P>) {
        let coords = tile.pix.get();
        self.vertex_buffer.set(screen_loc, tile, coords);
    }

    pub fn blit_console<P: PixLike>(
        &mut self,
        screen_loc: units::ScreenTile2D,
        console: &console::Console<P>,
    ) {
        // TODO iter ?
        for y in 0..console.get_height() {
            for x in 0..console.get_width() {
                let loc = screen_loc + units::ScreenTile2D::new(x as i32, y as i32);
                let tile = console.get_tile(x, y);
                let coords = tile.pix.get();
                self.vertex_buffer.set(loc, tile, coords)
            }
        }
    }
}

fn program(display: &Display) -> glium::Program {
    glium::Program::from_source(
        display as &glium::backend::Facade,
        &shaders::VERTEX,
        &shaders::FRAGMENT,
        None,
    ).unwrap()
}

fn indices(display: &Display, size: units::Size2D) -> glium::IndexBuffer<u16> {
    use glium::index::PrimitiveType;

    let indices = utils::indices((size.width * size.height) as usize);
    glium::IndexBuffer::new(
        display as &glium::backend::Facade,
        PrimitiveType::TrianglesList,
        &indices,
    ).unwrap()
}

fn texture(display: &Display, tileset: &[u8]) -> glium::texture::Texture2d {
    use glium::{backend, texture};

    let image = utils::read_png_to_image(tileset);
    let image_dimensions = image.dimensions();
    let texture = texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions);
    texture::Texture2d::new(display as &backend::Facade, texture).unwrap()
}
<commit_msg>chore(renderer): accept anything that can be turned into [i32; 2]<commit_after>use console;
use glium;
use glium::backend::glutin_backend::GlutinFacade as Display;
use mvp;
use pixset::PixLike;
use shaders;
use units;
use utils;

fn get_screen_size(display: &Display) -> units::Size2D {
    let factor = display.get_window().unwrap().hidpi_factor();
    let (width, height) = display.get_framebuffer_dimensions();
    units::Size2D::new(
        (width as f32 / factor) as i32,
        (height as f32 / factor) as i32,
    )
}

pub struct Renderer<'a> {
    pub screen_size: units::Size2D,
    pub size: units::Size2D,
    pub display: &'a Display,
    pub program: glium::Program,
    pub indices: glium::IndexBuffer<u16>,
    pub texture: glium::texture::Texture2d,
    pub vertex_buffer: console::VertexBuffer,
}

impl<'a> Renderer<'a> {
    pub fn new<P: PixLike>(display: &'a Display, tileset: &[u8], empty: P) -> Self {
        let screen_size = get_screen_size(display);
        let size = units::Size2D::new(
            (screen_size.width / empty.tile_size()),
            (screen_size.height / empty.tile_size()),
        );

        let program = program(display);
        let indices = indices(display, size);
        let texture = texture(display, tileset);
        let vertex_buffer = console::VertexBuffer::new(size, empty);

        Renderer {
            size: size,
            screen_size: screen_size,
            display: display,
            program: program,
            indices: indices,
            texture: texture,
            vertex_buffer: vertex_buffer,
        }
    }

    pub fn render(&self) {
        use glium::Surface;

        let vb = glium::VertexBuffer::new(self.display, &self.vertex_buffer.data()).unwrap();

        let cam_uniforms = {
            let mat4_id = utils::mat4_id();
            let ortho_projection = utils::ortho_projection(self.screen_size);

            // 1, 0, 0, X
            // 0, 1, 0, Y
            // 0, 0, 1, 0
            // 0, 0, 0, 1

            let cam = [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0],
            ]; // X, Y

            let tileset = self.texture
                .sampled()
                .magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest);

            uniform! {
                mvp: mvp::model_view_projection(mat4_id, cam, ortho_projection),
                tileset: tileset,
            }
        };

        let mut target = self.display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        target
            .draw(
                &vb,
                &self.indices,
                &self.program,
                &cam_uniforms,
                &Default::default(),
            )
            .unwrap();
        target.finish().unwrap();
    }

    pub fn set<P: PixLike, L: Into<[i32; 2]>>(&mut self, screen_loc: units::ScreenTile2D, tile: console::Tile<P>) {
        let coords = tile.pix.get();
        self.vertex_buffer.set(units::ScreenTile2D::from(screen_loc.into()), tile, coords);
    }

    pub fn blit_console<P: PixLike>(
        &mut self,
        screen_loc: units::ScreenTile2D,
        console: &console::Console<P>,
    ) {
        // TODO iter ?
        for y in 0..console.get_height() {
            for x in 0..console.get_width() {
                let loc = screen_loc + units::ScreenTile2D::new(x as i32, y as i32);
                let tile = console.get_tile(x, y);
                let coords = tile.pix.get();
                self.vertex_buffer.set(loc, tile, coords)
            }
        }
    }
}

fn program(display: &Display) -> glium::Program {
    glium::Program::from_source(
        display as &glium::backend::Facade,
        &shaders::VERTEX,
        &shaders::FRAGMENT,
        None,
    ).unwrap()
}

fn indices(display: &Display, size: units::Size2D) -> glium::IndexBuffer<u16> {
    use glium::index::PrimitiveType;

    let indices = utils::indices((size.width * size.height) as usize);
    glium::IndexBuffer::new(
        display as &glium::backend::Facade,
        PrimitiveType::TrianglesList,
        &indices,
    ).unwrap()
}

fn texture(display: &Display, tileset: &[u8]) -> glium::texture::Texture2d {
    use glium::{backend, texture};

    let image = utils::read_png_to_image(tileset);
    let image_dimensions = image.dimensions();
    let texture = texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions);
    texture::Texture2d::new(display as &backend::Facade, texture).unwrap()
}
<|endoftext|>


<commit_before>use super::prelude::*;

use crate::middleware::current_user::TrustedUserId;
use crate::models::{ApiToken, User};
use crate::util::errors::{internal, AppError, AppResult, ChainError, Unauthorized};

#[derive(Debug)]
pub struct AuthenticatedUser {
    user_id: i32,
    token_id: Option<i32>,
}

impl AuthenticatedUser {
    pub fn user_id(&self) -> i32 {
        self.user_id
    }

    pub fn api_token_id(&self) -> Option<i32> {
        self.token_id
    }

    pub fn find_user(&self, conn: &PgConnection) -> AppResult<User> {
        User::find(conn, self.user_id())
            .chain_error(|| internal("user_id from cookie or token not found in database"))
    }
}

impl<'a> UserAuthenticationExt for dyn Request + 'a {
    /// Obtain `AuthenticatedUser` for the request or return an `Unauthorized` error
    fn authenticate(&self, conn: &PgConnection) -> AppResult<AuthenticatedUser> {
        if let Some(id) = self.extensions().find::<TrustedUserId>() {
            // A trusted user_id was provided by a signed cookie (or a test `MockCookieUser`)
            Ok(AuthenticatedUser {
                user_id: id.0,
                token_id: None,
            })
        } else {
            // Otherwise, look for an `Authorization` header on the request
            if let Some(headers) = self.headers().find("Authorization") {
                ApiToken::find_by_api_token(conn, headers[0])
                    .map(|token| AuthenticatedUser {
                        user_id: token.user_id,
                        token_id: Some(token.id),
                    })
                    // Convert a NotFound (or other database error) into Unauthorized
                    .map_err(|_| Box::new(Unauthorized) as Box<dyn AppError>)
            } else {
                // Unable to authenticate the user
                Err(Box::new(Unauthorized))
            }
        }
    }
}
<commit_msg>Add some error chaining to log more on auth failure<commit_after>use super::prelude::*;

use crate::middleware::current_user::TrustedUserId;
use crate::models::{ApiToken, User};
use crate::util::errors::{internal, AppError, AppResult, ChainError, Unauthorized};

#[derive(Debug)]
pub struct AuthenticatedUser {
    user_id: i32,
    token_id: Option<i32>,
}

impl AuthenticatedUser {
    pub fn user_id(&self) -> i32 {
        self.user_id
    }

    pub fn api_token_id(&self) -> Option<i32> {
        self.token_id
    }

    pub fn find_user(&self, conn: &PgConnection) -> AppResult<User> {
        User::find(conn, self.user_id())
            .chain_error(|| internal("user_id from cookie or token not found in database"))
    }
}

impl<'a> UserAuthenticationExt for dyn Request + 'a {
    /// Obtain `AuthenticatedUser` for the request or return an `Unauthorized` error
    fn authenticate(&self, conn: &PgConnection) -> AppResult<AuthenticatedUser> {
        if let Some(id) = self.extensions().find::<TrustedUserId>() {
            // A trusted user_id was provided by a signed cookie (or a test `MockCookieUser`)
            Ok(AuthenticatedUser {
                user_id: id.0,
                token_id: None,
            })
        } else {
            // Otherwise, look for an `Authorization` header on the request
            if let Some(headers) = self.headers().find("Authorization") {
                ApiToken::find_by_api_token(conn, headers[0])
                    .map(|token| AuthenticatedUser {
                        user_id: token.user_id,
                        token_id: Some(token.id),
                    })
                    .chain_error(|| internal("invalid token"))
                    .chain_error(|| Box::new(Unauthorized) as Box<dyn AppError>)
            } else {
                // Unable to authenticate the user
                Err(internal("no cookie session or auth header found"))
                    .chain_error(|| Box::new(Unauthorized) as Box<dyn AppError>)
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Determining which types for which we can emit `#[derive(Debug)]`.

use super::{ConstrainResult, MonotoneFramework};
use std::collections::HashSet;
use std::collections::HashMap;
use ir::context::{BindgenContext, ItemId};
use ir::item::IsOpaque;
use ir::traversal::EdgeKind;
use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
use ir::ty::TypeKind;
use ir::comp::Field;
use ir::traversal::Trace;
use ir::comp::FieldMethods;
use ir::layout::Layout;
use ir::derive::CanTriviallyDeriveDebug;
use ir::comp::CompKind;

/// An analysis that finds for each IR item whether debug cannot be derived.
///
/// We use the monotone constraint function `cannot_derive_debug`, defined as
/// follows:
///
/// * If T is Opaque and layout of the type is known, get this layout as opaque
///   type and check whether it can be derived using trivial checks.
/// * If T is Array type, debug cannot be derived if the length of the array is
///   larger than the limit or the type of data the array contains cannot derive
///   debug.
/// * If T is a type alias, a templated alias or an indirection to another type,
///   debug cannot be derived if the type T refers to cannot be derived debug.
/// * If T is a compound type, debug cannot be derived if any of its base member
///   or field cannot be derived debug.
/// * If T is a pointer, T cannot be derived debug if T is a function pointer
///   and the function signature cannot be derived debug.
/// * If T is an instantiation of an abstract template definition, T cannot be
///   derived debug if any of the template arguments or template definition
///   cannot derive debug.
#[derive(Debug, Clone)]
pub struct CannotDeriveDebug<'ctx, 'gen>
    where 'gen: 'ctx
{
    ctx: &'ctx BindgenContext<'gen>,

    // The incremental result of this analysis's computation. Everything in this
    // set cannot derive debug.
    cannot_derive_debug: HashSet<ItemId>,

    // Dependencies saying that if a key ItemId has been inserted into the
    // `cannot_derive_debug` set, then each of the ids in Vec<ItemId> need to be
    // considered again.
    //
    // This is a subset of the natural IR graph with reversed edges, where we
    // only include the edges from the IR graph that can affect whether a type
    // can derive debug or not.
    dependencies: HashMap<ItemId, Vec<ItemId>>,
}

impl<'ctx, 'gen> CannotDeriveDebug<'ctx, 'gen> {
    fn consider_edge(kind: EdgeKind) -> bool {
        match kind {
            // These are the only edges that can affect whether a type can derive
            // debug or not.
            EdgeKind::BaseMember |
            EdgeKind::Field |
            EdgeKind::TypeReference |
            EdgeKind::VarType |
            EdgeKind::TemplateArgument |
            EdgeKind::TemplateDeclaration |
            EdgeKind::TemplateParameterDefinition => true,

            EdgeKind::Constructor |
            EdgeKind::Destructor |
            EdgeKind::FunctionReturn |
            EdgeKind::FunctionParameter |
            EdgeKind::InnerType |
            EdgeKind::InnerVar |
            EdgeKind::Method => false,
            EdgeKind::Generic => false,
        }
    }

    fn insert(&mut self, id: ItemId) -> ConstrainResult {
        let was_not_already_in_set = self.cannot_derive_debug.insert(id);
        assert!(
            was_not_already_in_set,
            "We shouldn't try and insert {:?} twice because if it was \
             already in the set, `constrain` should have exited early.",
            id
        );
        ConstrainResult::Changed
    }
}

impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
    type Node = ItemId;
    type Extra = &'ctx BindgenContext<'gen>;
    type Output = HashSet<ItemId>;

    fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveDebug<'ctx, 'gen> {
        let cannot_derive_debug = HashSet::new();
        let mut dependencies = HashMap::new();

        for &item in ctx.whitelisted_items() {
            dependencies.entry(item).or_insert(vec![]);

            {
                // We reverse our natural IR graph edges to find dependencies
                // between nodes.
                item.trace(ctx, &mut |sub_item: ItemId, edge_kind| {
                    if ctx.whitelisted_items().contains(&sub_item) &&
                       Self::consider_edge(edge_kind) {
                           dependencies.entry(sub_item)
                               .or_insert(vec![])
                               .push(item);
                    }
                }, &());
            }
        }

        CannotDeriveDebug {
            ctx,
            cannot_derive_debug,
            dependencies,
        }
    }

    fn initial_worklist(&self) -> Vec<ItemId> {
        self.ctx.whitelisted_items().iter().cloned().collect()
    }

    fn constrain(&mut self, id: ItemId) -> ConstrainResult {
        if self.cannot_derive_debug.contains(&id) {
            return ConstrainResult::Same;
        }

        let item = self.ctx.resolve_item(id);
        let ty = match item.as_type() {
            None => return ConstrainResult::Same,
            Some(ty) => ty
        };

        match *ty.kind() {
            // Handle the simple cases. These can derive debug without further
            // information.
            TypeKind::Void |
            TypeKind::NullPtr |
            TypeKind::Int(..) |
            TypeKind::Float(..) |
            TypeKind::Complex(..) |
            TypeKind::Function(..) |
            TypeKind::Enum(..) |
            TypeKind::Reference(..) |
            TypeKind::BlockPointer |
            TypeKind::Named |
            TypeKind::UnresolvedTypeRef(..) |
            TypeKind::ObjCInterface(..) |
            TypeKind::ObjCId |
            TypeKind::ObjCSel => {
                ConstrainResult::Same
            },

            TypeKind::Opaque => {
                if ty.layout(self.ctx)
                    .map_or(true, |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
                        ConstrainResult::Same
                    } else {
                        self.insert(id)
                    }
            },

            TypeKind::Array(t, len) => {
                if self.cannot_derive_debug.contains(&t) {
                    return self.insert(id);
                }

                if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
                    ConstrainResult::Same
                } else {
                    self.insert(id)
                }
            },

            TypeKind::ResolvedTypeRef(t) |
            TypeKind::TemplateAlias(t, _) |
            TypeKind::Alias(t) => {
                if self.cannot_derive_debug.contains(&t) {
                    self.insert(id)
                } else {
                    ConstrainResult::Same
                }
            },

            TypeKind::Comp(ref info) => {
                if info.has_non_type_template_params() {
                    if ty.layout(self.ctx)
                        .map_or(true,
                                |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
                        return ConstrainResult::Same;
                    } else {
                        return self.insert(id);
                    }
                }

                if info.kind() == CompKind::Union {
                    if self.ctx.options().unstable_rust {
                        return self.insert(id);
                    }

                    if ty.layout(self.ctx)
                        .map_or(true,
                                |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
                        return ConstrainResult::Same;
                    } else {
                        return self.insert(id);
                    }
                }

                let bases_cannot_derive = info.base_members()
                    .iter()
                    .any(|base| self.cannot_derive_debug.contains(&base.ty));
                if bases_cannot_derive {
                    return self.insert(id);
                }

                let fields_cannot_derive = info.fields()
                    .iter()
                    .any(|f| {
                        match *f {
                            Field::DataMember(ref data) => {
                                self.cannot_derive_debug.contains(&data.ty())
                            }
                            Field::Bitfields(ref bfu) => {
                                bfu.bitfields()
                                    .iter().any(|b| {
                                        self.cannot_derive_debug.contains(&b.ty())
                                    })
                            }
                        }
                    });
                if fields_cannot_derive {
                    return self.insert(id);
                }

                ConstrainResult::Same
            },

            TypeKind::Pointer(inner) => {
                let inner_type = self.ctx.resolve_type(inner).canonical_type(self.ctx);
                if let TypeKind::Function(ref sig) = *inner_type.kind() {
                    if !sig.can_trivially_derive_debug(&self.ctx, ()) {
                        return self.insert(id);
                    }
                }
                ConstrainResult::Same
            },

            TypeKind::TemplateInstantiation(ref template) => {
                let args_cannot_derive = template.template_arguments()
                    .iter()
                    .any(|arg| self.cannot_derive_debug.contains(&arg));
                if args_cannot_derive {
                    return self.insert(id);
                }

                let template_definition = template.template_definition()
                    .into_resolver()
                    .through_type_refs()
                    .through_type_aliases()
                    .resolve(self.ctx);

                let ty_cannot_derive = template_definition
                    .as_type()
                    .expect("Instantiations of a non-type?")
                    .as_comp()
                    .and_then(|c| {
                        // For non-type template parameters, or opaque template
                        // definitions, we generate an opaque blob, and in this
                        // case the instantiation has a better idea of the
                        // layout than the definition does.
                        if template_definition.is_opaque(self.ctx, &()) ||
                            c.has_non_type_template_params() {
                            let opaque = ty.layout(self.ctx)
                                .or_else(|| {
                                    self.ctx
                                        .resolve_type(template.template_definition())
                                        .layout(self.ctx)
                                })
                                .unwrap_or(Layout::zero())
                                .opaque();
                            Some(!opaque.can_trivially_derive_debug(&self.ctx, ()))
                        } else {
                            None
                        }
                    })
                    .unwrap_or_else(|| {
                        self.cannot_derive_debug.contains(&template.template_definition())
                    });
                if ty_cannot_derive {
                    return self.insert(id);
                }

                ConstrainResult::Same
            },
        }
    }

    fn each_depending_on<F>(&self, id: ItemId, mut f: F)
        where F: FnMut(ItemId),
    {
        if let Some(edges) = self.dependencies.get(&id) {
            for item in edges {
                trace!("enqueue {:?} into worklist", item);
                f(*item);
            }
        }
    }
}

impl<'ctx, 'gen> From<CannotDeriveDebug<'ctx, 'gen>> for HashSet<ItemId> {
    fn from(analysis: CannotDeriveDebug<'ctx, 'gen>) -> Self {
        analysis.cannot_derive_debug
    }
}
<commit_msg>Handle all opaque types at once in derive(Debug) analysis<commit_after>//! Determining which types for which we can emit `#[derive(Debug)]`.

use super::{ConstrainResult, MonotoneFramework};
use std::collections::HashSet;
use std::collections::HashMap;
use ir::context::{BindgenContext, ItemId};
use ir::item::IsOpaque;
use ir::traversal::EdgeKind;
use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
use ir::ty::TypeKind;
use ir::comp::Field;
use ir::traversal::Trace;
use ir::comp::FieldMethods;
use ir::derive::CanTriviallyDeriveDebug;
use ir::comp::CompKind;

/// An analysis that finds for each IR item whether debug cannot be derived.
///
/// We use the monotone constraint function `cannot_derive_debug`, defined as
/// follows:
///
/// * If T is Opaque and layout of the type is known, get this layout as opaque
///   type and check whether it can be derived using trivial checks.
/// * If T is Array type, debug cannot be derived if the length of the array is
///   larger than the limit or the type of data the array contains cannot derive
///   debug.
/// * If T is a type alias, a templated alias or an indirection to another type,
///   debug cannot be derived if the type T refers to cannot be derived debug.
/// * If T is a compound type, debug cannot be derived if any of its base member
///   or field cannot be derived debug.
/// * If T is a pointer, T cannot be derived debug if T is a function pointer
///   and the function signature cannot be derived debug.
/// * If T is an instantiation of an abstract template definition, T cannot be
///   derived debug if any of the template arguments or template definition
///   cannot derive debug.
#[derive(Debug, Clone)]
pub struct CannotDeriveDebug<'ctx, 'gen>
    where 'gen: 'ctx
{
    ctx: &'ctx BindgenContext<'gen>,

    // The incremental result of this analysis's computation. Everything in this
    // set cannot derive debug.
    cannot_derive_debug: HashSet<ItemId>,

    // Dependencies saying that if a key ItemId has been inserted into the
    // `cannot_derive_debug` set, then each of the ids in Vec<ItemId> need to be
    // considered again.
    //
    // This is a subset of the natural IR graph with reversed edges, where we
    // only include the edges from the IR graph that can affect whether a type
    // can derive debug or not.
    dependencies: HashMap<ItemId, Vec<ItemId>>,
}

impl<'ctx, 'gen> CannotDeriveDebug<'ctx, 'gen> {
    fn consider_edge(kind: EdgeKind) -> bool {
        match kind {
            // These are the only edges that can affect whether a type can derive
            // debug or not.
            EdgeKind::BaseMember |
            EdgeKind::Field |
            EdgeKind::TypeReference |
            EdgeKind::VarType |
            EdgeKind::TemplateArgument |
            EdgeKind::TemplateDeclaration |
            EdgeKind::TemplateParameterDefinition => true,

            EdgeKind::Constructor |
            EdgeKind::Destructor |
            EdgeKind::FunctionReturn |
            EdgeKind::FunctionParameter |
            EdgeKind::InnerType |
            EdgeKind::InnerVar |
            EdgeKind::Method => false,
            EdgeKind::Generic => false,
        }
    }

    fn insert(&mut self, id: ItemId) -> ConstrainResult {
        let was_not_already_in_set = self.cannot_derive_debug.insert(id);
        assert!(
            was_not_already_in_set,
            "We shouldn't try and insert {:?} twice because if it was \
             already in the set, `constrain` should have exited early.",
            id
        );
        ConstrainResult::Changed
    }
}

impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
    type Node = ItemId;
    type Extra = &'ctx BindgenContext<'gen>;
    type Output = HashSet<ItemId>;

    fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveDebug<'ctx, 'gen> {
        let cannot_derive_debug = HashSet::new();
        let mut dependencies = HashMap::new();

        for &item in ctx.whitelisted_items() {
            dependencies.entry(item).or_insert(vec![]);

            {
                // We reverse our natural IR graph edges to find dependencies
                // between nodes.
                item.trace(ctx, &mut |sub_item: ItemId, edge_kind| {
                    if ctx.whitelisted_items().contains(&sub_item) &&
                       Self::consider_edge(edge_kind) {
                           dependencies.entry(sub_item)
                               .or_insert(vec![])
                               .push(item);
                    }
                }, &());
            }
        }

        CannotDeriveDebug {
            ctx,
            cannot_derive_debug,
            dependencies,
        }
    }

    fn initial_worklist(&self) -> Vec<ItemId> {
        self.ctx.whitelisted_items().iter().cloned().collect()
    }

    fn constrain(&mut self, id: ItemId) -> ConstrainResult {
        if self.cannot_derive_debug.contains(&id) {
            return ConstrainResult::Same;
        }

        let item = self.ctx.resolve_item(id);
        let ty = match item.as_type() {
            None => return ConstrainResult::Same,
            Some(ty) => ty
        };

        if ty.is_opaque(self.ctx, item) {
            let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
                l.opaque().can_trivially_derive_debug(self.ctx, ())
            });
            if layout_can_derive {
                return ConstrainResult::Same;
            } else {
                return self.insert(id);
            }
        }

        match *ty.kind() {
            // Handle the simple cases. These can derive debug without further
            // information.
            TypeKind::Void |
            TypeKind::NullPtr |
            TypeKind::Int(..) |
            TypeKind::Float(..) |
            TypeKind::Complex(..) |
            TypeKind::Function(..) |
            TypeKind::Enum(..) |
            TypeKind::Reference(..) |
            TypeKind::BlockPointer |
            TypeKind::Named |
            TypeKind::UnresolvedTypeRef(..) |
            TypeKind::ObjCInterface(..) |
            TypeKind::ObjCId |
            TypeKind::ObjCSel => {
                ConstrainResult::Same
            }

            TypeKind::Array(t, len) => {
                if self.cannot_derive_debug.contains(&t) {
                    return self.insert(id);
                }

                if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
                    ConstrainResult::Same
                } else {
                    self.insert(id)
                }
            }

            TypeKind::ResolvedTypeRef(t) |
            TypeKind::TemplateAlias(t, _) |
            TypeKind::Alias(t) => {
                if self.cannot_derive_debug.contains(&t) {
                    self.insert(id)
                } else {
                    ConstrainResult::Same
                }
            }

            TypeKind::Comp(ref info) => {
                assert!(
                    !info.has_non_type_template_params(),
                    "The early ty.is_opaque check should have handled this case"
                );

                if info.kind() == CompKind::Union {
                    if self.ctx.options().unstable_rust {
                        return self.insert(id);
                    }

                    if ty.layout(self.ctx)
                        .map_or(true,
                                |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
                        return ConstrainResult::Same;
                    } else {
                        return self.insert(id);
                    }
                }

                let bases_cannot_derive = info.base_members()
                    .iter()
                    .any(|base| self.cannot_derive_debug.contains(&base.ty));
                if bases_cannot_derive {
                    return self.insert(id);
                }

                let fields_cannot_derive = info.fields()
                    .iter()
                    .any(|f| {
                        match *f {
                            Field::DataMember(ref data) => {
                                self.cannot_derive_debug.contains(&data.ty())
                            }
                            Field::Bitfields(ref bfu) => {
                                bfu.bitfields()
                                    .iter().any(|b| {
                                        self.cannot_derive_debug.contains(&b.ty())
                                    })
                            }
                        }
                    });
                if fields_cannot_derive {
                    return self.insert(id);
                }

                ConstrainResult::Same
            }

            TypeKind::Pointer(inner) => {
                let inner_type = self.ctx.resolve_type(inner).canonical_type(self.ctx);
                if let TypeKind::Function(ref sig) = *inner_type.kind() {
                    if !sig.can_trivially_derive_debug(&self.ctx, ()) {
                        return self.insert(id);
                    }
                }
                ConstrainResult::Same
            }

            TypeKind::TemplateInstantiation(ref template) => {
                let args_cannot_derive = template.template_arguments()
                    .iter()
                    .any(|arg| self.cannot_derive_debug.contains(&arg));
                if args_cannot_derive {
                    return self.insert(id);
                }

                assert!(
                    !template.template_definition().is_opaque(self.ctx, &()),
                    "The early ty.is_opaque check should have handled this case"
                );
                let def_cannot_derive = self.cannot_derive_debug
                    .contains(&template.template_definition());
                if def_cannot_derive {
                    return self.insert(id);
                }

                ConstrainResult::Same
            }

            TypeKind::Opaque => {
                unreachable!(
                    "The early ty.is_opaque check should have handled this case"
                )
            }
        }
    }

    fn each_depending_on<F>(&self, id: ItemId, mut f: F)
        where F: FnMut(ItemId),
    {
        if let Some(edges) = self.dependencies.get(&id) {
            for item in edges {
                trace!("enqueue {:?} into worklist", item);
                f(*item);
            }
        }
    }
}

impl<'ctx, 'gen> From<CannotDeriveDebug<'ctx, 'gen>> for HashSet<ItemId> {
    fn from(analysis: CannotDeriveDebug<'ctx, 'gen>) -> Self {
        analysis.cannot_derive_debug
    }
}
<|endoftext|>


<commit_before>use std::option::Option;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

//pub struct Format {
//}

pub struct Row {
    cells: Vec<CellType>
}

pub struct Table {
    rows: Vec<Row>
}

trait ISet {
    fn size(&self) -> usize;
    fn add(&mut self, row: Row);
    fn remove(&mut self, index: usize); // FIXME
}
<commit_msg>Try to implement format<commit_after>use std::option::Option;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

pub enum CellMetatype {
    tInt32
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

trait Metaformat<T> {
    fn construct(type: CellMetatype, name: String) -> T;
}

pub struct CellFormat {
    name: String,
    type: CellMetatype
}

pub struct Cell {
    value: CellType
}

pub impl Metaformat<Cell> for Cell {
    fn construct(type: CellMetatype, name: String) -> Cell {
        return match type {
            CellMetatype::tInt32 => Cell { value: None, name: name }
        }
    }
}

pub struct Row {
    cells: Vec<CellType>
}

pub struct Table {
    rows: Vec<Row>
}

trait ISet {
    fn size(&self) -> usize;
    fn add(&mut self, row: Row);
    fn remove(&mut self, index: usize); // FIXME
}
<|endoftext|>